Browse Source

esp_adc: new esp_adc component and adc drivers

Armando 3 years ago
parent
commit
5b523a3313
100 changed files with 5871 additions and 4103 deletions
  1. 1 1
      .gitlab/CODEOWNERS
  2. 9 12
      components/driver/CMakeLists.txt
  3. 50 9
      components/driver/Kconfig
  4. 0 640
      components/driver/adc_deprecated.c
  5. 0 0
      components/driver/deprecated/adc1_private.h
  6. 117 471
      components/driver/deprecated/adc_dma_legacy.c
  7. 252 0
      components/driver/deprecated/adc_i2s_deprecated.c
  8. 360 175
      components/driver/deprecated/adc_legacy.c
  9. 16 306
      components/driver/deprecated/driver/adc.h
  10. 0 163
      components/driver/deprecated/driver/adc_deprecated.h
  11. 51 0
      components/driver/deprecated/driver/adc_i2s_legacy.h
  12. 0 203
      components/driver/deprecated/driver/adc_types_deprecated.h
  13. 128 0
      components/driver/deprecated/driver/adc_types_legacy.h
  14. 4 2
      components/driver/deprecated/i2s_legacy.c
  15. 0 77
      components/driver/esp32/adc.c
  16. 0 135
      components/driver/esp32s2/adc.c
  17. 1 0
      components/driver/i2s/i2s_common.c
  18. 0 11
      components/driver/include/driver/adc_common.h
  19. 0 32
      components/driver/include/esp_private/adc_cali.h
  20. 2 2
      components/driver/test/CMakeLists.txt
  21. 0 654
      components/driver/test/adc_dma_test/test_esp32s2.c
  22. 0 1
      components/driver/test/dac_dma_test/test_esp32s2.c
  23. 1 1
      components/driver/test/include/test/test_common_adc.h
  24. 0 608
      components/driver/test/test_adc.c
  25. 4 3
      components/driver/test/test_adc2_with_wifi.c
  26. 0 394
      components/driver/test/test_adc_common.c
  27. 2 1
      components/driver/test/test_dac.c
  28. 0 1
      components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/main/test_i2s_dac.c
  29. 1 0
      components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/sdkconfig.defaults
  30. 1 0
      components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/sdkconfig.defaults
  31. 5 0
      components/driver/test_apps/legacy_adc_driver/CMakeLists.txt
  32. 2 0
      components/driver/test_apps/legacy_adc_driver/README.md
  33. 5 0
      components/driver/test_apps/legacy_adc_driver/main/CMakeLists.txt
  34. 40 0
      components/driver/test_apps/legacy_adc_driver/main/test_app_main.c
  35. 129 0
      components/driver/test_apps/legacy_adc_driver/main/test_legacy_adc.c
  36. 24 0
      components/driver/test_apps/legacy_adc_driver/pytest_legacy_adc.py
  37. 5 0
      components/driver/test_apps/legacy_adc_driver/sdkconfig.ci.release
  38. 3 0
      components/driver/test_apps/legacy_adc_driver/sdkconfig.defaults
  39. 2 1
      components/efuse/esp32c3/esp_efuse_rtc_calib.c
  40. 2 1
      components/efuse/esp32c3/include/esp_efuse_rtc_calib.h
  41. 39 0
      components/esp_adc/CMakeLists.txt
  42. 47 0
      components/esp_adc/Kconfig
  43. 45 0
      components/esp_adc/adc_cali.c
  44. 247 0
      components/esp_adc/adc_cali_curve_fitting.c
  45. 208 0
      components/esp_adc/adc_common.c
  46. 630 0
      components/esp_adc/adc_continuous.c
  47. 87 0
      components/esp_adc/adc_lock.c
  48. 260 0
      components/esp_adc/adc_oneshot.c
  49. 33 0
      components/esp_adc/curve_fitting_coefficients.h
  50. 4 3
      components/esp_adc/deprecated/esp32/esp_adc_cal_legacy.c
  51. 11 7
      components/esp_adc/deprecated/esp32c3/esp_adc_cal_legacy.c
  52. 3 2
      components/esp_adc/deprecated/esp32s2/esp_adc_cal_legacy.c
  53. 4 3
      components/esp_adc/deprecated/esp32s3/esp_adc_cal_legacy.c
  54. 9 2
      components/esp_adc/deprecated/esp_adc_cal_common_legacy.c
  55. 0 0
      components/esp_adc/deprecated/esp_adc_cal_internal_legacy.h
  56. 12 34
      components/esp_adc/deprecated/include/esp_adc_cal.h
  57. 50 0
      components/esp_adc/deprecated/include/esp_adc_cal_types_legacy.h
  58. 435 0
      components/esp_adc/esp32/adc_cali_line_fitting.c
  59. 15 0
      components/esp_adc/esp32/include/adc_cali_schemes.h
  60. 15 0
      components/esp_adc/esp32c2/include/adc_cali_schemes.h
  61. 11 5
      components/esp_adc/esp32c3/adc2_init_cal.c
  62. 36 0
      components/esp_adc/esp32c3/curve_fitting_coefficients.c
  63. 15 0
      components/esp_adc/esp32c3/include/adc_cali_schemes.h
  64. 15 0
      components/esp_adc/esp32h2/include/adc_cali_schemes.h
  65. 11 5
      components/esp_adc/esp32s2/adc2_init_cal.c
  66. 255 0
      components/esp_adc/esp32s2/adc_cali_line_fitting.c
  67. 15 0
      components/esp_adc/esp32s2/include/adc_cali_schemes.h
  68. 48 0
      components/esp_adc/esp32s3/curve_fitting_coefficients.c
  69. 15 0
      components/esp_adc/esp32s3/include/adc_cali_schemes.h
  70. 59 0
      components/esp_adc/include/esp_adc/adc_cali.h
  71. 135 0
      components/esp_adc/include/esp_adc/adc_cali_scheme.h
  72. 232 0
      components/esp_adc/include/esp_adc/adc_continuous.h
  73. 130 0
      components/esp_adc/include/esp_adc/adc_oneshot.h
  74. 5 4
      components/esp_adc/include/esp_private/adc2_wifi.h
  75. 60 0
      components/esp_adc/include/esp_private/adc_lock.h
  76. 130 0
      components/esp_adc/include/esp_private/adc_private.h
  77. 46 0
      components/esp_adc/interface/adc_cali_interface.h
  78. 5 0
      components/esp_adc/linker.lf
  79. 20 0
      components/esp_adc/test_apps/adc/CMakeLists.txt
  80. 2 0
      components/esp_adc/test_apps/adc/README.md
  81. 11 0
      components/esp_adc/test_apps/adc/main/CMakeLists.txt
  82. 260 0
      components/esp_adc/test_apps/adc/main/test_adc.c
  83. 128 0
      components/esp_adc/test_apps/adc/main/test_adc_driver.c
  84. 266 0
      components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c
  85. 298 0
      components/esp_adc/test_apps/adc/main/test_adc_performance.c
  86. 40 0
      components/esp_adc/test_apps/adc/main/test_app_main.c
  87. 94 0
      components/esp_adc/test_apps/adc/main/test_common_adc.c
  88. 107 0
      components/esp_adc/test_apps/adc/main/test_common_adc.h
  89. 21 0
      components/esp_adc/test_apps/adc/pytest_adc.py
  90. 6 0
      components/esp_adc/test_apps/adc/sdkconfig.ci.iram_safe
  91. 3 0
      components/esp_adc/test_apps/adc/sdkconfig.ci.release
  92. 2 0
      components/esp_adc/test_apps/adc/sdkconfig.defaults
  93. 0 12
      components/esp_adc_cal/CMakeLists.txt
  94. 0 31
      components/esp_adc_cal/Kconfig
  95. 1 1
      components/esp_phy/CMakeLists.txt
  96. 2 1
      components/esp_phy/src/phy_override.c
  97. 1 1
      components/esp_wifi/CMakeLists.txt
  98. 1 0
      components/esp_wifi/src/wifi_init.c
  99. 5 3
      components/hal/CMakeLists.txt
  100. 9 85
      components/hal/adc_hal.c

+ 1 - 1
.gitlab/CODEOWNERS

@@ -77,7 +77,7 @@
 /components/cxx/                      @esp-idf-codeowners/system
 /components/driver/                   @esp-idf-codeowners/peripherals
 /components/efuse/                    @esp-idf-codeowners/system
-/components/esp_adc_cal/              @esp-idf-codeowners/peripherals
+/components/esp_adc/                  @esp-idf-codeowners/peripherals
 /components/esp_common/               @esp-idf-codeowners/system
 /components/esp_eth/                  @esp-idf-codeowners/network
 /components/esp_event/                @esp-idf-codeowners/system

+ 9 - 12
components/driver/CMakeLists.txt

@@ -24,9 +24,11 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target}/include")
 endif()
 
 if(CONFIG_SOC_ADC_SUPPORTED)
-    list(APPEND srcs
-         "adc_single.c"
-         "adc.c")
+    list(APPEND srcs "deprecated/adc_legacy.c")
+endif()
+
+if(CONFIG_SOC_ADC_DMA_SUPPORTED)
+    list(APPEND srcs "deprecated/adc_dma_legacy.c")
 endif()
 
 if(CONFIG_SOC_MCPWM_SUPPORTED)
@@ -87,8 +89,7 @@ if(${target} STREQUAL "esp32")
                      "sdio_slave.c"
                      "touch_sensor_common.c"
                      "esp32/touch_sensor.c"
-                     "esp32/adc.c"
-                     "adc_deprecated.c"
+                     "deprecated/adc_i2s_deprecated.c"
                      "esp32/dac.c")
 endif()
 
@@ -96,9 +97,6 @@ if(${target} STREQUAL "esp32s2")
     list(APPEND srcs "dac_common.c"
                      "touch_sensor_common.c"
                      "esp32s2/touch_sensor.c"
-                     "esp32s2/adc.c"
-                     "adc_deprecated.c"
-                     "esp32s2/adc2_init_cal.c"
                      "esp32s2/dac.c")
 endif()
 
@@ -107,19 +105,18 @@ if(${target} STREQUAL "esp32s3")
                      "esp32s3/touch_sensor.c")
 endif()
 
-if(${target} STREQUAL "esp32c3")
-    list(APPEND srcs "esp32c3/adc2_init_cal.c")
-endif()
 
 if(BOOTLOADER_BUILD)
     # Bootloader shall NOT depend on the drivers
     idf_component_register()
 else()
     # (REQUIRES cannot hide soc headers, since many arguments in the driver headers are chip-dependent)
+    # (Legacy drivers requires `esp_adc`, due to ADC HW resource mutex logics are there.
+    # Can be removed together with legacy drivers)
     idf_component_register(SRCS "${srcs}"
                         INCLUDE_DIRS ${includes}
                         PRIV_INCLUDE_DIRS "include/driver"
-                        PRIV_REQUIRES efuse esp_timer
+                        PRIV_REQUIRES efuse esp_timer esp_adc
                         REQUIRES esp_pm esp_ringbuf freertos soc hal esp_hw_support
                         LDFRAGMENTS linker.lf)
 endif()

+ 50 - 9
components/driver/Kconfig

@@ -1,16 +1,9 @@
 menu "Driver Configurations"
 
-    menu "ADC Configuration"
-
-        config ADC_FORCE_XPD_FSM
-            bool "Use the FSM to control ADC power"
-            default n
-            help
-                ADC power can be controlled by the FSM instead of software. This allows the ADC to
-                be shut off when it is not working leading to lower power consumption. However
-                using the FSM control ADC power will increase the noise of ADC.
+    menu "Legacy ADC Configuration"
 
         config ADC_DISABLE_DAC
+            depends on SOC_DAC_SUPPORTED
             bool "Disable DAC when ADC2 is used on GPIO 25 and 26"
             default y
             help
@@ -19,6 +12,54 @@ menu "Driver Configurations"
 
                 For testing, disable this option so that we can measure the output of DAC by internal ADC.
 
+        config ADC_SUPPRESS_DEPRECATE_WARN
+            bool "Suppress legacy driver deprecated warning"
+            default n
+            help
+                Wether to suppress the deprecation warnings when using legacy adc driver (driver/adc.h).
+                If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
+                you can enable this option.
+
+        menu "Legacy ADC Calibration Configuration"
+
+            config ADC_CAL_EFUSE_TP_ENABLE
+                depends on IDF_TARGET_ESP32
+                bool "Use Two Point Values"
+                default "y"
+                help
+                    Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.
+                    This option will allow the ADC calibration component to characterize the
+                    ADC-Voltage curve using Two Point values if they are available.
+
+            config ADC_CAL_EFUSE_VREF_ENABLE
+                depends on IDF_TARGET_ESP32
+                bool "Use eFuse Vref"
+                default "y"
+                help
+                    Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow
+                    the ADC calibration component to characterize the ADC-Voltage curve using
+                    eFuse Vref if it is available.
+
+            config ADC_CAL_LUT_ENABLE
+                depends on IDF_TARGET_ESP32
+                bool "Use Lookup Tables"
+                default "y"
+                help
+                    This option will allow the ADC calibration component to use Lookup Tables
+                    to correct for non-linear behavior in 11db attenuation. Other attenuations
+                    do not exhibit non-linear behavior hence will not be affected by this option.
+
+            config ADC_CALI_SUPPRESS_DEPRECATE_WARN
+                bool "Suppress legacy driver deprecated warning"
+                default n
+                help
+                    Wether to suppress the deprecation warnings when using legacy adc calibration
+                    driver (esp_adc_cal.h).
+                    If you want to continue using the legacy driver, and don't want to see related
+                    deprecation warnings, you can enable this option.
+
+        endmenu
+
     endmenu  # ADC Configuration
 
     menu "SPI Configuration"

+ 0 - 640
components/driver/adc_deprecated.c

@@ -1,640 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/*----------------------------------------------------------------------------------
-        This file contains ESP32 and ESP32S2 Depricated ADC APIs and functions
------------------------------------------------------------------------------------*/
-
-#include "sdkconfig.h"
-#include "esp_types.h"
-#include "esp_log.h"
-#include "esp_intr_alloc.h"
-#include "driver/rtc_io.h"
-#include "hal/adc_ll.h"
-#include "hal/adc_types.h"
-#include "hal/adc_hal_conf.h"
-#ifdef CONFIG_PM_ENABLE
-#include "esp_pm.h"
-#endif
-#include "adc.h"
-#include "esp_private/adc_cali.h"
-#include "freertos/FreeRTOS.h"
-
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#include "deprecated/driver/adc_types_deprecated.h"
-
-static const char *ADC_TAG = "ADC";
-
-#define ADC_CHECK_RET(fun_ret) ({                  \
-    if (fun_ret != ESP_OK) {                                \
-        ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__);  \
-        return ESP_FAIL;                                    \
-    }                                                       \
-})
-
-#define ADC_CHECK(a, str, ret_val) ({                                               \
-    if (!(a)) {                                                                     \
-        ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str);                \
-        return (ret_val);                                                           \
-    }                                                                               \
-})
-
-#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
-#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
-
-extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
-#define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
-#define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
-
-#ifdef CONFIG_PM_ENABLE
-esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL;
-#endif  //CONFIG_PM_ENABLE
-
-
-#if CONFIG_IDF_TARGET_ESP32
-/*---------------------------------------------------------------
-        ESP32 Depricated ADC APIs and functions
----------------------------------------------------------------*/
-#define ADC_MEAS_NUM_LIM_DEFAULT      (1)
-#define ADC_MAX_MEAS_NUM_DEFAULT      (255)
-#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
-#define DIG_ADC_ATTEN_DEFUALT         (ADC_ATTEN_DB_11)
-#define DIG_ADC_BIT_WIDTH_DEFUALT     (ADC_WIDTH_BIT_12)
-
-esp_err_t adc_digi_init(void)
-{
-    ADC_ENTER_CRITICAL();
-    adc_ll_digi_set_fsm_time(ADC_HAL_FSM_RSTB_WAIT_DEFAULT, ADC_HAL_FSM_START_WAIT_DEFAULT,
-                             ADC_HAL_FSM_STANDBY_WAIT_DEFAULT);
-    adc_ll_set_sample_cycle(ADC_HAL_SAMPLE_CYCLE_DEFAULT);
-    adc_hal_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
-    adc_ll_digi_output_invert(ADC_UNIT_1, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
-    adc_ll_digi_output_invert(ADC_UNIT_2, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
-    adc_ll_digi_set_clk_div(ADC_HAL_DIGI_SAR_CLK_DIV_DEFAULT);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_deinit(void)
-{
-    adc_power_release();
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_deinit(NULL);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * Set adc output 16-bit-data format from digital controller.
- *
- * @param data_sel 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode.
- *                 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode
- * @note see `adc_ll_digi_pattern_table_t` for more detail of data bit width
- */
-static inline void adc_ll_digi_set_output_format(bool data_sel)
-{
-    SYSCON.saradc_ctrl.data_sar_sel = data_sel;
-}
-
-static inline void adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
-{
-    uint32_t tab;
-    uint8_t index = pattern_index / 4;
-    uint8_t offset = (pattern_index % 4) * 8;
-    if (adc_n == ADC_UNIT_1) {
-        tab = SYSCON.saradc_sar1_patt_tab[index];   // Read old register value
-        tab &= (~(0xFF000000 >> offset));           // clear old data
-        tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
-        SYSCON.saradc_sar1_patt_tab[index] = tab;   // Write back
-    } else { // adc_n == ADC_UNIT_2
-        tab = SYSCON.saradc_sar2_patt_tab[index];   // Read old register value
-        tab &= (~(0xFF000000 >> offset));           // clear old data
-        tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
-        SYSCON.saradc_sar2_patt_tab[index] = tab;   // Write back
-    }
-}
-
-void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
-{
-    /* On ESP32, only support ADC1 */
-    switch (cfg->conv_mode) {
-        case ADC_CONV_SINGLE_UNIT_1:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
-            break;
-        case ADC_CONV_SINGLE_UNIT_2:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
-            break;
-        case ADC_CONV_BOTH_UNIT:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
-            break;
-        case ADC_CONV_ALTER_UNIT:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
-            break;
-        default:
-            abort();
-    }
-
-    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
-        adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
-        if (cfg->adc1_pattern_len) {
-            adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
-            adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, cfg->adc1_pattern_len);
-            for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
-                adc_ll_digi_prepare_pattern_table(ADC_UNIT_1, i, cfg->adc1_pattern[i]);
-            }
-        }
-    }
-    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
-        adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_DIG);
-        if (cfg->adc2_pattern_len) {
-            adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
-            adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, cfg->adc2_pattern_len);
-            for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
-                adc_ll_digi_prepare_pattern_table(ADC_UNIT_2, i, cfg->adc2_pattern[i]);
-            }
-        }
-    }
-    adc_ll_digi_set_output_format(cfg->format);
-    if (cfg->conv_limit_en) {
-        adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
-        adc_ll_digi_convert_limit_enable();
-    } else {
-        adc_ll_digi_convert_limit_disable();
-    }
-    adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
-}
-
-esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
-{
-    adc_power_acquire();
-    ADC_ENTER_CRITICAL();
-    adc_digi_controller_reg_set(config);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
-{
-    ADC_CHECK(src < ADC_I2S_DATA_SRC_MAX, "ADC i2s data source error", ESP_ERR_INVALID_ARG);
-    ADC_ENTER_CRITICAL();
-    adc_ll_digi_set_data_source(src);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
-esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
-{
-    if (adc_unit == ADC_UNIT_1) {
-        ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_UNIT_1)), "ADC1 not support DMA for now.", ESP_ERR_INVALID_ARG);
-        ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
-    } else if (adc_unit == ADC_UNIT_2) {
-        //ADC2 does not support DMA mode
-        ADC_CHECK((SOC_ADC_SUPPORT_DMA_MODE(ADC_UNIT_2)), "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
-        ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
-    }
-
-    adc_digi_pattern_table_t adc1_pattern[1];
-    adc_digi_pattern_table_t adc2_pattern[1];
-    adc_digi_config_t dig_cfg = {
-        .conv_limit_en = ADC_MEAS_NUM_LIM_DEFAULT,
-        .conv_limit_num = ADC_MAX_MEAS_NUM_DEFAULT,
-        .format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
-        .conv_mode = ADC_CONV_SINGLE_UNIT_1,
-    };
-
-    if (adc_unit == ADC_UNIT_1) {
-        adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
-        adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
-        adc1_pattern[0].channel = channel;
-        dig_cfg.adc1_pattern_len = 1;
-        dig_cfg.adc1_pattern = adc1_pattern;
-    } else if (adc_unit == ADC_UNIT_2) {
-        adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
-        adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
-        adc2_pattern[0].channel = channel;
-        dig_cfg.adc2_pattern_len = 1;
-        dig_cfg.adc2_pattern = adc2_pattern;
-    }
-    adc_common_gpio_init(adc_unit, channel);
-    ADC_ENTER_CRITICAL();
-    adc_ll_digi_set_fsm_time(ADC_HAL_FSM_RSTB_WAIT_DEFAULT, ADC_HAL_FSM_START_WAIT_DEFAULT,
-                             ADC_HAL_FSM_STANDBY_WAIT_DEFAULT);
-    adc_ll_set_sample_cycle(ADC_HAL_SAMPLE_CYCLE_DEFAULT);
-    adc_hal_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
-    adc_ll_digi_output_invert(ADC_UNIT_1, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
-    adc_ll_digi_output_invert(ADC_UNIT_2, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
-    adc_ll_digi_set_clk_div(ADC_HAL_DIGI_SAR_CLK_DIV_DEFAULT);
-    adc_digi_controller_reg_set(&dig_cfg);
-    ADC_EXIT_CRITICAL();
-
-    return ESP_OK;
-}
-
-#endif  //#if CONFIG_IDF_TARGET_ESP32
-
-#if CONFIG_IDF_TARGET_ESP32S2
-/*---------------------------------------------------------------
-            ESP32S2 Depricated ADC functions and APIs
----------------------------------------------------------------*/
-esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
-{
-    if (adc_unit == ADC_UNIT_1) {
-        return ESP_ERR_NOT_SUPPORTED;
-    }
-    ADC_ENTER_CRITICAL();
-    adc_hal_arbiter_config(config);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * Enable interrupt of adc digital controller by bitmask.
- *
- * @param adc_n ADC unit.
- * @param intr Interrupt bitmask.
- */
-static inline void adc_ll_digi_intr_enable(adc_unit_t adc_n, adc_digi_intr_t intr)
-{
-    if (adc_n == ADC_UNIT_1) {
-        if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
-            APB_SARADC.int_ena.adc1_thres = 1;
-        }
-        if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
-            APB_SARADC.int_ena.adc1_done = 1;
-        }
-    } else { // adc_n == ADC_UNIT_2
-        if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
-            APB_SARADC.int_ena.adc2_thres = 1;
-        }
-        if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
-            APB_SARADC.int_ena.adc2_done = 1;
-        }
-    }
-}
-
-esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
-{
-    ADC_ENTER_CRITICAL();
-    if (adc_unit == ADC_UNIT_1) {
-        adc_ll_digi_intr_enable(ADC_UNIT_1, intr_mask);
-    } else if (adc_unit == ADC_UNIT_2) {
-        adc_ll_digi_intr_enable(ADC_UNIT_2, intr_mask);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * Disable interrupt of adc digital controller by bitmask.
- *
- * @param adc_n ADC unit.
- * @param intr Interrupt bitmask.
- */
-static inline void adc_ll_digi_intr_disable(adc_unit_t adc_n, adc_digi_intr_t intr)
-{
-    if (adc_n == ADC_UNIT_1) {
-        if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
-            APB_SARADC.int_ena.adc1_thres = 0;
-        }
-        if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
-            APB_SARADC.int_ena.adc1_done = 0;
-        }
-    } else { // adc_n == ADC_UNIT_2
-        if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
-            APB_SARADC.int_ena.adc2_thres = 0;
-        }
-        if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
-            APB_SARADC.int_ena.adc2_done = 0;
-        }
-    }
-}
-
-esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
-{
-    ADC_ENTER_CRITICAL();
-    if (adc_unit == ADC_UNIT_1) {
-        adc_ll_digi_intr_disable(ADC_UNIT_1, intr_mask);
-    } else if (adc_unit == ADC_UNIT_2) {
-        adc_ll_digi_intr_disable(ADC_UNIT_2, intr_mask);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * Clear interrupt of adc digital controller by bitmask.
- *
- * @param adc_n ADC unit.
- * @param intr Interrupt bitmask.
- */
-static inline void adc_ll_digi_intr_clear(adc_unit_t adc_n, adc_digi_intr_t intr)
-{
-    if (adc_n == ADC_UNIT_1) {
-        if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
-            APB_SARADC.int_clr.adc1_thres = 1;
-        }
-        if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
-            APB_SARADC.int_clr.adc1_done = 1;
-        }
-    } else { // adc_n == ADC_UNIT_2
-        if (intr & ADC_DIGI_INTR_MASK_MONITOR) {
-            APB_SARADC.int_clr.adc2_thres = 1;
-        }
-        if (intr & ADC_DIGI_INTR_MASK_MEAS_DONE) {
-            APB_SARADC.int_clr.adc2_done = 1;
-        }
-    }
-}
-
-esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
-{
-    ADC_ENTER_CRITICAL();
-    if (adc_unit == ADC_UNIT_1) {
-        adc_ll_digi_intr_clear(ADC_UNIT_1, intr_mask);
-    } else if (adc_unit == ADC_UNIT_2) {
-        adc_ll_digi_intr_clear(ADC_UNIT_2, intr_mask);
-    }
-    ADC_EXIT_CRITICAL();
-
-    return ESP_OK;
-}
-
-/**
- * Get interrupt status mask of adc digital controller.
- *
- * @param adc_n ADC unit.
- * @return
- *     - intr Interrupt bitmask.
- */
-static inline uint32_t adc_ll_digi_get_intr_status(adc_unit_t adc_n)
-{
-    uint32_t int_st = APB_SARADC.int_st.val;
-    uint32_t ret_msk = 0;
-
-    if (adc_n == ADC_UNIT_1) {
-        if (int_st & APB_SARADC_ADC1_DONE_INT_ST_M) {
-            ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE;
-        }
-        if (int_st & APB_SARADC_ADC1_THRES_INT_ST) {
-            ret_msk |= ADC_DIGI_INTR_MASK_MONITOR;
-        }
-    } else { // adc_n == ADC_UNIT_2
-        if (int_st & APB_SARADC_ADC2_DONE_INT_ST_M) {
-            ret_msk |= ADC_DIGI_INTR_MASK_MEAS_DONE;
-        }
-        if (int_st & APB_SARADC_ADC2_THRES_INT_ST_M) {
-            ret_msk |= ADC_DIGI_INTR_MASK_MONITOR;
-        }
-    }
-
-    return ret_msk;
-}
-
-uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
-{
-    uint32_t ret = 0;
-    ADC_ENTER_CRITICAL();
-    if (adc_unit == ADC_UNIT_1) {
-        ret = adc_ll_digi_get_intr_status(ADC_UNIT_1);
-    } else if (adc_unit == ADC_UNIT_2) {
-        ret = adc_ll_digi_get_intr_status(ADC_UNIT_2);
-    }
-    ADC_EXIT_CRITICAL();
-    return ret;
-}
-
-static uint8_t s_isr_registered = 0;
-static intr_handle_t s_adc_isr_handle = NULL;
-
-esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
-{
-    ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
-    ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
-
-    esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
-    if (ret == ESP_OK) {
-        s_isr_registered = 1;
-    }
-    return ret;
-}
-
-esp_err_t adc_digi_isr_deregister(void)
-{
-    esp_err_t ret = ESP_FAIL;
-    if (s_isr_registered) {
-        ret = esp_intr_free(s_adc_isr_handle);
-        if (ret == ESP_OK) {
-            s_isr_registered = 0;
-        }
-    }
-    return ret;
-}
-
-esp_err_t adc_digi_init(void)
-{
-    adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
-    ADC_ENTER_CRITICAL();
-    adc_ll_digi_set_fsm_time(ADC_HAL_FSM_RSTB_WAIT_DEFAULT, ADC_HAL_FSM_START_WAIT_DEFAULT,
-                             ADC_HAL_FSM_STANDBY_WAIT_DEFAULT);
-    adc_ll_set_sample_cycle(ADC_HAL_SAMPLE_CYCLE_DEFAULT);
-    adc_hal_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
-    adc_ll_digi_output_invert(ADC_UNIT_1, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
-    adc_ll_digi_output_invert(ADC_UNIT_2, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
-    adc_ll_digi_set_clk_div(ADC_HAL_DIGI_SAR_CLK_DIV_DEFAULT);
-    adc_hal_arbiter_config(&config);
-    ADC_EXIT_CRITICAL();
-
-    adc_hal_calibration_init(ADC_UNIT_1);
-    adc_hal_calibration_init(ADC_UNIT_2);
-
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_deinit(void)
-{
-#ifdef CONFIG_PM_ENABLE
-    if (adc_digi_arbiter_lock) {
-        esp_pm_lock_delete(adc_digi_arbiter_lock);
-        adc_digi_arbiter_lock = NULL;
-    }
-#endif
-    adc_power_release();
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_deinit(NULL);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * @brief Reset FSM of adc digital controller.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_reset(void)
-{
-    ADC_ENTER_CRITICAL();
-    adc_ll_digi_reset();
-    adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
-    adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * Set adc output data format for digital controller.
- *
- * @param format Output data format.
- */
-static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format)
-{
-    APB_SARADC.ctrl.data_sar_sel = format;
-}
-
-static inline void adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
-{
-    uint32_t tab;
-    uint8_t index = pattern_index / 4;
-    uint8_t offset = (pattern_index % 4) * 8;
-    if (adc_n == ADC_UNIT_1) {
-        tab = APB_SARADC.sar1_patt_tab[index];  // Read old register value
-        tab &= (~(0xFF000000 >> offset));       // clear old data
-        tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
-        APB_SARADC.sar1_patt_tab[index] = tab;  // Write back
-    } else { // adc_n == ADC_UNIT_2
-        tab = APB_SARADC.sar2_patt_tab[index];  // Read old register value
-        tab &= (~(0xFF000000 >> offset));       // clear old data
-        tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
-        APB_SARADC.sar2_patt_tab[index] = tab;  // Write back
-    }
-}
-
-static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
-{
-    /* Single channel mode or multi channel mode. */
-    switch (cfg->conv_mode) {
-        case ADC_CONV_SINGLE_UNIT_1:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
-            break;
-        case ADC_CONV_SINGLE_UNIT_2:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
-            break;
-        case ADC_CONV_BOTH_UNIT:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
-            break;
-        case ADC_CONV_ALTER_UNIT:
-            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
-            break;
-        default:
-            abort();
-    }
-
-    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
-        if (cfg->adc1_pattern_len) {
-            adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
-            adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, cfg->adc1_pattern_len);
-            for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
-                adc_ll_digi_prepare_pattern_table(ADC_UNIT_1, i, cfg->adc1_pattern[i]);
-            }
-        }
-    }
-    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
-        if (cfg->adc2_pattern_len) {
-            adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
-            adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, cfg->adc2_pattern_len);
-            for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
-                adc_ll_digi_prepare_pattern_table(ADC_UNIT_2, i, cfg->adc2_pattern[i]);
-            }
-        }
-    }
-    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
-        adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
-    }
-    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
-        adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_ARB);
-    }
-    adc_ll_digi_set_output_format(cfg->format);
-    if (cfg->conv_limit_en) {
-        adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
-        adc_ll_digi_convert_limit_enable();
-    } else {
-        adc_ll_digi_convert_limit_disable();
-    }
-
-    adc_ll_digi_set_trigger_interval(cfg->interval);
-    adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a);
-    adc_ll_digi_clk_sel(cfg->dig_clk.use_apll);
-    adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num);
-}
-
-esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
-{
-#ifdef CONFIG_PM_ENABLE
-    esp_err_t err;
-    if (adc_digi_arbiter_lock == NULL) {
-        if (config->dig_clk.use_apll) {
-            err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "adc_dma", &adc_digi_arbiter_lock);
-        } else {
-            err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &adc_digi_arbiter_lock);
-        }
-        if (err != ESP_OK) {
-            adc_digi_arbiter_lock = NULL;
-            ESP_LOGE(ADC_TAG, "ADC-DMA pm lock error");
-            return err;
-        }
-    }
-#endif //CONFIG_PM_ENABLE
-
-    if (config->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
-        for (int i = 0; i < config->adc1_pattern_len; i++) {
-            adc_cal_offset(ADC_UNIT_1, config->adc1_pattern[i].atten);
-        }
-    }
-    if (config->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
-        for (int i = 0; i < config->adc2_pattern_len; i++) {
-            adc_cal_offset(ADC_UNIT_2, config->adc2_pattern[i].atten);
-        }
-    }
-
-    /* If enable digtal controller, adc xpd should always on. */
-    adc_power_acquire();
-    ADC_ENTER_CRITICAL();
-    adc_digi_controller_reg_set(config);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-#endif // #if CONFIG_IDF_TARGET_ESP32S2
-
-
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
-/*---------------------------------------------------------------
-            ESP32S2 Depricated ADC functions and APIs
----------------------------------------------------------------*/
-esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
-{
-    gpio_num_t gpio_num = 0;
-    //If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run
-    if (adc_unit == ADC_UNIT_1) {
-        ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
-        gpio_num = ADC_GET_IO_NUM(ADC_UNIT_1, channel);
-        ADC_CHECK_RET(rtc_gpio_init(gpio_num));
-        ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
-        ADC_CHECK_RET(rtc_gpio_pulldown_dis(gpio_num));
-        ADC_CHECK_RET(rtc_gpio_pullup_dis(gpio_num));
-    }
-    if (adc_unit == ADC_UNIT_2) {
-        ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
-        gpio_num = ADC_GET_IO_NUM(ADC_UNIT_2, channel);
-        ADC_CHECK_RET(rtc_gpio_init(gpio_num));
-        ADC_CHECK_RET(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
-        ADC_CHECK_RET(rtc_gpio_pulldown_dis(gpio_num));
-        ADC_CHECK_RET(rtc_gpio_pullup_dis(gpio_num));
-    }
-
-    return ESP_OK;
-}
-#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3

+ 0 - 0
components/driver/adc1_private.h → components/driver/deprecated/adc1_private.h


+ 117 - 471
components/driver/adc.c → components/driver/deprecated/adc_dma_legacy.c

@@ -19,11 +19,15 @@
 #include "freertos/timers.h"
 #include "freertos/ringbuf.h"
 #include "esp_private/periph_ctrl.h"
-#include "driver/gpio.h"
-#include "driver/adc.h"
+#include "esp_private/adc_private.h"
+#include "esp_private/adc_lock.h"
 #include "hal/adc_types.h"
 #include "hal/adc_hal.h"
 #include "hal/dma_types.h"
+
+#include "driver/gpio.h"
+#include "driver/adc_types_legacy.h"
+
 //For calibration
 #if CONFIG_IDF_TARGET_ESP32S2
 #include "esp_efuse_rtc_table.h"
@@ -37,7 +41,6 @@
 #include "hal/spi_types.h"
 #include "esp_private/spi_common_internal.h"
 #elif CONFIG_IDF_TARGET_ESP32
-#include "hal/i2s_types.h"
 #include "driver/i2s_types.h"
 #include "soc/i2s_periph.h"
 #include "esp_private/i2s_platform.h"
@@ -51,21 +54,6 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
 #define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
 #define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
 
-/**
- * 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
- * 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module.
- * 3. adc_reg_lock:  this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
- */
-static _lock_t sar_adc1_lock;
-#define SAR_ADC1_LOCK_ACQUIRE()    _lock_acquire(&sar_adc1_lock)
-#define SAR_ADC1_LOCK_RELEASE()    _lock_release(&sar_adc1_lock)
-static _lock_t sar_adc2_lock;
-#define SAR_ADC2_LOCK_ACQUIRE()    _lock_acquire(&sar_adc2_lock)
-#define SAR_ADC2_LOCK_RELEASE()    _lock_release(&sar_adc2_lock)
-portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
-#define ADC_REG_LOCK_ENTER()       portENTER_CRITICAL(&adc_reg_lock)
-#define ADC_REG_LOCK_EXIT()        portEXIT_CRITICAL(&adc_reg_lock)
-
 #define INTERNAL_BUF_NUM 5
 
 /*---------------------------------------------------------------
@@ -101,10 +89,6 @@ static adc_digi_context_t *s_adc_digi_ctx = NULL;
 extern esp_pm_lock_handle_t adc_digi_arbiter_lock;
 #endif  //CONFIG_PM_ENABLE
 
-#if SOC_ADC_CALIBRATION_V1_SUPPORTED
-uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten);
-#endif
-
 /*---------------------------------------------------------------
                    ADC Continuous Read Mode (via DMA)
 ---------------------------------------------------------------*/
@@ -152,9 +136,54 @@ static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
     return ret;
 }
 
+esp_err_t adc_digi_deinitialize(void)
+{
+    if (!s_adc_digi_ctx) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (s_adc_digi_ctx->driver_start_flag != 0) {
+        ESP_LOGE(ADC_TAG, "The driver is not stopped");
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (s_adc_digi_ctx->ringbuf_hdl) {
+        vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
+        s_adc_digi_ctx->ringbuf_hdl = NULL;
+    }
+
+#if CONFIG_PM_ENABLE
+    if (s_adc_digi_ctx->pm_lock) {
+        esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
+    }
+#endif  //CONFIG_PM_ENABLE
+
+    free(s_adc_digi_ctx->rx_dma_buf);
+    free(s_adc_digi_ctx->hal.rx_desc);
+    free(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern);
+#if SOC_GDMA_SUPPORTED
+    gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
+    gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
+#elif CONFIG_IDF_TARGET_ESP32S2
+    esp_intr_free(s_adc_digi_ctx->intr_hdl);
+    spicommon_dma_chan_free(s_adc_digi_ctx->spi_host);
+    spicommon_periph_free(s_adc_digi_ctx->spi_host);
+#elif CONFIG_IDF_TARGET_ESP32
+    esp_intr_free(s_adc_digi_ctx->intr_hdl);
+    i2s_platform_release_occupation(s_adc_digi_ctx->i2s_host);
+#endif
+    free(s_adc_digi_ctx);
+    s_adc_digi_ctx = NULL;
+
+    periph_module_disable(PERIPH_SARADC_MODULE);
+
+    return ESP_OK;
+}
+
 esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
 {
     esp_err_t ret = ESP_OK;
+    ESP_RETURN_ON_FALSE((init_config->conv_num_each_intr % SOC_ADC_DIGI_DATA_BYTES_PER_CONV == 0), ESP_ERR_INVALID_ARG, ADC_TAG, "conv_frame_size should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`");
 
     s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t));
     if (s_adc_digi_ctx == NULL) {
@@ -282,7 +311,7 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
 #endif
         .desc_max_num = INTERNAL_BUF_NUM,
         .dma_chan = dma_chan,
-        .eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
+        .eof_num = init_config->conv_num_each_intr / SOC_ADC_DIGI_DATA_BYTES_PER_CONV
     };
     adc_hal_dma_ctx_config(&s_adc_digi_ctx->hal, &config);
 
@@ -362,116 +391,83 @@ static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
 
 esp_err_t adc_digi_start(void)
 {
-    if (s_adc_digi_ctx) {
-        if (s_adc_digi_ctx->driver_start_flag != 0) {
-            ESP_LOGE(ADC_TAG, "The driver is already started");
-            return ESP_ERR_INVALID_STATE;
-        }
-        adc_power_acquire();
-        //reset flags
-        s_adc_digi_ctx->ringbuf_overflow_flag = 0;
-        s_adc_digi_ctx->driver_start_flag = 1;
-        if (s_adc_digi_ctx->use_adc1) {
-            SAR_ADC1_LOCK_ACQUIRE();
-        }
-        if (s_adc_digi_ctx->use_adc2) {
-            SAR_ADC2_LOCK_ACQUIRE();
-        }
+
+    if (s_adc_digi_ctx->driver_start_flag != 0) {
+        ESP_LOGE(ADC_TAG, "The driver is already started");
+        return ESP_ERR_INVALID_STATE;
+    }
+    adc_power_acquire();
+    //reset flags
+    s_adc_digi_ctx->ringbuf_overflow_flag = 0;
+    s_adc_digi_ctx->driver_start_flag = 1;
+    if (s_adc_digi_ctx->use_adc1) {
+        adc_lock_acquire(ADC_UNIT_1);
+    }
+    if (s_adc_digi_ctx->use_adc2) {
+        adc_lock_acquire(ADC_UNIT_2);
+    }
 
 #if CONFIG_PM_ENABLE
-        // Lock APB frequency while ADC driver is in use
-        esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
+    // Lock APB frequency while ADC driver is in use
+    esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
 #endif
 
 #if SOC_ADC_CALIBRATION_V1_SUPPORTED
-        if (s_adc_digi_ctx->use_adc1) {
-            uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_1, s_adc_digi_ctx->adc1_atten);
-            adc_hal_set_calibration_param(ADC_UNIT_1, cal_val);
-        }
-        if (s_adc_digi_ctx->use_adc2) {
-            uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_2, s_adc_digi_ctx->adc2_atten);
-            adc_hal_set_calibration_param(ADC_UNIT_2, cal_val);
-        }
+    if (s_adc_digi_ctx->use_adc1) {
+        adc_set_hw_calibration_code(ADC_UNIT_1, s_adc_digi_ctx->adc1_atten);
+    }
+    if (s_adc_digi_ctx->use_adc2) {
+        adc_set_hw_calibration_code(ADC_UNIT_2, s_adc_digi_ctx->adc2_atten);
+    }
 #endif  //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
 
 #if SOC_ADC_ARBITER_SUPPORTED
-        adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
-        adc_hal_arbiter_config(&config);
+    adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
+    adc_hal_arbiter_config(&config);
 #endif  //#if SOC_ADC_ARBITER_SUPPORTED
 
-        adc_hal_set_controller(ADC_UNIT_1, ADC_HAL_CONTINUOUS_READ_MODE);
-        adc_hal_set_controller(ADC_UNIT_2, ADC_HAL_CONTINUOUS_READ_MODE);
+    adc_hal_set_controller(ADC_UNIT_1, ADC_HAL_CONTINUOUS_READ_MODE);
+    adc_hal_set_controller(ADC_UNIT_2, ADC_HAL_CONTINUOUS_READ_MODE);
 
-        adc_hal_digi_init(&s_adc_digi_ctx->hal);
-        adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg);
+    adc_hal_digi_init(&s_adc_digi_ctx->hal);
+    adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg);
 
-        //start conversion
-        adc_hal_digi_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
+    //start conversion
+    adc_hal_digi_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
 
-    }
-#if CONFIG_IDF_TARGET_ESP32S2
-    //For being compatible with the deprecated behaviour
-    else {
-        ESP_LOGE(ADC_TAG, "API used without driver initialization before. The following behaviour is deprecated!!");
-#ifdef CONFIG_PM_ENABLE
-        ESP_RETURN_ON_FALSE((adc_digi_arbiter_lock), ESP_FAIL, ADC_TAG, "Should start after call `adc_digi_controller_config`");
-        esp_pm_lock_acquire(adc_digi_arbiter_lock);
-#endif
-        ADC_ENTER_CRITICAL();
-        adc_ll_digi_dma_enable();
-        adc_ll_digi_trigger_enable();
-        ADC_EXIT_CRITICAL();
-    }
-#endif  //#if CONFIG_IDF_TARGET_ESP32S2
     return ESP_OK;
 }
 
 esp_err_t adc_digi_stop(void)
 {
-    if (s_adc_digi_ctx) {
-        if (s_adc_digi_ctx->driver_start_flag != 1) {
-            ESP_LOGE(ADC_TAG, "The driver is already stopped");
-            return ESP_ERR_INVALID_STATE;
-        }
-        s_adc_digi_ctx->driver_start_flag = 0;
+    if (s_adc_digi_ctx->driver_start_flag != 1) {
+        ESP_LOGE(ADC_TAG, "The driver is already stopped");
+        return ESP_ERR_INVALID_STATE;
+    }
+    s_adc_digi_ctx->driver_start_flag = 0;
 
-        //disable the in suc eof intrrupt
-        adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
-        //clear the in suc eof interrupt
-        adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
-        //stop ADC
-        adc_hal_digi_stop(&s_adc_digi_ctx->hal);
+    //disable the in suc eof intrrupt
+    adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
+    //clear the in suc eof interrupt
+    adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, ADC_HAL_DMA_INTR_MASK);
+    //stop ADC
+    adc_hal_digi_stop(&s_adc_digi_ctx->hal);
 
-        adc_hal_digi_deinit(&s_adc_digi_ctx->hal);
+    adc_hal_digi_deinit(&s_adc_digi_ctx->hal);
 #if CONFIG_PM_ENABLE
-        if (s_adc_digi_ctx->pm_lock) {
-            esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
-        }
+    if (s_adc_digi_ctx->pm_lock) {
+        esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
+    }
 #endif  //CONFIG_PM_ENABLE
 
-        if (s_adc_digi_ctx->use_adc1) {
-            SAR_ADC1_LOCK_RELEASE();
-        }
-        if (s_adc_digi_ctx->use_adc2) {
-            SAR_ADC2_LOCK_RELEASE();
-        }
-        adc_power_release();
+    if (s_adc_digi_ctx->use_adc2) {
+        adc_lock_release(ADC_UNIT_2);
     }
-#if CONFIG_IDF_TARGET_ESP32S2
-    else {
-        //For being compatible with the deprecated behaviour
-        ESP_LOGE(ADC_TAG, "API used without driver initialization before. The following behaviour is deprecated!!");
-#ifdef CONFIG_PM_ENABLE
-        if (adc_digi_arbiter_lock) {
-            esp_pm_lock_release(adc_digi_arbiter_lock);
-        }
-#endif
-        ADC_ENTER_CRITICAL();
-        adc_ll_digi_trigger_disable();
-        adc_ll_digi_dma_disable();
-        ADC_EXIT_CRITICAL();
+    if (s_adc_digi_ctx->use_adc1) {
+        adc_lock_release(ADC_UNIT_1);
     }
-#endif  //#if CONFIG_IDF_TARGET_ESP32S2
+    adc_power_release();
+
     return ESP_OK;
 }
 
@@ -507,50 +503,6 @@ esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_l
     return ret;
 }
 
-esp_err_t adc_digi_deinitialize(void)
-{
-    if (!s_adc_digi_ctx) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    if (s_adc_digi_ctx->driver_start_flag != 0) {
-        ESP_LOGE(ADC_TAG, "The driver is not stopped");
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    if (s_adc_digi_ctx->ringbuf_hdl) {
-        vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
-        s_adc_digi_ctx->ringbuf_hdl = NULL;
-    }
-
-#if CONFIG_PM_ENABLE
-    if (s_adc_digi_ctx->pm_lock) {
-        esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
-    }
-#endif  //CONFIG_PM_ENABLE
-
-    free(s_adc_digi_ctx->rx_dma_buf);
-    free(s_adc_digi_ctx->hal.rx_desc);
-    free(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern);
-#if SOC_GDMA_SUPPORTED
-    gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
-    gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
-#elif CONFIG_IDF_TARGET_ESP32S2
-    esp_intr_free(s_adc_digi_ctx->intr_hdl);
-    spicommon_dma_chan_free(s_adc_digi_ctx->spi_host);
-    spicommon_periph_free(s_adc_digi_ctx->spi_host);
-#elif CONFIG_IDF_TARGET_ESP32
-    esp_intr_free(s_adc_digi_ctx->intr_hdl);
-    i2s_platform_release_occupation(s_adc_digi_ctx->i2s_host);
-#endif
-    free(s_adc_digi_ctx);
-    s_adc_digi_ctx = NULL;
-
-    periph_module_disable(PERIPH_SARADC_MODULE);
-
-    return ESP_OK;
-}
-
 /*---------------------------------------------------------------
                     Digital controller setting
 ---------------------------------------------------------------*/
@@ -573,9 +525,6 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
     }
 #endif
     ESP_RETURN_ON_FALSE(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC sampling frequency out of range");
-#if CONFIG_IDF_TARGET_ESP32
-    ESP_RETURN_ON_FALSE(config->conv_limit_en == 1, ESP_ERR_INVALID_ARG, ADC_TAG, "`conv_limit_en` should be set to 1");
-#endif
 
 #if CONFIG_IDF_TARGET_ESP32
     ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
@@ -589,8 +538,6 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
     ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
 #endif
 
-    s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_en = config->conv_limit_en;
-    s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_num = config->conv_limit_num;
     s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->pattern_num;
     s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz;
     s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_mode = config->conv_mode;
@@ -626,319 +573,18 @@ esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
     return ESP_OK;
 }
 
-
-#if CONFIG_IDF_TARGET_ESP32C3
-/*---------------------------------------------------------------
-                    ADC Single Read Mode
----------------------------------------------------------------*/
-static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX];    //Array saving attenuate of each channel of ADC1, used by single read API
-static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX];    //Array saving attenuate of each channel of ADC2, used by single read API
-
-esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
-{
-    esp_err_t ret;
-    uint32_t channel = ADC2_CHANNEL_MAX;
-    if (adc_unit == ADC_UNIT_2) {
-        for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
-            if (gpio == ADC_GET_IO_NUM(ADC_UNIT_2, i)) {
-                channel = i;
-                break;
-            }
-        }
-        if (channel == ADC2_CHANNEL_MAX) {
-            return ESP_ERR_INVALID_ARG;
-        }
-    }
-
-    adc_power_acquire();
-    if (adc_unit == ADC_UNIT_1) {
-        ADC_ENTER_CRITICAL();
-        adc_hal_vref_output(ADC_UNIT_1, channel, true);
-        ADC_EXIT_CRITICAL();
-    } else {    //ADC_UNIT_2
-        ADC_ENTER_CRITICAL();
-        adc_hal_vref_output(ADC_UNIT_2, channel, true);
-        ADC_EXIT_CRITICAL();
-    }
-
-    ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
-
-    return ret;
-}
-
-esp_err_t adc1_config_width(adc_bits_width_t width_bit)
-{
-    //On ESP32C3, the data width is always 12-bits.
-    if (width_bit != ADC_WIDTH_BIT_12) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    return ESP_OK;
-}
-
-esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
-{
-    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC1 channel error");
-    ESP_RETURN_ON_FALSE((atten < SOC_ADC_ATTEN_NUM), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err");
-
-    esp_err_t ret = ESP_OK;
-    s_atten1_single[channel] = atten;
-    ret = adc_digi_gpio_init(ADC_UNIT_1, BIT(channel));
-
-    adc_hal_calibration_init(ADC_UNIT_1);
-
-    return ret;
-}
-
-int adc1_get_raw(adc1_channel_t channel)
-{
-    int raw_out = 0;
-
-    periph_module_enable(PERIPH_SARADC_MODULE);
-    adc_power_acquire();
-
-    SAR_ADC1_LOCK_ACQUIRE();
-
-    adc_atten_t atten = s_atten1_single[channel];
-    uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_1, atten);
-    adc_hal_set_calibration_param(ADC_UNIT_1, cal_val);
-
-    ADC_REG_LOCK_ENTER();
-    adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
-    adc_hal_convert(ADC_UNIT_1, channel, &raw_out);
-    ADC_REG_LOCK_EXIT();
-
-    SAR_ADC1_LOCK_RELEASE();
-
-    adc_power_release();
-    periph_module_disable(PERIPH_SARADC_MODULE);
-
-    return raw_out;
-}
-
-esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
-{
-    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_2), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 channel error");
-    ESP_RETURN_ON_FALSE((atten <= ADC_ATTEN_11db), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 Atten Err");
-
-    esp_err_t ret = ESP_OK;
-    s_atten2_single[channel] = atten;
-    ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
-
-    adc_hal_calibration_init(ADC_UNIT_2);
-
-    return ret;
-}
-
-esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
-{
-    //On ESP32C3, the data width is always 12-bits.
-    if (width_bit != ADC_WIDTH_BIT_12) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    esp_err_t ret = ESP_OK;
-
-    periph_module_enable(PERIPH_SARADC_MODULE);
-    adc_power_acquire();
-
-    SAR_ADC2_LOCK_ACQUIRE();
-
-    adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
-    adc_hal_arbiter_config(&config);
-
-    adc_atten_t atten = s_atten2_single[channel];
-    uint32_t cal_val = adc_get_calibration_offset(ADC_UNIT_2, atten);
-    adc_hal_set_calibration_param(ADC_UNIT_2, cal_val);
-
-    ADC_REG_LOCK_ENTER();
-    adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
-    ret = adc_hal_convert(ADC_UNIT_2, channel, raw_out);
-    ADC_REG_LOCK_EXIT();
-
-    SAR_ADC2_LOCK_RELEASE();
-
-    adc_power_release();
-    periph_module_disable(PERIPH_SARADC_MODULE);
-
-    return ret;
-}
-
-/*************************************/
-/* Digital controller filter setting */
-/*************************************/
-
-esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
-{
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_filter_reset(idx);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
-{
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_filter_set_factor(idx, config);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
-{
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_filter_get_factor(idx, config);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
-{
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_filter_enable(idx, enable);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**************************************/
-/* Digital controller monitor setting */
-/**************************************/
-
-esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
-{
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_monitor_config(idx, config);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
-{
-
-    ADC_ENTER_CRITICAL();
-    adc_hal_digi_monitor_enable(idx, enable);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-#endif  //#if CONFIG_IDF_TARGET_ESP32C3
-
-
-#if SOC_ADC_CALIBRATION_V1_SUPPORTED
-/*---------------------------------------------------------------
-                    Hardware Calibration Setting
----------------------------------------------------------------*/
-#if CONFIG_IDF_TARGET_ESP32S2
-#define esp_efuse_rtc_calib_get_ver()                               esp_efuse_rtc_table_read_calib_version()
-
-static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
-{
-    int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT);
-    return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
-}
-#endif
-
-static uint16_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {};
-
-//NOTE: according to calibration version, different types of lock may be taken during the process:
-//  1. Semaphore when reading efuse
-//  2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future
-//This function shoudn't be called inside critical section or ISR
-uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten)
-{
-    if (s_adc_cali_param[adc_n][atten]) {
-        ESP_LOGV(ADC_TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n, atten, s_adc_cali_param[adc_n][atten]);
-        return (uint32_t)s_adc_cali_param[adc_n][atten];
-    }
-
-    // check if we can fetch the values from eFuse.
-    int version = esp_efuse_rtc_calib_get_ver();
-
-    uint32_t init_code = 0;
-
-    if (version == ESP_EFUSE_ADC_CALIB_VER) {
-        init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
-
-    } else {
-        ESP_LOGD(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
-        adc_power_acquire();
-        ADC_ENTER_CRITICAL();
-        const bool internal_gnd = true;
-        init_code = adc_hal_self_calibration(adc_n, atten, internal_gnd);
-        ADC_EXIT_CRITICAL();
-        adc_power_release();
-    }
-
-    s_adc_cali_param[adc_n][atten] = init_code;
-    ESP_LOGV(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
-
-    return init_code;
-}
-
-// Internal function to calibrate PWDET for WiFi
-esp_err_t adc_cal_offset(adc_unit_t adc_n, adc_atten_t atten)
-{
-    adc_hal_calibration_init(adc_n);
-    uint32_t cal_val = adc_get_calibration_offset(adc_n, atten);
-    ADC_ENTER_CRITICAL();
-    adc_hal_set_calibration_param(adc_n, cal_val);
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
-
-/*---------------------------------------------------------------
-                   Deprecated API
----------------------------------------------------------------*/
-#if CONFIG_IDF_TARGET_ESP32C3
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#include "deprecated/driver/adc_deprecated.h"
-#include "deprecated/driver/adc_types_deprecated.h"
-esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
+/**
+ * @brief This function will be called during start up, to check that adc_continuous driver is not running along with the legacy adc_continuous driver
+ */
+__attribute__((constructor))
+static void check_adc_continuous_driver_conflict(void)
 {
-    if (!s_adc_digi_ctx) {
-        return ESP_ERR_INVALID_STATE;
-    }
-    ESP_RETURN_ON_FALSE((config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW), ESP_ERR_INVALID_ARG, ADC_TAG, "DC sampling frequency out of range");
-
-    s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_en = config->conv_limit_en;
-    s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_limit_num = config->conv_limit_num;
-    s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->adc_pattern_len;
-    s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz;
-
-    for (int i = 0; i < config->adc_pattern_len; i++) {
-        s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].atten = config->adc_pattern[i].atten;
-        s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].channel = config->adc_pattern[i].channel;
-        s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i].unit = config->adc_pattern[i].unit;
-    }
-
-
-    const int atten_uninitialized = 999;
-    s_adc_digi_ctx->adc1_atten = atten_uninitialized;
-    s_adc_digi_ctx->adc2_atten = atten_uninitialized;
-    s_adc_digi_ctx->use_adc1 = 0;
-    s_adc_digi_ctx->use_adc2 = 0;
-    for (int i = 0; i < config->adc_pattern_len; i++) {
-        const adc_digi_pattern_config_t *pat = &s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern[i];
-        if (pat->unit == ADC_UNIT_1) {
-            s_adc_digi_ctx->use_adc1 = 1;
-
-            if (s_adc_digi_ctx->adc1_atten == atten_uninitialized) {
-                s_adc_digi_ctx->adc1_atten = pat->atten;
-            } else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
-                return ESP_ERR_INVALID_ARG;
-            }
-        } else if (pat->unit == ADC_UNIT_2) {
-            //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
-            s_adc_digi_ctx->use_adc2 = 1;
-
-            if (s_adc_digi_ctx->adc2_atten == atten_uninitialized) {
-                s_adc_digi_ctx->adc2_atten = pat->atten;
-            } else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
-                return ESP_ERR_INVALID_ARG;
-            }
-        }
-    }
-
-    return ESP_OK;
+    // This function was declared as weak here. adc_continuous driver has one implementation.
+    // So if adc_continuous driver is not linked in, then `adc_continuous_new_handle` should be NULL at runtime.
+    extern __attribute__((weak)) esp_err_t adc_continuous_new_handle(const void *init_config, void **ret_handle);
+    if ((void *)adc_continuous_new_handle != NULL) {
+        ESP_EARLY_LOGE(ADC_TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
+        abort();
+    }
+    ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_continuous.h`");
 }
-#endif  //#if CONFIG_IDF_TARGET_ESP32C3

+ 252 - 0
components/driver/deprecated/adc_i2s_deprecated.c

@@ -0,0 +1,252 @@
+/*
+ * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*----------------------------------------------------------------------------------
+        This file contains ESP32 and ESP32S2 Depricated ADC APIs and functions
+-----------------------------------------------------------------------------------*/
+
+#include "sdkconfig.h"
+#include "esp_types.h"
+#include "esp_log.h"
+#include "esp_intr_alloc.h"
+#include "driver/rtc_io.h"
+#include "hal/adc_hal.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "hal/adc_hal_conf.h"
+#ifdef CONFIG_PM_ENABLE
+#include "esp_pm.h"
+#endif
+#include "esp_private/adc_private.h"
+#include "freertos/FreeRTOS.h"
+
+#include "driver/adc_i2s_legacy.h"
+#include "driver/adc_types_legacy.h"
+
+static __attribute__((unused)) const char *ADC_TAG = "ADC";
+
+#define ADC_CHECK_RET(fun_ret) ({                  \
+    if (fun_ret != ESP_OK) {                                \
+        ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__);  \
+        return ESP_FAIL;                                    \
+    }                                                       \
+})
+
+#define ADC_CHECK(a, str, ret_val) ({                                               \
+    if (!(a)) {                                                                     \
+        ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str);                \
+        return (ret_val);                                                           \
+    }                                                                               \
+})
+
+#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
+#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
+
+extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
+#define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
+#define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
+
+#ifdef CONFIG_PM_ENABLE
+esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL;
+#endif  //CONFIG_PM_ENABLE
+
+
+#if CONFIG_IDF_TARGET_ESP32
+/*---------------------------------------------------------------
+        ESP32 Depricated ADC APIs and functions
+---------------------------------------------------------------*/
+#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
+#define DIG_ADC_ATTEN_DEFUALT         (ADC_ATTEN_DB_11)
+#define DIG_ADC_BIT_WIDTH_DEFUALT     (3)   //3 for ADC_WIDTH_BIT_12
+
+/**
+ * @brief ADC digital controller (DMA mode) conversion rules setting.
+ */
+typedef struct {
+    union {
+        struct {
+            uint8_t atten:     2;   /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
+                                         0: measurement range 0 - 800mV,
+                                         1: measurement range 0 - 1100mV,
+                                         2: measurement range 0 - 1350mV,
+                                         3: measurement range 0 - 2600mV. */
+            uint8_t bit_width: 2;   /*!< ADC resolution.
+-                                         0: 9 bit;
+-                                         1: 10 bit;
+-                                         2: 11 bit;
+-                                         3: 12 bit. */
+            int8_t channel:   4;   /*!< ADC channel index. */
+        };
+        uint8_t val;                /*!<Raw data value */
+    };
+} adc_digi_pattern_table_t;
+
+/**
+ * @brief ADC digital controller (DMA mode) output data format option.
+ */
+typedef enum {
+    ADC_DIGI_FORMAT_12BIT,  /*!<ADC to DMA data format,                [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`). Note: For single convert mode. */
+    ADC_DIGI_FORMAT_11BIT,  /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`). Note: For multi or alter convert mode. */
+    ADC_DIGI_FORMAT_MAX,
+} adc_digi_format_t;
+
+/**
+  * Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
+  *
+  *     +---------------------+--------+--------+--------+
+  *     | conv_mode           | single |  both  |  alter |
+  *     +---------------------+--------+--------+--------+
+  *     | trigger meas times  |    1   |    1   |    1   |
+  *     +---------------------+--------+--------+--------+
+  *     | conv_limit_num      |   +1   |   +1   |   +1   |
+  *     | dma_eof_num         |   +1   |   +2   |   +1   |
+  *     | dma output (byte)   |   +2   |   +4   |   +2   |
+  *     +---------------------+--------+--------+--------+
+  */
+typedef struct {
+    uint32_t adc1_pattern_len;               /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
+                                                 The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
+                                                 resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
+                                                 pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
+    uint32_t adc2_pattern_len;               /*!<Refer to ``adc1_pattern_len`` */
+    adc_digi_pattern_table_t *adc1_pattern;  /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
+    adc_digi_pattern_table_t *adc2_pattern;  /*!<Refer to `adc1_pattern` */
+    adc_digi_convert_mode_t conv_mode;       /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
+    adc_digi_format_t format;                /*!<ADC output data format for digital controller. See ``adc_digi_format_t``. */
+} adc_digi_config_t;
+
+/**
+ * Set adc output 16-bit-data format from digital controller.
+ *
+ * @param data_sel 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode.
+ *                 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode
+ * @note see `adc_ll_digi_pattern_table_t` for more detail of data bit width
+ */
+static inline void adc_ll_digi_set_output_format(bool data_sel)
+{
+    SYSCON.saradc_ctrl.data_sar_sel = data_sel;
+}
+
+static inline void adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
+{
+    uint32_t tab;
+    uint8_t index = pattern_index / 4;
+    uint8_t offset = (pattern_index % 4) * 8;
+    if (adc_n == ADC_UNIT_1) {
+        tab = SYSCON.saradc_sar1_patt_tab[index];   // Read old register value
+        tab &= (~(0xFF000000 >> offset));           // clear old data
+        tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
+        SYSCON.saradc_sar1_patt_tab[index] = tab;   // Write back
+    } else { // adc_n == ADC_UNIT_2
+        tab = SYSCON.saradc_sar2_patt_tab[index];   // Read old register value
+        tab &= (~(0xFF000000 >> offset));           // clear old data
+        tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
+        SYSCON.saradc_sar2_patt_tab[index] = tab;   // Write back
+    }
+}
+
+static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
+{
+    /* On ESP32, only support ADC1 */
+    switch (cfg->conv_mode) {
+        case ADC_CONV_SINGLE_UNIT_1:
+            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
+            break;
+        case ADC_CONV_SINGLE_UNIT_2:
+            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
+            break;
+        case ADC_CONV_BOTH_UNIT:
+            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
+            break;
+        case ADC_CONV_ALTER_UNIT:
+            adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
+            break;
+        default:
+            abort();
+    }
+
+    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
+        adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
+        if (cfg->adc1_pattern_len) {
+            adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
+            adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, cfg->adc1_pattern_len);
+            for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
+                adc_ll_digi_prepare_pattern_table(ADC_UNIT_1, i, cfg->adc1_pattern[i]);
+            }
+        }
+    }
+    if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
+        adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_DIG);
+        if (cfg->adc2_pattern_len) {
+            adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
+            adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, cfg->adc2_pattern_len);
+            for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
+                adc_ll_digi_prepare_pattern_table(ADC_UNIT_2, i, cfg->adc2_pattern[i]);
+            }
+        }
+    }
+    adc_ll_digi_set_output_format(cfg->format);
+    adc_ll_digi_convert_limit_enable(ADC_LL_DEFAULT_CONV_LIMIT_EN);
+    adc_ll_digi_set_convert_limit_num(ADC_LL_DEFAULT_CONV_LIMIT_NUM);
+    adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
+}
+
+esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
+{
+    ADC_CHECK((src == ADC_I2S_DATA_SRC_IO_SIG || src == ADC_I2S_DATA_SRC_ADC), "ADC i2s data source error", ESP_ERR_INVALID_ARG);
+    ADC_ENTER_CRITICAL();
+    adc_ll_digi_set_data_source(src);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
+esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
+{
+    if (adc_unit == ADC_UNIT_1) {
+        ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
+    } else if (adc_unit == ADC_UNIT_2) {
+        //ADC2 does not support DMA mode
+        ADC_CHECK(false, "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
+        ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
+    }
+
+    adc_digi_pattern_table_t adc1_pattern[1];
+    adc_digi_pattern_table_t adc2_pattern[1];
+    adc_digi_config_t dig_cfg = {
+        .format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
+        .conv_mode = ADC_CONV_SINGLE_UNIT_1,
+    };
+
+    if (adc_unit == ADC_UNIT_1) {
+        adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
+        adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
+        adc1_pattern[0].channel = channel;
+        dig_cfg.adc1_pattern_len = 1;
+        dig_cfg.adc1_pattern = adc1_pattern;
+    } else if (adc_unit == ADC_UNIT_2) {
+        adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
+        adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
+        adc2_pattern[0].channel = channel;
+        dig_cfg.adc2_pattern_len = 1;
+        dig_cfg.adc2_pattern = adc2_pattern;
+    }
+    adc_common_gpio_init(adc_unit, channel);
+    ADC_ENTER_CRITICAL();
+    adc_ll_digi_set_fsm_time(ADC_HAL_FSM_RSTB_WAIT_DEFAULT, ADC_HAL_FSM_START_WAIT_DEFAULT,
+                             ADC_HAL_FSM_STANDBY_WAIT_DEFAULT);
+    adc_ll_set_sample_cycle(ADC_HAL_SAMPLE_CYCLE_DEFAULT);
+    adc_hal_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
+    adc_ll_digi_output_invert(ADC_UNIT_1, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
+    adc_ll_digi_output_invert(ADC_UNIT_2, ADC_HAL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
+    adc_ll_digi_set_clk_div(ADC_HAL_DIGI_SAR_CLK_DIV_DEFAULT);
+    adc_digi_controller_reg_set(&dig_cfg);
+    ADC_EXIT_CRITICAL();
+
+    return ESP_OK;
+}
+
+#endif  //#if CONFIG_IDF_TARGET_ESP32

+ 360 - 175
components/driver/adc_single.c → components/driver/deprecated/adc_legacy.c

@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include "sdkconfig.h"
+
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
 #include "freertos/timers.h"
@@ -17,11 +18,14 @@
 #include "driver/rtc_io.h"
 #include "sys/lock.h"
 #include "driver/gpio.h"
-#include "driver/adc.h"
+#include "esp_private/adc_private.h"
 #include "adc1_private.h"
 #include "hal/adc_types.h"
 #include "hal/adc_hal.h"
 #include "hal/adc_hal_conf.h"
+#include "esp_private/periph_ctrl.h"
+#include "esp_private/adc_lock.h"
+#include "driver/adc_types_legacy.h"
 
 #if SOC_DAC_SUPPORTED
 #include "driver/dac.h"
@@ -79,7 +83,6 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
 #define FSM_ENTER()             RTC_ENTER_CRITICAL()
 #define FSM_EXIT()              RTC_EXIT_CRITICAL()
 
-//TODO: IDF-3610
 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
 //prevent ADC1 being used by I2S dma and other tasks at the same time.
 static _lock_t adc1_dma_lock;
@@ -102,97 +105,20 @@ In ADC2, there're two locks used for different cases:
    Since conversions are short (about 31us), app returns the lock very soon,
    we use a spinlock to stand there waiting to do conversions one by one.
 
-adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.
+adc2_spinlock should be acquired first, then call `adc_lock_release(ADC_UNIT_2)` or rtc_spinlock.
 */
 
-#ifdef CONFIG_IDF_TARGET_ESP32
-//prevent ADC2 being used by wifi and other tasks at the same time.
-static _lock_t adc2_wifi_lock;
-/** For ESP32S2 the ADC2 The right to use ADC2 is controlled by the arbiter, and there is no need to set a lock. */
-#define SARADC2_ACQUIRE()       _lock_acquire( &adc2_wifi_lock )
-#define SARADC2_RELEASE()       _lock_release( &adc2_wifi_lock )
-#define SARADC2_TRY_ACQUIRE()   _lock_try_acquire( &adc2_wifi_lock )
-#define SARADC2_LOCK_CHECK()    ((uint32_t *)adc2_wifi_lock != NULL)
-
-#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-#define SARADC2_ACQUIRE()
-#define SARADC2_RELEASE()
-#define SARADC2_TRY_ACQUIRE()   (0)     //WIFI controller and rtc controller have independent parameter configuration.
-#define SARADC2_LOCK_CHECK()    (true)
-
-#endif // CONFIG_IDF_TARGET_*
-
 #if CONFIG_IDF_TARGET_ESP32S2
 #ifdef CONFIG_PM_ENABLE
 static esp_pm_lock_handle_t s_adc2_arbiter_lock;
 #endif  //CONFIG_PM_ENABLE
 #endif  // !CONFIG_IDF_TARGET_ESP32
 
+static esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, int *out_raw);
 
 /*---------------------------------------------------------------
                     ADC Common
 ---------------------------------------------------------------*/
-// ADC Power
-
-// This gets incremented when adc_power_acquire() is called, and decremented when
-// adc_power_release() is called. ADC is powered down when the value reaches zero.
-// Should be modified within critical section (ADC_ENTER/EXIT_CRITICAL).
-static int s_adc_power_on_cnt;
-
-static void adc_power_on_internal(void)
-{
-    /* Set the power always on to increase precision. */
-    adc_hal_set_power_manage(ADC_POWER_SW_ON);
-}
-
-void adc_power_acquire(void)
-{
-    ADC_POWER_ENTER();
-    s_adc_power_on_cnt++;
-    if (s_adc_power_on_cnt == 1) {
-        adc_power_on_internal();
-    }
-    ADC_POWER_EXIT();
-}
-
-void adc_power_on(void)
-{
-    ADC_POWER_ENTER();
-    adc_power_on_internal();
-    ADC_POWER_EXIT();
-}
-
-static void adc_power_off_internal(void)
-{
-#if CONFIG_IDF_TARGET_ESP32
-    adc_hal_set_power_manage(ADC_POWER_SW_OFF);
-#else
-    adc_hal_set_power_manage(ADC_POWER_BY_FSM);
-#endif
-}
-
-void adc_power_release(void)
-{
-    ADC_POWER_ENTER();
-    s_adc_power_on_cnt--;
-    /* Sanity check */
-    if (s_adc_power_on_cnt < 0) {
-        ADC_POWER_EXIT();
-        ESP_LOGE(ADC_TAG, "%s called, but s_adc_power_on_cnt == 0", __func__);
-        abort();
-    } else if (s_adc_power_on_cnt == 0) {
-        adc_power_off_internal();
-    }
-    ADC_POWER_EXIT();
-}
-
-void adc_power_off(void)
-{
-    ADC_POWER_ENTER();
-    adc_power_off_internal();
-    ADC_POWER_EXIT();
-}
-
 esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
 {
     ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
@@ -207,6 +133,7 @@ esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
     return ESP_OK;
 }
 
+#if (SOC_ADC_PERIPH_NUM >= 2)
 esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
 {
     ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
@@ -220,20 +147,10 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
 
     return ESP_OK;
 }
+#endif
 
 //------------------------------------------------------------RTC Single Read----------------------------------------------//
 #if SOC_ADC_RTC_CTRL_SUPPORTED
-
-#if SOC_ADC_CALIBRATION_V1_SUPPORTED
-uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan)
-{
-    adc_atten_t atten = adc_ll_get_atten(adc_n, chan);
-    extern uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten);
-
-    return adc_get_calibration_offset(adc_n, atten);
-}
-#endif  //SOC_ADC_CALIBRATION_V1_SUPPORTED
-
 esp_err_t adc_set_clk_div(uint8_t clk_div)
 {
     DIGI_CONTROLLER_ENTER();
@@ -264,11 +181,6 @@ static void adc_rtc_chan_init(adc_unit_t adc_unit)
     }
 }
 
-/**
- * This function is NOT an API.
- * Now some to-be-deprecated APIs are using this function, so don't make it static for now.
- * Will make this static on v5.0
- */
 esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
 {
     gpio_num_t gpio_num = 0;
@@ -314,21 +226,25 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit)
     ADC_CHECK(width_bit < ADC_WIDTH_MAX, "unsupported bit width", ESP_ERR_INVALID_ARG);
     adc_bitwidth_t bitwidth = 0;
 #if CONFIG_IDF_TARGET_ESP32
-    switch(width_bit) {
-        case ADC_WIDTH_BIT_9:
-            bitwidth = ADC_BITWIDTH_9;
-            break;
-        case ADC_WIDTH_BIT_10:
-            bitwidth = ADC_BITWIDTH_10;
-            break;
-        case ADC_WIDTH_BIT_11:
-            bitwidth = ADC_BITWIDTH_11;
-            break;
-        case ADC_WIDTH_BIT_12:
-            bitwidth = ADC_BITWIDTH_12;
-            break;
-        default:
-            abort();
+    if ((uint32_t)width_bit == (uint32_t)ADC_BITWIDTH_DEFAULT) {
+        bitwidth = SOC_ADC_RTC_MAX_BITWIDTH;
+    } else {
+        switch(width_bit) {
+            case ADC_WIDTH_BIT_9:
+                bitwidth = ADC_BITWIDTH_9;
+                break;
+            case ADC_WIDTH_BIT_10:
+                bitwidth = ADC_BITWIDTH_10;
+                break;
+            case ADC_WIDTH_BIT_11:
+                bitwidth = ADC_BITWIDTH_11;
+                break;
+            case ADC_WIDTH_BIT_12:
+                bitwidth = ADC_BITWIDTH_12;
+                break;
+            default:
+                return ESP_ERR_INVALID_ARG;
+        }
     }
 #elif CONFIG_IDF_TARGET_ESP32S2
     bitwidth = ADC_BITWIDTH_13;
@@ -392,21 +308,25 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
     ADC_CHECK(width_bit < ADC_WIDTH_MAX, "unsupported bit width", ESP_ERR_INVALID_ARG);
     adc_bitwidth_t bitwidth = 0;
 #if CONFIG_IDF_TARGET_ESP32
-    switch(width_bit) {
-        case ADC_WIDTH_BIT_9:
-            bitwidth = ADC_BITWIDTH_9;
-            break;
-        case ADC_WIDTH_BIT_10:
-            bitwidth = ADC_BITWIDTH_10;
-            break;
-        case ADC_WIDTH_BIT_11:
-            bitwidth = ADC_BITWIDTH_11;
-            break;
-        case ADC_WIDTH_BIT_12:
-            bitwidth = ADC_BITWIDTH_12;
-            break;
-        default:
-            abort();
+    if ((uint32_t)width_bit == (uint32_t)ADC_BITWIDTH_DEFAULT) {
+        bitwidth = SOC_ADC_RTC_MAX_BITWIDTH;
+    } else {
+        switch(width_bit) {
+            case ADC_WIDTH_BIT_9:
+                bitwidth = ADC_BITWIDTH_9;
+                break;
+            case ADC_WIDTH_BIT_10:
+                bitwidth = ADC_BITWIDTH_10;
+                break;
+            case ADC_WIDTH_BIT_11:
+                bitwidth = ADC_BITWIDTH_11;
+                break;
+            case ADC_WIDTH_BIT_12:
+                bitwidth = ADC_BITWIDTH_12;
+                break;
+            default:
+                return ESP_ERR_INVALID_ARG;
+        }
     }
 #elif CONFIG_IDF_TARGET_ESP32S2
     bitwidth = ADC_BITWIDTH_13;
@@ -470,9 +390,8 @@ int adc1_get_raw(adc1_channel_t channel)
     adc1_rtc_mode_acquire();
 
 #if SOC_ADC_CALIBRATION_V1_SUPPORTED
-    // Get calibration value before going into critical section
-    uint32_t cal_val = get_calibration_offset(ADC_UNIT_1, channel);
-    adc_hal_set_calibration_param(ADC_UNIT_1, cal_val);
+    adc_atten_t atten = adc_ll_get_atten(ADC_UNIT_1, channel);
+    adc_set_hw_calibration_code(ADC_UNIT_1, atten);
 #endif  //SOC_ADC_CALIBRATION_V1_SUPPORTED
 
     SARADC1_ENTER();
@@ -515,27 +434,10 @@ void adc1_ulp_enable(void)
 }
 #endif
 
+#if (SOC_ADC_PERIPH_NUM >= 2)
 /*---------------------------------------------------------------
                     ADC2
 ---------------------------------------------------------------*/
-/** For ESP32S2 the ADC2 The right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
-esp_err_t adc2_wifi_acquire(void)
-{
-    /* Wi-Fi module will use adc2. Use locks to avoid conflicts. */
-    SARADC2_ACQUIRE();
-    ESP_LOGD( ADC_TAG, "Wi-Fi takes adc2 lock." );
-    return ESP_OK;
-}
-
-esp_err_t adc2_wifi_release(void)
-{
-    ADC_CHECK(SARADC2_LOCK_CHECK(), "wifi release called before acquire", ESP_ERR_INVALID_STATE );
-    SARADC2_RELEASE();
-    ESP_LOGD( ADC_TAG, "Wi-Fi returns adc2 lock." );
-
-    return ESP_OK;
-}
-
 esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
 {
     ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
@@ -543,10 +445,13 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
 
     adc_common_gpio_init(ADC_UNIT_2, channel);
 
-    if ( SARADC2_TRY_ACQUIRE() == -1 ) {
+#if CONFIG_IDF_TARGET_ESP32
+    /** For ESP32S2 and S3, the right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
+    if (adc_lock_try_acquire(ADC_UNIT_2) != ESP_OK) {
         //try the lock, return if failed (wifi using).
         return ESP_ERR_TIMEOUT;
     }
+#endif
 
     //avoid collision with other tasks
     SARADC2_ENTER();
@@ -554,7 +459,9 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
     adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
     SARADC2_EXIT();
 
-    SARADC2_RELEASE();
+#if CONFIG_IDF_TARGET_ESP32
+    adc_lock_release(ADC_UNIT_2);
+#endif
 
 #if SOC_ADC_CALIBRATION_V1_SUPPORTED
     adc_hal_calibration_init(ADC_UNIT_2);
@@ -610,21 +517,25 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
     ADC_CHECK(channel < ADC2_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
     ADC_CHECK(width_bit < ADC_WIDTH_MAX, "unsupported bit width", ESP_ERR_INVALID_ARG);
 #if CONFIG_IDF_TARGET_ESP32
-    switch(width_bit) {
-        case ADC_WIDTH_BIT_9:
-            bitwidth = ADC_BITWIDTH_9;
-            break;
-        case ADC_WIDTH_BIT_10:
-            bitwidth = ADC_BITWIDTH_10;
-            break;
-        case ADC_WIDTH_BIT_11:
-            bitwidth = ADC_BITWIDTH_11;
-            break;
-        case ADC_WIDTH_BIT_12:
-            bitwidth = ADC_BITWIDTH_12;
-            break;
-        default:
-            abort();
+    if ((uint32_t)width_bit == (uint32_t)ADC_BITWIDTH_DEFAULT) {
+        bitwidth = SOC_ADC_RTC_MAX_BITWIDTH;
+    } else {
+        switch(width_bit) {
+            case ADC_WIDTH_BIT_9:
+                bitwidth = ADC_BITWIDTH_9;
+                break;
+            case ADC_WIDTH_BIT_10:
+                bitwidth = ADC_BITWIDTH_10;
+                break;
+            case ADC_WIDTH_BIT_11:
+                bitwidth = ADC_BITWIDTH_11;
+                break;
+            case ADC_WIDTH_BIT_12:
+                bitwidth = ADC_BITWIDTH_12;
+                break;
+            default:
+                return ESP_ERR_INVALID_ARG;
+        }
     }
 #elif CONFIG_IDF_TARGET_ESP32S2
     bitwidth = ADC_BITWIDTH_13;
@@ -633,15 +544,17 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
 #endif
 
 #if SOC_ADC_CALIBRATION_V1_SUPPORTED
-    // Get calibration value before going into critical section
-    uint32_t cal_val = get_calibration_offset(ADC_UNIT_2, channel);
-    adc_hal_set_calibration_param(ADC_UNIT_2, cal_val);
+    adc_atten_t atten = adc_ll_get_atten(ADC_UNIT_2, channel);
+    adc_set_hw_calibration_code(ADC_UNIT_2, atten);
 #endif  //SOC_ADC_CALIBRATION_V1_SUPPORTED
 
-    if ( SARADC2_TRY_ACQUIRE() == -1 ) {
+#if CONFIG_IDF_TARGET_ESP32
+    /** For ESP32S2 and S3, the right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
+    if (adc_lock_try_acquire(ADC_UNIT_2) != ESP_OK) {
         //try the lock, return if failed (wifi using).
         return ESP_ERR_TIMEOUT;
     }
+#endif
     adc_power_acquire();         //in critical section with whole rtc module
 
     //avoid collision with other tasks
@@ -689,17 +602,14 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
     SARADC2_EXIT();
 
     adc_power_release();
-    SARADC2_RELEASE();
+#if CONFIG_IDF_TARGET_ESP32
+    adc_lock_release(ADC_UNIT_2);
+#endif
 
     *raw_out = adc_value;
     return ret;
 }
 
-esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
-{
-    return adc_vref_to_gpio(ADC_UNIT_2, gpio);
-}
-
 esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
 {
 #ifdef CONFIG_IDF_TARGET_ESP32
@@ -736,3 +646,278 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
 }
 
 #endif //SOC_ADC_RTC_CTRL_SUPPORTED
+#endif  //#if (SOC_ADC_PERIPH_NUM >= 2)
+
+
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+/*---------------------------------------------------------------
+            Legacy ADC Single Read Mode
+            when RTC controller isn't supported
+---------------------------------------------------------------*/
+#include "esp_check.h"
+
+portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
+#define ADC_REG_LOCK_ENTER()       portENTER_CRITICAL(&adc_reg_lock)
+#define ADC_REG_LOCK_EXIT()        portEXIT_CRITICAL(&adc_reg_lock)
+
+static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX];    //Array saving attenuate of each channel of ADC1, used by single read API
+#if (SOC_ADC_PERIPH_NUM >= 2)
+static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX];    //Array saving attenuate of each channel of ADC2, used by single read API
+#endif
+
+
+static int8_t adc_digi_get_io_num(adc_unit_t adc_unit, uint8_t adc_channel)
+{
+    assert(adc_unit <= SOC_ADC_PERIPH_NUM);
+    uint8_t adc_n = (adc_unit == ADC_UNIT_1) ? 0 : 1;
+    return adc_channel_io_map[adc_n][adc_channel];
+}
+
+static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
+{
+    esp_err_t ret = ESP_OK;
+    uint64_t gpio_mask = 0;
+    uint32_t n = 0;
+    int8_t io = 0;
+
+    while (channel_mask) {
+        if (channel_mask & 0x1) {
+            io = adc_digi_get_io_num(adc_unit, n);
+            if (io < 0) {
+                return ESP_ERR_INVALID_ARG;
+            }
+            gpio_mask |= BIT64(io);
+        }
+        channel_mask = channel_mask >> 1;
+        n++;
+    }
+
+    gpio_config_t cfg = {
+        .pin_bit_mask = gpio_mask,
+        .mode = GPIO_MODE_DISABLE,
+    };
+    ret = gpio_config(&cfg);
+
+    return ret;
+}
+
+#if CONFIG_IDF_TARGET_ESP32C3
+esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
+{
+    esp_err_t ret;
+    uint32_t channel = ADC2_CHANNEL_MAX;
+    if (adc_unit == ADC_UNIT_2) {
+        for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
+            if (gpio == ADC_GET_IO_NUM(ADC_UNIT_2, i)) {
+                channel = i;
+                break;
+            }
+        }
+        if (channel == ADC2_CHANNEL_MAX) {
+            return ESP_ERR_INVALID_ARG;
+        }
+    }
+
+    adc_power_acquire();
+    if (adc_unit == ADC_UNIT_1) {
+        RTC_ENTER_CRITICAL();
+        adc_hal_vref_output(ADC_UNIT_1, channel, true);
+        RTC_EXIT_CRITICAL();
+    } else {    //ADC_UNIT_2
+        RTC_ENTER_CRITICAL();
+        adc_hal_vref_output(ADC_UNIT_2, channel, true);
+        RTC_EXIT_CRITICAL();
+    }
+
+    ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
+
+    return ret;
+}
+#endif
+
+esp_err_t adc1_config_width(adc_bits_width_t width_bit)
+{
+    //On ESP32C3, the data width is always 12-bits.
+    if (width_bit != ADC_WIDTH_BIT_12) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
+{
+    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC1 channel error");
+    ESP_RETURN_ON_FALSE((atten < SOC_ADC_ATTEN_NUM), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err");
+
+    esp_err_t ret = ESP_OK;
+    s_atten1_single[channel] = atten;
+    ret = adc_digi_gpio_init(ADC_UNIT_1, BIT(channel));
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_hal_calibration_init(ADC_UNIT_1);
+#endif
+
+    return ret;
+}
+
+int adc1_get_raw(adc1_channel_t channel)
+{
+    int raw_out = 0;
+
+    if (adc_lock_try_acquire(ADC_UNIT_1) != ESP_OK) {
+        return ESP_ERR_TIMEOUT;
+    }
+
+    periph_module_enable(PERIPH_SARADC_MODULE);
+    adc_power_acquire();
+    adc_ll_digi_clk_sel(0);
+
+    adc_atten_t atten = s_atten1_single[channel];
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_set_hw_calibration_code(ADC_UNIT_1, atten);
+#endif
+
+    ADC_REG_LOCK_ENTER();
+    adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
+    adc_hal_convert(ADC_UNIT_1, channel, &raw_out);
+    ADC_REG_LOCK_EXIT();
+
+    adc_power_release();
+    periph_module_disable(PERIPH_SARADC_MODULE);
+    adc_lock_release(ADC_UNIT_1);
+
+    return raw_out;
+}
+
+#if (SOC_ADC_PERIPH_NUM >= 2)
+esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
+{
+    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_2), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 channel error");
+    ESP_RETURN_ON_FALSE((atten <= ADC_ATTEN_DB_11), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 Atten Err");
+
+    esp_err_t ret = ESP_OK;
+    s_atten2_single[channel] = atten;
+    ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_hal_calibration_init(ADC_UNIT_2);
+#endif
+
+    return ret;
+}
+
+esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
+{
+    //On ESP32C3, the data width is always 12-bits.
+    if (width_bit != ADC_WIDTH_BIT_12) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    esp_err_t ret = ESP_OK;
+
+    if (adc_lock_try_acquire(ADC_UNIT_2) != ESP_OK) {
+        return ESP_ERR_TIMEOUT;
+    }
+
+    periph_module_enable(PERIPH_SARADC_MODULE);
+    adc_power_acquire();
+
+    adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
+    adc_hal_arbiter_config(&config);
+
+    adc_atten_t atten = s_atten2_single[channel];
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_set_hw_calibration_code(ADC_UNIT_2, atten);
+#endif
+
+    ADC_REG_LOCK_ENTER();
+    adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
+    ret = adc_hal_convert(ADC_UNIT_2, channel, raw_out);
+    ADC_REG_LOCK_EXIT();
+
+    adc_power_release();
+    periph_module_disable(PERIPH_SARADC_MODULE);
+    adc_lock_release(ADC_UNIT_2);
+
+    return ret;
+}
+#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
+#endif  //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+
+
+static void adc_hal_onetime_start(adc_unit_t adc_n)
+{
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+    (void)adc_n;
+    /**
+     * There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the
+     * ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller
+     * clock cycle.
+     *
+     * This limitation will be removed in hardware future versions.
+     *
+     */
+    uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1);
+    //Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough.
+    uint32_t delay = (1000 * 1000) / digi_clk + 1;
+    //3 ADC digital controller clock cycle
+    delay = delay * 3;
+    //This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed.
+    if (digi_clk >= APB_CLK_FREQ/8) {
+        delay = 0;
+    }
+
+    adc_oneshot_ll_start(false);
+    esp_rom_delay_us(delay);
+    adc_oneshot_ll_start(true);
+
+    //No need to delay here. Becuase if the start signal is not seen, there won't be a done intr.
+#else
+    adc_oneshot_ll_start(adc_n);
+#endif
+}
+
+static esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, int *out_raw)
+{
+    uint32_t event = (adc_n == ADC_UNIT_1) ? ADC_LL_EVENT_ADC1_ONESHOT_DONE : ADC_LL_EVENT_ADC2_ONESHOT_DONE;
+    adc_oneshot_ll_clear_event(event);
+    adc_oneshot_ll_disable_all_unit();
+    adc_oneshot_ll_enable(adc_n);
+    adc_oneshot_ll_set_channel(adc_n, channel);
+
+    adc_hal_onetime_start(adc_n);
+
+    while (adc_oneshot_ll_get_event(event) != true) {
+        ;
+    }
+
+    *out_raw = adc_oneshot_ll_get_raw_result(adc_n);
+    if (adc_oneshot_ll_raw_check_valid(adc_n, *out_raw) == false) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    //HW workaround: when enabling periph clock, this should be false
+    adc_oneshot_ll_disable_all_unit();
+
+    return ESP_OK;
+}
+
+#if !CONFIG_IDF_TARGET_ESP32
+//wrapper should be removed after I2S deprecation
+/**
+ * @brief This function will be called during start up, to check that adc_oneshot driver is not running along with the legacy adc oneshot driver
+ */
+__attribute__((constructor))
+static void check_adc_oneshot_driver_conflict(void)
+{
+    // This function was declared as weak here. adc_oneshot driver has one implementation.
+    // So if adc_oneshot driver is not linked in, then `adc_oneshot_new_unit` should be NULL at runtime.
+    extern __attribute__((weak)) esp_err_t adc_oneshot_new_unit(const void *init_config, void **ret_unit);
+    if ((void *)adc_oneshot_new_unit != NULL) {
+        ESP_EARLY_LOGE(ADC_TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
+        abort();
+    }
+    ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_oneshot.h`");
+}
+#endif

+ 16 - 306
components/driver/include/driver/adc.h → components/driver/deprecated/driver/adc.h

@@ -1,152 +1,31 @@
 /*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#pragma once
+/*----------------------------------------------------------------------------------
+              This file contains Deprecated ADC APIs
+-----------------------------------------------------------------------------------*/
 
-#include <stdint.h>
-#include <stdbool.h>
-#include "esp_err.h"
+#pragma once
 #include "sdkconfig.h"
+#include "esp_err.h"
 #include "driver/gpio.h"
+#include "driver/adc_types_legacy.h"
 #include "hal/adc_types.h"
 
-#ifdef __cplusplus
-extern "C" {
+#if !CONFIG_ADC_SUPPRESS_DEPRECATE_WARN
+#warning "legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively"
 #endif
 
-#if CONFIG_IDF_TARGET_ESP32
-/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
-typedef enum {
-    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
-    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO37 */
-    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO38 */
-    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO39 */
-    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO32 */
-    ADC1_CHANNEL_5,     /*!< ADC1 channel 5 is GPIO33 */
-    ADC1_CHANNEL_6,     /*!< ADC1 channel 6 is GPIO34 */
-    ADC1_CHANNEL_7,     /*!< ADC1 channel 7 is GPIO35 */
-    ADC1_CHANNEL_MAX,
-} adc1_channel_t;
-#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
-/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
-typedef enum {
-    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1  */
-    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO2  */
-    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO3  */
-    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO4  */
-    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO5  */
-    ADC1_CHANNEL_5,     /*!< ADC1 channel 5 is GPIO6  */
-    ADC1_CHANNEL_6,     /*!< ADC1 channel 6 is GPIO7  */
-    ADC1_CHANNEL_7,     /*!< ADC1 channel 7 is GPIO8  */
-    ADC1_CHANNEL_8,     /*!< ADC1 channel 8 is GPIO9  */
-    ADC1_CHANNEL_9,     /*!< ADC1 channel 9 is GPIO10 */
-    ADC1_CHANNEL_MAX,
-} adc1_channel_t;
-#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
-/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
-typedef enum {
-    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */
-    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO1 */
-    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO2 */
-    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO3 */
-    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO4 */
-    ADC1_CHANNEL_MAX,
-} adc1_channel_t;
-#endif // CONFIG_IDF_TARGET_*
-
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO ESP32-S3 channels are wrong IDF-1776
-/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
-typedef enum {
-    ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4  (ESP32), GPIO11 (ESP32-S2) */
-    ADC2_CHANNEL_1,     /*!< ADC2 channel 1 is GPIO0  (ESP32), GPIO12 (ESP32-S2) */
-    ADC2_CHANNEL_2,     /*!< ADC2 channel 2 is GPIO2  (ESP32), GPIO13 (ESP32-S2) */
-    ADC2_CHANNEL_3,     /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */
-    ADC2_CHANNEL_4,     /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */
-    ADC2_CHANNEL_5,     /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */
-    ADC2_CHANNEL_6,     /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */
-    ADC2_CHANNEL_7,     /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */
-    ADC2_CHANNEL_8,     /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */
-    ADC2_CHANNEL_9,     /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */
-    ADC2_CHANNEL_MAX,
-} adc2_channel_t;
-#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
-/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
-typedef enum {
-    ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
-    ADC2_CHANNEL_MAX,
-} adc2_channel_t;
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-
-/**
- * @brief ADC rtc controller attenuation option.
- *
- * @note  This definitions are only for being back-compatible
- */
-#define ADC_ATTEN_0db   ADC_ATTEN_DB_0
-#define ADC_ATTEN_2_5db ADC_ATTEN_DB_2_5
-#define ADC_ATTEN_6db   ADC_ATTEN_DB_6
-#define ADC_ATTEN_11db  ADC_ATTEN_DB_11
-
-/**
- * The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth
- * by `SOC_ADC_RTC_MAX_BITWIDTH` defined in soc_caps.h.
- */
-#define ADC_WIDTH_BIT_DEFAULT   (ADC_WIDTH_MAX-1)
-
-//this definitions are only for being back-compatible
-#define ADC_WIDTH_9Bit  ADC_WIDTH_BIT_9
-#define ADC_WIDTH_10Bit ADC_WIDTH_BIT_10
-#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
-#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
-
-/**
- * @brief ADC digital controller encode option.
- *
- * @deprecated The ESP32-S2 doesn't use I2S DMA. Call ``adc_digi_output_format_t`` instead.
- */
-typedef enum {
-    ADC_ENCODE_12BIT,        /*!< ADC to DMA data format,          , [15:12]-channel [11:0]-12 bits ADC data */
-    ADC_ENCODE_11BIT,        /*!< ADC to DMA data format, [15]-unit, [14:11]-channel [10:0]-11 bits ADC data */
-    ADC_ENCODE_MAX,
-} adc_i2s_encode_t;
-
 /*---------------------------------------------------------------
-                    Common setting
+            Deprecated API
 ---------------------------------------------------------------*/
-
-/**
- * @brief Enable ADC power
- * @deprecated Use adc_power_acquire and adc_power_release instead.
- */
-void adc_power_on(void) __attribute__((deprecated));
-
-/**
- * @brief Power off SAR ADC
- * @deprecated Use adc_power_acquire and adc_power_release instead.
- * This function will force power down for ADC.
- * This function is deprecated because forcing power ADC power off may
- * disrupt operation of other components which may be using the ADC.
- */
-void adc_power_off(void) __attribute__((deprecated));
-
-/**
- * @brief Increment the usage counter for ADC module.
- * ADC will stay powered on while the counter is greater than 0.
- * Call adc_power_release when done using the ADC.
- */
-void adc_power_acquire(void);
-
-/**
- * @brief Decrement the usage counter for ADC module.
- * ADC will stay powered on while the counter is greater than 0.
- * Call this function when done using the ADC.
- */
-void adc_power_release(void);
-
 /*---------------------------------------------------------------
                     ADC Single Read Setting
 ---------------------------------------------------------------*/
@@ -288,6 +167,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
 void adc1_ulp_enable(void);
 #endif  //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
 
+#if (SOC_ADC_PERIPH_NUM >= 2)
 /**
  * @brief Get the GPIO number of a specific ADC2 channel.
  *
@@ -396,59 +276,13 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
  *                  - ESP_ERR_INVALID_ARG: Unsupported GPIO
  */
 esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
+#endif  //#if (SOC_ADC_PERIPH_NUM >= 2)
 
-/**
- *  @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO.
- *
- *  This function routes the internal reference voltage of ADCn to one of
- *  ADC2's channels. This reference voltage can then be manually measured
- *  for calibration purposes.
- *
- *  @deprecated Use ``adc_vref_to_gpio`` instead.
- *
- *  @param[in]  gpio    GPIO number (ADC2's channels are supported)
- *
- *  @return
- *                  - ESP_OK: v_ref successfully routed to selected GPIO
- *                  - ESP_ERR_INVALID_ARG: Unsupported GPIO
- */
-esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
 
 /*---------------------------------------------------------------
-                    DMA setting
+            ADC DMA Read Setting
 ---------------------------------------------------------------*/
-/**
- * @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
- */
-#define ADC_MAX_DELAY UINT32_MAX
-
-/**
- * @brief ADC DMA driver configuration
- */
-typedef struct adc_digi_init_config_s {
-    uint32_t max_store_buf_size;    ///< Max length of the converted data that driver can store before they are processed.
-    uint32_t conv_num_each_intr;    ///< Bytes of data that can be converted in 1 interrupt.
-    uint32_t adc1_chan_mask;        ///< Channel list of ADC1 to be initialized.
-    uint32_t adc2_chan_mask;        ///< Channel list of ADC2 to be initialized.
-} adc_digi_init_config_t;
-
-/**
- * @brief ADC digital controller settings
- */
-typedef struct {
-    bool conv_limit_en;                      ///< To limit ADC conversion times. Conversion stops after finishing `conv_limit_num` times conversion
-    uint32_t conv_limit_num;                 ///< Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255.
-    uint32_t pattern_num;                    ///< Number of ADC channels that will be used
-    adc_digi_pattern_config_t *adc_pattern;    ///< List of configs for each ADC channel that will be used
-    uint32_t sample_freq_hz;  /*!< The expected ADC sampling frequency in Hz. Range: 611Hz ~ 83333Hz
-                                   Fs = Fd / interval / 2
-                                   Fs: sampling frequency;
-                                   Fd: digital controller frequency, no larger than 5M for better performance
-                                   interval: interval between 2 measurement trigger signal, the smallest interval should not be smaller than the ADC measurement period, the largest interval should not be larger than 4095 */
-    adc_digi_convert_mode_t conv_mode;      ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
-    adc_digi_output_format_t format;        ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
-} adc_digi_configuration_t;
-
+#if SOC_ADC_DMA_SUPPORTED
 /**
  * @brief Initialize the Digital ADC.
  *
@@ -515,130 +349,6 @@ esp_err_t adc_digi_deinitialize(void);
  *      - ESP_OK                On success
  */
 esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config);
-
-
-#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
-//TODO IDF-3610
-/**
- * @brief Reset adc digital controller filter.
- *
- * @param idx Filter index.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
-
-/**
- * @brief Set adc digital controller filter configuration.
- *
- * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
- *
- * @param idx Filter index.
- * @param config See ``adc_digi_filter_t``.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
-
-/**
- * @brief Get adc digital controller filter configuration.
- *
- * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
- *
- * @param idx Filter index.
- * @param config See ``adc_digi_filter_t``.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
-
-/**
- * @brief Enable/disable adc digital controller filter.
- *        Filtering the ADC data to obtain smooth data at higher sampling rates.
- *
- * @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
- *
- * @param idx Filter index.
- * @param enable Enable/Disable filter.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
-
-/**
- * @brief Config monitor of adc digital controller.
- *
- * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
- *
- * @param idx Monitor index.
- * @param config See ``adc_digi_monitor_t``.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
-
-/**
- * @brief Enable/disable monitor of adc digital controller.
- *
- * @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
- *
- * @param idx Monitor index.
- * @param enable True or false enable monitor.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
-#endif  //#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
-
-#if CONFIG_IDF_TARGET_ESP32
-//TODO IDF-3610
-/**
- * @brief Read Hall Sensor
- *
- * @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
- *       the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
- *       When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
- *       Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
- *
- * @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
- * these channels for use as ADC channels.
- *
- * @note The ADC1 module must be enabled by calling
- *       adc1_config_width() before calling hall_sensor_read(). ADC1
- *       should be configured for 12 bit readings, as the hall sensor
- *       readings are low values and do not cover the full range of the
- *       ADC.
- *
- * @return The hall sensor reading.
- */
-int hall_sensor_read(void);
-
-/*---------------------------------------------------------------
-                    To Be Deprecated TODO: IDF-3610
----------------------------------------------------------------*/
-/**
- * @brief Set I2S data source
- * @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
- * @return
- *     - ESP_OK success
- */
-esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
-
-/**
- * @brief Initialize I2S ADC mode
- * @param adc_unit ADC unit index
- * @param channel ADC channel index
- * @return
- *     - ESP_OK success
- *     - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
 #endif
 
 #ifdef __cplusplus

+ 0 - 163
components/driver/deprecated/driver/adc_deprecated.h

@@ -1,163 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/*----------------------------------------------------------------------------------
-              This file contains Deprecated ADC APIs
------------------------------------------------------------------------------------*/
-
-#pragma once
-#include "esp_err.h"
-#include "hal/adc_types.h"
-#include "driver/adc_types_deprecated.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if CONFIG_IDF_TARGET_ESP32S2
-/*---------------------------------------------------------------
-                    ESP32S2 Deprecated ADC APIs
----------------------------------------------------------------*/
-/**
- * @brief Config ADC module arbiter.
- *        The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
- *        the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
- *
- * @note Only ADC2 support arbiter.
- * @note Default priority: Wi-Fi > RTC > Digital;
- * @note In normal use, there is no need to call this interface to config arbiter.
- *
- * @param adc_unit ADC unit.
- * @param config Refer to `adc_arbiter_t`.
- *
- * @return
- *      - ESP_OK Success
- *      - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
- */
-esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config) __attribute__((deprecated));
-
-/**
- * @brief Enable interrupt of adc digital controller by bitmask.
- *
- * @param adc_unit ADC unit.
- * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated));
-
-/**
- * @brief Disable interrupt of adc digital controller by bitmask.
- *
- * @param adc_unit ADC unit.
- * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated));
-
-/**
- * @brief Clear interrupt of adc digital controller by bitmask.
- *
- * @param adc_unit ADC unit.
- * @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
- *
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask) __attribute__((deprecated));
-
-/**
- * @brief Get interrupt status mask of adc digital controller.
- *
- * @param adc_unit ADC unit.
- * @return
- *     - intr Interrupt bitmask, See ``adc_digi_intr_t``.
- */
-uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit) __attribute__((deprecated));
-
-/**
- * @brief Register ADC interrupt handler, the handler is an ISR.
- *        The handler will be attached to the same CPU core that this function is running on.
- *
- * @param fn Interrupt handler function.
- * @param arg Parameter for handler function
- * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
- *        ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
- *
- * @return
- *     - ESP_OK Success
- *     - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
- *     - ESP_ERR_INVALID_ARG Function pointer error.
- */
-esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags) __attribute__((deprecated));
-
-/**
- * @brief Deregister ADC interrupt handler, the handler is an ISR.
- *
- * @return
- *     - ESP_OK Success
- *     - ESP_ERR_INVALID_ARG hander error.
- *     - ESP_FAIL ISR not be registered.
- */
-esp_err_t adc_digi_isr_deregister(void) __attribute__((deprecated));
-#endif  // #if CONFIG_IDF_TARGET_ESP32S2
-
-
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
-/*---------------------------------------------------------------
-            ESP32, ESP32S2 Deprecated ADC APIs
----------------------------------------------------------------*/
-/**
- * @brief ADC digital controller initialization.
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_init(void) __attribute__((deprecated));
-
-/**
- * @brief ADC digital controller deinitialization.
- * @return
- *      - ESP_OK Success
- */
-esp_err_t adc_digi_deinit(void) __attribute__((deprecated));
-#endif  //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
-
-
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
-/*---------------------------------------------------------------
-            ESP32, ESP32S2, ESP32C3 Deprecated ADC APIs
----------------------------------------------------------------*/
-/**
- * @brief Setting the digital controller.
- *
- * @param config Pointer to digital controller paramter. Refer to ``adc_digi_config_t``.
- *
- * @return
- *      - ESP_ERR_INVALID_STATE Driver state is invalid.
- *      - ESP_ERR_INVALID_ARG   If the combination of arguments is invalid.
- *      - ESP_OK                On success
- */
-esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) __attribute__((deprecated));
-
-/**
- * @brief Initialize ADC pad
- * @param adc_unit ADC unit index
- * @param channel ADC channel index
- * @return
- *     - ESP_OK success
- *     - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));;
-#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
-
-
-#ifdef __cplusplus
-}
-#endif

+ 51 - 0
components/driver/deprecated/driver/adc_i2s_legacy.h

@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+#include "sdkconfig.h"
+#include "esp_err.h"
+#include "hal/adc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CONFIG_IDF_TARGET_ESP32
+/**
+ * @brief ESP32 ADC DMA source selection.
+ */
+typedef enum {
+    ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal  */
+    ADC_I2S_DATA_SRC_ADC = 1,    /*!< I2S data from ADC */
+} adc_i2s_source_t;
+#endif
+
+#if CONFIG_IDF_TARGET_ESP32
+/*---------------------------------------------------------------
+            ESP32 Deprecated API
+---------------------------------------------------------------*/
+/**
+ * @brief Set I2S data source
+ * @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
+ * @return
+ *     - ESP_OK success
+ */
+esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
+
+/**
+ * @brief Initialize I2S ADC mode
+ * @param adc_unit ADC unit index
+ * @param channel ADC channel index
+ * @return
+ *     - ESP_OK success
+ *     - ESP_ERR_INVALID_ARG Parameter error
+ */
+esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
+#endif
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 203
components/driver/deprecated/driver/adc_types_deprecated.h

@@ -1,203 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-#include "esp_err.h"
-#include "hal/adc_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if CONFIG_IDF_TARGET_ESP32
-/*---------------------------------------------------------------
-                    ESP32 Deprecated Types
----------------------------------------------------------------*/
-/**
- * @brief ADC digital controller (DMA mode) conversion rules setting.
- */
-typedef struct {
-    union {
-        struct {
-            uint8_t atten:     2;   /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
-                                         0: measurement range 0 - 800mV,
-                                         1: measurement range 0 - 1100mV,
-                                         2: measurement range 0 - 1350mV,
-                                         3: measurement range 0 - 2600mV. */
-            uint8_t bit_width: 2;   /*!< ADC resolution.
--                                         0: 9 bit;
--                                         1: 10 bit;
--                                         2: 11 bit;
--                                         3: 12 bit. */
-            int8_t channel:   4;   /*!< ADC channel index. */
-        };
-        uint8_t val;                /*!<Raw data value */
-    };
-} adc_digi_pattern_table_t __attribute__((deprecated));
-
-/**
-  * Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
-  *
-  *     +---------------------+--------+--------+--------+
-  *     | conv_mode           | single |  both  |  alter |
-  *     +---------------------+--------+--------+--------+
-  *     | trigger meas times  |    1   |    1   |    1   |
-  *     +---------------------+--------+--------+--------+
-  *     | conv_limit_num      |   +1   |   +1   |   +1   |
-  *     | dma_eof_num         |   +1   |   +2   |   +1   |
-  *     | dma output (byte)   |   +2   |   +4   |   +2   |
-  *     +---------------------+--------+--------+--------+
-  */
-typedef struct {
-    bool conv_limit_en;                      /*!<Enable the function of limiting ADC conversion times.
-                                                 If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
-    uint32_t conv_limit_num;                 /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
-    uint32_t adc1_pattern_len;               /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
-                                                 The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
-                                                 resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
-                                                 pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
-    uint32_t adc2_pattern_len;               /*!<Refer to ``adc1_pattern_len`` */
-    adc_digi_pattern_table_t *adc1_pattern;  /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
-    adc_digi_pattern_table_t *adc2_pattern;  /*!<Refer to `adc1_pattern` */
-    adc_digi_convert_mode_t conv_mode;       /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
-    adc_digi_output_format_t format;         /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
-} adc_digi_config_t __attribute__((deprecated));
-#endif  //#if CONFIG_IDF_TARGET_ESP32
-
-
-#if CONFIG_IDF_TARGET_ESP32S2
-/*---------------------------------------------------------------
-                    ESP32S2 Deprecated Types
----------------------------------------------------------------*/
-/**
- * @brief ADC digital controller (DMA mode) conversion rules setting.
- */
-typedef struct {
-    union {
-        struct {
-            uint8_t atten:     2;   /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
-                                         0: measurement range 0 - 800mV,
-                                         1: measurement range 0 - 1100mV,
-                                         2: measurement range 0 - 1350mV,
-                                         3: measurement range 0 - 2600mV. */
-            uint8_t reserved:  2;   /*!< reserved0 */
-            uint8_t channel:   4;   /*!< ADC channel index. */
-        };
-        uint8_t val;                /*!<Raw data value */
-    };
-} adc_digi_pattern_table_t __attribute__((deprecated));
-
-/**
-  * @brief ADC digital controller (DMA mode) configuration parameters.
-  *
-  * Example setting: When using ADC1 channel0 to measure voltage, the sampling rate is required to be 1 kHz:
-  *
-  *     +---------------------+--------+--------+--------+
-  *     | sample rate         | 1 kHz  | 1 kHz  | 1 kHz  |
-  *     +---------------------+--------+--------+--------+
-  *     | conv_mode           | single |  both  |  alter |
-  *     | adc1_pattern_len    |    1   |    1   |    1   |
-  *     | dig_clk.use_apll    |    0   |    0   |    0   |
-  *     | dig_clk.div_num     |   99   |   99   |   99   |
-  *     | dig_clk.div_b       |    0   |    0   |    0   |
-  *     | dig_clk.div_a       |    0   |    0   |    0   |
-  *     | interval            |  400   |  400   |  200   |
-  *     +---------------------+--------+--------+--------+
-  *     | `trigger_meas_freq` | 1 kHz  | 1 kHz  | 2 kHz  |
-  *     +---------------------+--------+--------+--------+
-  *
-  * Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
-  *
-  *     +---------------------+--------+--------+--------+
-  *     | conv_mode           | single |  both  |  alter |
-  *     +---------------------+--------+--------+--------+
-  *     | trigger meas times  |    1   |    1   |    1   |
-  *     +---------------------+--------+--------+--------+
-  *     | conv_limit_num      |   +1   |   +1   |   +1   |
-  *     | dma_eof_num         |   +1   |   +2   |   +1   |
-  *     | dma output (byte)   |   +2   |   +4   |   +2   |
-  *     +---------------------+--------+--------+--------+
-  */
-typedef struct {
-    bool conv_limit_en;                      /*!<Enable the function of limiting ADC conversion times.
-                                                 If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
-    uint32_t conv_limit_num;                 /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
-    uint32_t adc1_pattern_len;               /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
-                                                 The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
-                                                 resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
-                                                 pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
-    uint32_t adc2_pattern_len;               /*!<Refer to ``adc1_pattern_len`` */
-    adc_digi_pattern_table_t *adc1_pattern;  /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
-    adc_digi_pattern_table_t *adc2_pattern;  /*!<Refer to `adc1_pattern` */
-    adc_digi_convert_mode_t conv_mode;       /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
-    adc_digi_output_format_t format;         /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
-    uint32_t interval;                       /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
-                                                 The unit is the divided clock. Range: 40 ~ 4095.
-                                                 Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
-                                                 Note: The sampling rate of each channel is also related to the conversion mode (See ``adc_digi_convert_mode_t``) and pattern table settings. */
-    adc_digi_clk_t dig_clk;                  /*!<ADC digital controller clock divider settings. Refer to ``adc_digi_clk_t``.
-                                                 Note: The clocks of the DAC digital controller use the ADC digital controller clock divider. */
-    uint32_t dma_eof_num;                    /*!<DMA eof num of adc digital controller.
-                                                 If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated in DMA.
-                                                 Note: The converted data in the DMA in link buffer will be multiple of two bytes. */
-} adc_digi_config_t __attribute__((deprecated));
-
-/**
- * @brief ADC digital controller (DMA mode) interrupt type options.
- */
-typedef enum {
-    ADC_DIGI_INTR_MASK_MONITOR = 0x1,
-    ADC_DIGI_INTR_MASK_MEAS_DONE = 0x2,
-    ADC_DIGI_INTR_MASK_ALL = 0x3,
-} adc_digi_intr_t __attribute__((deprecated));
-FLAG_ATTR(adc_digi_intr_t)
-#endif  //#if CONFIG_IDF_TARGET_ESP32S2
-
-
-#if CONFIG_IDF_TARGET_ESP32C3
-/*---------------------------------------------------------------
-                    ESP32C3 Deprecated Types
----------------------------------------------------------------*/
-/**
- * @brief ADC digital controller (DMA mode) conversion rules setting.
- */
-typedef struct {
-    union {
-        struct {
-            uint8_t atten:     2;   /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
-                                         0: measurement range 0 - 800mV,
-                                         1: measurement range 0 - 1100mV,
-                                         2: measurement range 0 - 1350mV,
-                                         3: measurement range 0 - 2600mV. */
-            uint8_t channel:   3;   /*!< ADC channel index. */
-            uint8_t unit:      1;   /*!< ADC unit index. */
-            uint8_t reserved:  2;   /*!< reserved0 */
-        };
-        uint8_t val;                /*!<Raw data value */
-    };
-} adc_digi_pattern_table_t __attribute__((deprecated));
-
-typedef struct {
-    bool conv_limit_en;                      /*!<Enable the function of limiting ADC conversion times.
-                                                 If the number of ADC conversion trigger count is equal to the `limit_num`, the conversion is stopped. */
-    uint32_t conv_limit_num;                 /*!<Set the upper limit of the number of ADC conversion triggers. Range: 1 ~ 255. */
-    uint32_t adc_pattern_len;                /*!<Pattern table length for digital controller. Range: 0 ~ 7 (0: Don't change the pattern table setting).
-                                                 The pattern table that defines the conversion rules for each SAR ADC. Each table has 7 items, in which channel selection,
-                                                 resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
-                                                 pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
-    adc_digi_pattern_table_t *adc_pattern;   /*!<Pointer to pattern table for digital controller. The table size defined by `adc_pattern_len`. */
-    uint32_t sample_freq_hz;  /*!< The expected ADC sampling frequency in Hz. Range: 611Hz ~ 83333Hz
-                                   Fs = Fd / interval / 2
-                                   Fs: sampling frequency;
-                                   Fd: digital controller frequency, no larger than 5M for better performance
-                                   interval: interval between 2 measurement trigger signal, the smallest interval should not be smaller than the ADC measurement period, the largest interval should not be larger than 4095 */
-} adc_digi_config_t __attribute__((deprecated));
-#endif  //#if CONFIG_IDF_TARGET_ESP32C3
-
-
-#ifdef __cplusplus
-}
-#endif

+ 128 - 0
components/driver/deprecated/driver/adc_types_legacy.h

@@ -0,0 +1,128 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+#include "hal/adc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief ADC resolution setting option.
+ * @note  Only used in single read mode
+ */
+typedef enum {
+#if CONFIG_IDF_TARGET_ESP32
+    ADC_WIDTH_BIT_9  = 9, /*!< ADC capture width is 9Bit. */
+    ADC_WIDTH_BIT_10 = 10, /*!< ADC capture width is 10Bit. */
+    ADC_WIDTH_BIT_11 = 11, /*!< ADC capture width is 11Bit. */
+    ADC_WIDTH_BIT_12 = 12, /*!< ADC capture width is 12Bit. */
+#elif SOC_ADC_RTC_MAX_BITWIDTH == 12
+    ADC_WIDTH_BIT_12 = 12, /*!< ADC capture width is 12Bit. */
+#elif SOC_ADC_RTC_MAX_BITWIDTH == 13
+    ADC_WIDTH_BIT_13 = 13, /*!< ADC capture width is 13Bit. */
+#endif
+    ADC_WIDTH_MAX,
+} adc_bits_width_t;
+
+/**
+ * The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth
+ * by `SOC_ADC_RTC_MAX_BITWIDTH` defined in soc_caps.h.
+ */
+#define ADC_WIDTH_BIT_DEFAULT    (ADC_WIDTH_MAX-1)
+
+#if CONFIG_IDF_TARGET_ESP32
+typedef enum {
+    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
+    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO37 */
+    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO38 */
+    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO39 */
+    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO32 */
+    ADC1_CHANNEL_5,     /*!< ADC1 channel 5 is GPIO33 */
+    ADC1_CHANNEL_6,     /*!< ADC1 channel 6 is GPIO34 */
+    ADC1_CHANNEL_7,     /*!< ADC1 channel 7 is GPIO35 */
+    ADC1_CHANNEL_MAX,
+} adc1_channel_t;
+#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+typedef enum {
+    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO1  */
+    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO2  */
+    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO3  */
+    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO4  */
+    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO5  */
+    ADC1_CHANNEL_5,     /*!< ADC1 channel 5 is GPIO6  */
+    ADC1_CHANNEL_6,     /*!< ADC1 channel 6 is GPIO7  */
+    ADC1_CHANNEL_7,     /*!< ADC1 channel 7 is GPIO8  */
+    ADC1_CHANNEL_8,     /*!< ADC1 channel 8 is GPIO9  */
+    ADC1_CHANNEL_9,     /*!< ADC1 channel 9 is GPIO10 */
+    ADC1_CHANNEL_MAX,
+} adc1_channel_t;
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H2
+typedef enum {
+    ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */
+    ADC1_CHANNEL_1,     /*!< ADC1 channel 1 is GPIO1 */
+    ADC1_CHANNEL_2,     /*!< ADC1 channel 2 is GPIO2 */
+    ADC1_CHANNEL_3,     /*!< ADC1 channel 3 is GPIO3 */
+    ADC1_CHANNEL_4,     /*!< ADC1 channel 4 is GPIO4 */
+    ADC1_CHANNEL_MAX,
+} adc1_channel_t;
+#endif // CONFIG_IDF_TARGET_*
+
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+typedef enum {
+    ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4  (ESP32), GPIO11 (ESP32-S2) */
+    ADC2_CHANNEL_1,     /*!< ADC2 channel 1 is GPIO0  (ESP32), GPIO12 (ESP32-S2) */
+    ADC2_CHANNEL_2,     /*!< ADC2 channel 2 is GPIO2  (ESP32), GPIO13 (ESP32-S2) */
+    ADC2_CHANNEL_3,     /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */
+    ADC2_CHANNEL_4,     /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */
+    ADC2_CHANNEL_5,     /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */
+    ADC2_CHANNEL_6,     /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */
+    ADC2_CHANNEL_7,     /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */
+    ADC2_CHANNEL_8,     /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */
+    ADC2_CHANNEL_9,     /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */
+    ADC2_CHANNEL_MAX,
+} adc2_channel_t;
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H2
+typedef enum {
+    ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
+    ADC2_CHANNEL_MAX,
+} adc2_channel_t;
+#endif
+
+#if SOC_ADC_DMA_SUPPORTED
+/**
+ * @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
+ */
+#define ADC_MAX_DELAY UINT32_MAX
+
+/**
+ * @brief ADC DMA driver configuration
+ */
+typedef struct adc_digi_init_config_s {
+    uint32_t max_store_buf_size;    ///< Max length of the converted data that driver can store before they are processed.
+    uint32_t conv_num_each_intr;    ///< Bytes of data that can be converted in 1 interrupt. This should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`.
+    uint32_t adc1_chan_mask;        ///< Channel list of ADC1 to be initialized.
+    uint32_t adc2_chan_mask;        ///< Channel list of ADC2 to be initialized.
+} adc_digi_init_config_t;
+
+/**
+ * @brief ADC digital controller settings
+ */
+typedef struct {
+    bool conv_limit_en;                     ///< Suggest leaving it empty, this parameter has been deprecated
+    uint32_t conv_limit_num;                ///< suggest leaving it empty, this parameter has been deprecated
+    uint32_t pattern_num;                   ///< Number of ADC channels that will be used
+    adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used
+    uint32_t sample_freq_hz;                /*!< Please refer to `soc/soc_caps.h` to know the ADC sampling frequency range*/
+    adc_digi_convert_mode_t conv_mode;      ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
+    adc_digi_output_format_t format;        ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
+} adc_digi_configuration_t;
+#endif // #if SOC_ADC_DMA_SUPPORTED
+
+#ifdef __cplusplus
+}
+#endif

+ 4 - 2
components/driver/deprecated/i2s_legacy.c

@@ -27,8 +27,10 @@
 #include "hal/i2s_hal.h"
 #if SOC_I2S_SUPPORTS_DAC
 #include "driver/dac.h"
-#include "driver/adc.h"
-#include "../adc1_private.h"
+#include "esp_private/adc_private.h"
+#include "adc1_private.h"
+#include "driver/adc_i2s_legacy.h"
+#include "driver/adc_types_legacy.h"
 #endif // SOC_I2S_SUPPORTS_ADC
 
 #if SOC_GDMA_SUPPORTED

+ 0 - 77
components/driver/esp32/adc.c

@@ -1,77 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdlib.h>
-#include <ctype.h>
-#include "sdkconfig.h"
-#include "esp_types.h"
-#include "esp_log.h"
-#include "sys/lock.h"
-#include "soc/rtc.h"
-#include "soc/periph_defs.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/xtensa_api.h"
-#include "freertos/semphr.h"
-#include "freertos/timers.h"
-#include "esp_intr_alloc.h"
-#include "driver/rtc_io.h"
-#include "esp_private/rtc_ctrl.h"
-#include "driver/gpio.h"
-#include "driver/adc.h"
-
-#ifndef NDEBUG
-// Enable built-in checks in queue.h in debug builds
-#define INVARIANTS
-#endif
-#include "sys/queue.h"
-#include "hal/adc_types.h"
-#include "hal/adc_hal.h"
-
-
-#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
-
-
-extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
-#define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
-#define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
-
-
-/*---------------------------------------------------------------
-                        HALL SENSOR
----------------------------------------------------------------*/
-
-static int hall_sensor_get_value(void)    //hall sensor without LNA
-{
-    int hall_value;
-
-    adc_power_acquire();
-
-    ADC_ENTER_CRITICAL();
-    /* disable other peripherals. */
-    adc_ll_amp_disable();
-    adc_ll_hall_enable();
-    // set controller
-    adc_ll_set_controller( ADC_UNIT_1, ADC_LL_CTRL_RTC );
-    hall_value = adc_hal_hall_convert();
-    adc_ll_hall_disable();
-    ADC_EXIT_CRITICAL();
-
-    adc_power_release();
-    return hall_value;
-}
-
-/**
- * To Be Deprecated
- */
-extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
-int hall_sensor_read(void)
-{
-    adc_common_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_0);
-    adc_common_gpio_init(ADC_UNIT_1, ADC1_CHANNEL_3);
-    adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
-    adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_0);
-    return hall_sensor_get_value();
-}

+ 0 - 135
components/driver/esp32s2/adc.c

@@ -1,135 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdlib.h>
-#include <ctype.h>
-#include "sdkconfig.h"
-#include "esp_types.h"
-#include "esp_log.h"
-#include "sys/lock.h"
-#include "freertos/FreeRTOS.h"
-#include "hal/adc_types.h"
-#include "hal/adc_ll.h"
-
-extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
-#define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
-#define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
-
-/**
- * Config monitor of adc digital controller.
- *
- * @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
- * @param adc_n ADC unit.
- * @param config Refer to ``adc_digi_monitor_t``.
- */
-static void adc_digi_monitor_config(adc_unit_t adc_n, adc_digi_monitor_t *config)
-{
-    adc_ll_digi_monitor_set_mode(adc_n, config->mode);
-    adc_ll_digi_monitor_set_thres(adc_n, config->threshold);
-}
-
-/*************************************/
-/* Digital controller filter setting */
-/*************************************/
-
-esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
-{
-    ADC_ENTER_CRITICAL();
-    if (idx == ADC_DIGI_FILTER_IDX0) {
-        adc_ll_digi_filter_reset(ADC_UNIT_1);
-    } else if (idx == ADC_DIGI_FILTER_IDX1) {
-        adc_ll_digi_filter_reset(ADC_UNIT_2);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
-{
-    ADC_ENTER_CRITICAL();
-    if (idx == ADC_DIGI_FILTER_IDX0) {
-        adc_ll_digi_filter_set_factor(ADC_UNIT_1, config->mode);
-    } else if (idx == ADC_DIGI_FILTER_IDX1) {
-        adc_ll_digi_filter_set_factor(ADC_UNIT_2, config->mode);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
-{
-    ADC_ENTER_CRITICAL();
-    if (idx == ADC_DIGI_FILTER_IDX0) {
-        config->adc_unit = ADC_UNIT_1;
-        config->channel = SOC_ADC_CHANNEL_NUM(0);
-        adc_ll_digi_filter_get_factor(ADC_UNIT_1, &config->mode);
-    } else if (idx == ADC_DIGI_FILTER_IDX1) {
-        config->adc_unit = ADC_UNIT_2;
-        config->channel = SOC_ADC_CHANNEL_NUM(1);
-        adc_ll_digi_filter_get_factor(ADC_UNIT_2, &config->mode);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
-{
-    ADC_ENTER_CRITICAL();
-    if (idx == ADC_DIGI_FILTER_IDX0) {
-        adc_ll_digi_filter_enable(ADC_UNIT_1, enable);
-    } else if (idx == ADC_DIGI_FILTER_IDX1) {
-        adc_ll_digi_filter_enable(ADC_UNIT_2, enable);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-/**
- * @brief Get the filtered data of adc digital controller filter. For debug.
- *        The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API.
- *
- * @note For ESP32S2, The filter will filter all the enabled channel data of the each ADC unit at the same time.
- * @param idx Filter index.
- * @return Filtered data. if <0, the read data invalid.
- */
-int adc_digi_filter_read_data(adc_digi_filter_idx_t idx)
-{
-    if (idx == ADC_DIGI_FILTER_IDX0) {
-        return adc_ll_digi_filter_read_data(ADC_UNIT_1);
-    } else if (idx == ADC_DIGI_FILTER_IDX1) {
-        return adc_ll_digi_filter_read_data(ADC_UNIT_2);
-    } else {
-        return -1;
-    }
-}
-
-/**************************************/
-/* Digital controller monitor setting */
-/**************************************/
-
-esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
-{
-    ADC_ENTER_CRITICAL();
-    if (idx == ADC_DIGI_MONITOR_IDX0) {
-        adc_digi_monitor_config(ADC_UNIT_1, config);
-    } else if (idx == ADC_DIGI_MONITOR_IDX1) {
-        adc_digi_monitor_config(ADC_UNIT_2, config);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}
-
-esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
-{
-    ADC_ENTER_CRITICAL();
-    if (idx == ADC_DIGI_MONITOR_IDX0) {
-        adc_ll_digi_monitor_enable(ADC_UNIT_1, enable);
-    } else if (idx == ADC_DIGI_MONITOR_IDX1) {
-        adc_ll_digi_monitor_enable(ADC_UNIT_2, enable);
-    }
-    ADC_EXIT_CRITICAL();
-    return ESP_OK;
-}

+ 1 - 0
components/driver/i2s/i2s_common.c

@@ -27,6 +27,7 @@
 
 #if SOC_I2S_SUPPORTS_ADC_DAC
 #include "hal/adc_ll.h"
+#include "driver/adc_i2s_legacy.h"
 #endif
 #if SOC_I2S_SUPPORTS_APLL
 #include "clk_ctrl_os.h"

+ 0 - 11
components/driver/include/driver/adc_common.h

@@ -1,11 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/**
- * This file is only a wrapper for `driver/adc.h` for back-compatability.
- */
-
-#include "adc.h"

+ 0 - 32
components/driver/include/esp_private/adc_cali.h

@@ -1,32 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-// Internal header for calibration, don't use in app
-
-#include "sdkconfig.h"
-#include "esp_err.h"
-#include "hal/adc_hal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if !CONFIG_IDF_TARGET_ESP32
-
-/**
- * @brief Calibrate the offset of ADC. (Based on the pre-stored efuse or actual calibration)
- *
- * @param adc_n ADC unit to calibrate
- * @param atten Attenuation to use
- * @return Always ESP_OK
- */
-extern esp_err_t adc_cal_offset(adc_unit_t adc_n, adc_atten_t atten);
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif

+ 2 - 2
components/driver/test/CMakeLists.txt

@@ -1,4 +1,4 @@
-idf_component_register(SRC_DIRS . param_test touch_sensor_test adc_dma_test dac_dma_test
+idf_component_register(SRC_DIRS . param_test touch_sensor_test dac_dma_test
                        PRIV_INCLUDE_DIRS include param_test/include touch_sensor_test/include
                        PRIV_REQUIRES cmock test_utils driver nvs_flash esp_serial_slave_link
-                                     esp_adc_cal esp_timer)
+                                     esp_timer esp_adc)

+ 0 - 654
components/driver/test/adc_dma_test/test_esp32s2.c

@@ -1,654 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/*
- Tests for the adc device driver on ESP32-S2 only
-*/
-#include "sdkconfig.h"
-#include "unity.h"
-#include "test_utils.h"
-
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)    //TODO: IDF-3160
-#if CONFIG_IDF_TARGET_ESP32S2
-
-
-#include "esp_system.h"
-#include "esp_intr_alloc.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "freertos/queue.h"
-#include "driver/adc.h"
-#include "driver/rtc_io.h"
-#include "driver/gpio.h"
-#include "unity.h"
-#include "esp_system.h"
-#include "esp_event.h"
-#include "esp_wifi.h"
-#include "esp_log.h"
-#include "nvs_flash.h"
-#include "test_utils.h"
-#include "soc/adc_periph.h"
-#include "test/test_common_adc.h"
-#include "esp_rom_sys.h"
-#include "driver/dac.h"
-
-#include "soc/system_reg.h"
-#include "soc/spi_reg.h"
-#include "soc/soc.h"
-#include "soc/lldesc.h"
-#include "test/test_adc_dac_dma.h"
-
-#include "driver/adc_deprecated.h"
-#include "hal/adc_ll.h"
-#include "esp_pm.h"
-
-static const char *TAG = "test_adc";
-
-#define PLATFORM_SELECT            (1)  //0: pxp; 1: chip
-#if (PLATFORM_SELECT == 0)              //PXP platform
-#include "soc/syscon_reg.h"
-#define SET_BREAK_POINT(flag) REG_WRITE(SYSCON_DATE_REG, flag)
-//PXP clk is slower.
-#define SYS_DELAY_TIME_MOM    (1/40)
-#define RTC_SLOW_CLK_FLAG     1     // Slow clock is 32KHz.
-static void test_pxp_deinit_io(void)
-{
-    for (int i = 0; i < 22; i++) {
-        rtc_gpio_init(i);
-    }
-}
-#else
-//PXP clk is slower.
-#define SET_BREAK_POINT(flag)
-#define SYS_DELAY_TIME_MOM    (1)
-#define RTC_SLOW_CLK_FLAG     0     // Slow clock is 32KHz.
-#endif
-
-#define ADC_REG_BASE_TEST() ({    \
-   TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(APB_SARADC_APB_CTRL_DATE_REG, APB_SARADC_APB_CTRL_DATE), APB_SARADC.apb_ctrl_date);   \
-   TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(SENS_SARDATE_REG, SENS_SAR_DATE), SENS.sardate.sar_date);     \
-   TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_IO_DATE_REG, RTC_IO_IO_DATE), RTCIO.date.date);           \
-})
-/** Sample rate = APB_CLK(80 MHz) / (CLK_DIV + 1) / TRIGGER_INTERVAL / 2. */
-#define TEST_ADC_TRIGGER_INTERVAL_DEFAULT (40)
-#define TEST_ADC_DIGI_CLK_DIV_DEFAULT     (9)
-static uint8_t adc_test_num = 9;
-static adc_channel_t adc_list[SOC_ADC_PATT_LEN_MAX] = {
-    ADC_CHANNEL_0,
-    ADC_CHANNEL_1,
-    ADC_CHANNEL_2,
-    ADC_CHANNEL_3,
-    ADC_CHANNEL_4,
-    ADC_CHANNEL_5,
-    ADC_CHANNEL_6,
-    // ADC_CHANNEL_7, // Workaround: IO18 is pullup outside in ESP32S2-Saola Runner.
-    ADC_CHANNEL_8,
-    ADC_CHANNEL_9,
-};
-/* For ESP32S2, it should use same atten, or, it will have error. */
-#define TEST_ADC_ATTEN_DEFAULT (ADC_ATTEN_11db)
-
-
-/* Work mode.
- * single: eof_num;
- * double: SAR_EOF_NUMBER/2;
- * alter: eof_num;
- * */
-#define SAR_SIMPLE_NUM  512  // Set sample number of enabled unit.
-/* Use two DMA linker to save ADC data. ADC sample 1 times -> 2 byte data -> 2 DMA link buf. */
-#define SAR_DMA_DATA_SIZE(unit, sample_num)     (SAR_EOF_NUMBER(unit, sample_num))
-#define SAR_EOF_NUMBER(unit, sample_num)        ((sample_num) * (unit))
-#define SAR_MEAS_LIMIT_NUM(unit, sample_num)    (SAR_SIMPLE_NUM)
-#define SAR_SIMPLE_TIMEOUT_MS  1000
-
-typedef struct dma_msg {
-    uint32_t int_msk;
-    uint8_t *data;
-    uint32_t data_len;
-} adc_dma_event_t;
-
-static uint8_t link_buf[2][SAR_DMA_DATA_SIZE(2, SAR_SIMPLE_NUM)] = {0};
-static lldesc_t dma1 = {0};
-static lldesc_t dma2 = {0};
-static QueueHandle_t que_adc = NULL;
-static adc_dma_event_t adc_evt;
-
-/**
- * @brief Reset FSM of adc digital controller.
- *
- * @return
- *      - ESP_OK Success
- */
-static esp_err_t adc_digi_reset(void)
-{
-    adc_ll_digi_reset();
-    adc_ll_digi_clear_pattern_table(ADC_NUM_1);
-    adc_ll_digi_clear_pattern_table(ADC_NUM_2);
-    return ESP_OK;
-}
-
-/** ADC-DMA ISR handler. */
-static IRAM_ATTR void adc_dma_isr(void *arg)
-{
-    uint32_t int_st = REG_READ(SPI_DMA_INT_ST_REG(3));
-    int task_awoken = pdFALSE;
-    REG_WRITE(SPI_DMA_INT_CLR_REG(3), int_st);
-    if (int_st & SPI_IN_SUC_EOF_INT_ST_M) {
-        adc_evt.int_msk = int_st;
-        xQueueSendFromISR(que_adc, &adc_evt, &task_awoken);
-    }
-    if (int_st & SPI_IN_DONE_INT_ST) {
-        adc_evt.int_msk = int_st;
-        xQueueSendFromISR(que_adc, &adc_evt, &task_awoken);
-    }
-    ESP_EARLY_LOGV(TAG, "int msk%x\n", int_st);
-    if (task_awoken == pdTRUE) {
-        portYIELD_FROM_ISR();
-    }
-}
-
-/**
- * DMA liner initialization and start.
- * @param is_loop
- *     - true: The two dma linked lists are connected end to end, with no end mark (eof).
- *     - false: The two dma linked lists are connected end to end, with end mark (eof).
- */
-static uint32_t adc_dma_linker_init(adc_unit_t adc, bool is_loop)
-{
-    dma1 = (lldesc_t) {
-        .size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM),
-        .owner = 1,
-        .buf = &link_buf[0][0],
-        .qe.stqe_next = &dma2,
-    };
-    dma2 = (lldesc_t) {
-        .size = SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM),
-        .owner = 1,
-        .buf = &link_buf[1][0],
-    };
-    if (is_loop) {
-        dma2.qe.stqe_next = &dma1;
-    } else {
-        dma2.qe.stqe_next = NULL;
-    }
-    return (uint32_t)&dma1;
-}
-
-#define DEBUG_CHECK_ENABLE  1
-#define DEBUG_PRINT_ENABLE  1
-#define DEBUG_CHECK_ERROR   10
-
-/**
- * Check the ADC-DMA data in linker buffer by input level.
- * ideal_level
- *     - -1: Don't check data.
- *     -  0: ADC channel voltage is 0v.
- *     -  1: ADC channel voltage is 3.3v.
- *     -  2: ADC channel voltage is 1.4v.
- */
-static esp_err_t adc_dma_data_check(adc_unit_t adc, int ideal_level)
-{
-    int unit_old = 1;
-    int ch_cnt = 0;
-    for (int cnt = 0; cnt < 2; cnt++) {
-        esp_rom_printf("\n[%s] link_buf[%d]: \n", __func__, cnt % 2);
-        for (int i = 0; i < SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); i += 2) {
-            uint8_t h = link_buf[cnt % 2][i + 1], l = link_buf[cnt % 2][i];
-            uint16_t temp = (h << 8 | l);
-            adc_digi_output_data_t *data = (adc_digi_output_data_t *)&temp;
-
-            if (adc > ADC_UNIT_2) {  //ADC_ENCODE_11BIT
-#if DEBUG_PRINT_ENABLE
-                if (i % 16 == 0) {
-                    esp_rom_printf("\n");
-                }
-                esp_rom_printf("[%d_%d_%04x] ", data->type2.unit, data->type2.channel, data->type2.data);
-#endif
-#if DEBUG_CHECK_ENABLE
-                if (ideal_level >= 0) {
-                    TEST_ASSERT_NOT_EQUAL(unit_old, data->type2.unit);
-                    unit_old = data->type2.unit;
-                    if (data->type2.channel > ADC_CHANNEL_MAX) {
-                        printf("Data invalid [%d]\n", data->type2.channel);
-                        continue;
-                    }
-                    int cur_ch = ((ch_cnt++ / 2) % adc_test_num);
-                    TEST_ASSERT_EQUAL( data->type2.channel, adc_list[cur_ch] );
-                }
-                if (ideal_level == 1) {         // high level 3.3v
-                    TEST_ASSERT_EQUAL( 0x7FF, data->type2.data );
-                } else if (ideal_level == 0) {  // low level 0v
-                    TEST_ASSERT_LESS_THAN( 10, data->type2.data );
-                } else if (ideal_level == 2) {  // middle level 1.4v
-                    TEST_ASSERT_INT_WITHIN( 128, 1100, data->type2.data );
-                } else if (ideal_level == 3) {  // normal level
-                } else { // no check
-                }
-#endif
-            } else {        //ADC_ENCODE_12BIT
-#if DEBUG_PRINT_ENABLE
-                if (i % 16 == 0) {
-                    esp_rom_printf("\n");
-                }
-                esp_rom_printf("[%d_%04x] ", data->type1.channel, data->type1.data);
-#endif
-#if DEBUG_CHECK_ENABLE
-                if (ideal_level >= 0) {
-                    int cur_ch = ((ch_cnt++) % adc_test_num);
-                    TEST_ASSERT_EQUAL( adc_list[cur_ch], data->type1.channel );
-                }
-                if (ideal_level == 1) {         // high level 3.3v
-                    TEST_ASSERT_EQUAL( 0XFFF, data->type1.data );
-                } else if (ideal_level == 0) {  // low level 0v
-                    TEST_ASSERT_LESS_THAN( 10, data->type1.data );
-                } else if (ideal_level == 2) {  // middle level 1.4v
-                    TEST_ASSERT_INT_WITHIN( 256, 2200, data->type1.data );
-                } else if (ideal_level == 3) {  // normal level
-                } else { // no check
-                }
-#endif
-            }
-            link_buf[cnt % 2][i] = 0;
-            link_buf[cnt % 2][i + 1] = 0;
-        }
-        esp_rom_printf("\n");
-    }
-    return ESP_OK;
-}
-
-static esp_err_t adc_dma_data_multi_st_check(adc_unit_t adc, void *dma_addr, uint32_t int_mask)
-{
-    adc_dma_event_t evt;
-
-    ESP_LOGI(TAG, "adc IO normal, test ...");
-    for (int i = 0; i < adc_test_num; i++) {
-        adc_io_normal(adc, adc_list[i]);
-    }
-    TEST_ESP_OK( adc_digi_start() );
-    while (1) {
-        TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_PERIOD_MS), pdTRUE );
-        if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) {
-            break;
-        }
-    }
-    TEST_ESP_OK( adc_digi_stop() );
-    adc_dac_dma_linker_start(DMA_ONLY_ADC_INLINK, (void *)dma_addr, int_mask);
-    adc_digi_reset();
-    TEST_ESP_OK( adc_dma_data_check(adc, -1) ); // Don't check data.
-
-    ESP_LOGI(TAG, "adc IO fake tie high, test ...");
-    for (int i = 0; i < adc_test_num; i++) {
-        adc_fake_tie_high(adc, adc_list[i]);
-    }
-    TEST_ESP_OK( adc_digi_start() );
-    while (1) {
-        TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_PERIOD_MS), pdTRUE );
-        if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) {
-            break;
-        }
-    }
-    TEST_ESP_OK( adc_digi_stop() );
-    adc_dac_dma_linker_start(DMA_ONLY_ADC_INLINK, (void *)dma_addr, int_mask);
-    adc_digi_reset();
-    TEST_ESP_OK( adc_dma_data_check(adc, 1) );
-
-    ESP_LOGI(TAG, "adc IO fake tie low, test ...");
-    for (int i = 0; i < adc_test_num; i++) {
-        adc_fake_tie_low(adc, adc_list[i]);
-    }
-    TEST_ESP_OK( adc_digi_start() );
-    while (1) {
-        TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_PERIOD_MS), pdTRUE );
-        if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) {
-            break;
-        }
-    }
-    TEST_ESP_OK( adc_digi_stop() );
-    adc_dac_dma_linker_start(DMA_ONLY_ADC_INLINK, (void *)dma_addr, int_mask);
-    adc_digi_reset();
-    TEST_ESP_OK( adc_dma_data_check(adc, 0) );
-
-    ESP_LOGI(TAG, "adc IO fake tie middle, test ...");
-    for (int i = 0; i < adc_test_num; i++) {
-        adc_fake_tie_middle(adc, adc_list[i]);
-    }
-    TEST_ESP_OK( adc_digi_start() );
-    while (1) {
-        TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, SAR_SIMPLE_TIMEOUT_MS / portTICK_PERIOD_MS), pdTRUE );
-        if (evt.int_msk & SPI_IN_SUC_EOF_INT_ENA) {
-            break;
-        }
-    }
-    TEST_ESP_OK( adc_digi_stop() );
-    adc_dac_dma_linker_start(DMA_ONLY_ADC_INLINK, (void *)dma_addr, int_mask);
-    adc_digi_reset();
-    TEST_ESP_OK( adc_dma_data_check(adc, 2) );
-
-    return ESP_OK;
-}
-
-#include "soc/apb_saradc_struct.h"
-/**
- * Test the partten table setting. It's easy wrong.
- *
- * @param adc_n ADC unit.
- * @param in_partten_len The length of partten be set.
- * @param in_last_ch The channel number of the last message.
- */
-static esp_err_t adc_check_patt_table(adc_unit_t adc, uint32_t in_partten_len, adc_channel_t in_last_ch)
-{
-    esp_err_t ret = ESP_FAIL;
-    uint8_t index = (in_partten_len - 1) / 4;
-    uint8_t offset = 24 - ((in_partten_len - 1) % 4) * 8;
-    uint32_t temp = 0, len;
-
-    if (adc & ADC_UNIT_1) {
-        len = APB_SARADC.ctrl.sar1_patt_len + 1;
-        temp = APB_SARADC.sar1_patt_tab[index];
-        printf("patt1 len %d\n", len);
-        printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[0]);
-        printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[1]);
-        printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[2]);
-        printf("patt1 0x%08x\n", APB_SARADC.sar1_patt_tab[3]);
-        if (in_partten_len == len) {
-            if (in_last_ch == (((temp >> (offset + 4))) & 0xf)) {
-                ret = ESP_OK;
-            }
-        }
-    }
-    if (adc & ADC_UNIT_2) {
-        len = APB_SARADC.ctrl.sar2_patt_len + 1;
-        temp = APB_SARADC.sar2_patt_tab[index];
-        printf("patt2 len %d\n", len);
-        printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[0]);
-        printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[1]);
-        printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[2]);
-        printf("patt2 0x%08x\n", APB_SARADC.sar2_patt_tab[3]);
-        if (in_partten_len == len) {
-            if (in_last_ch == (((temp >> (offset + 4))) & 0xf)) {
-                ret = ESP_OK;
-            }
-        }
-    }
-    return ret;
-}
-
-/**
- * Testcase: Check the base function of ADC-DMA. Include:
- * - Various conversion modes.
- * - Whether the channel and data are lost.
- * - Whether the data is the same as the channel voltage.
- */
-int test_adc_dig_dma_single_unit(adc_unit_t adc)
-{
-    ESP_LOGI(TAG, "  >> %s <<  ", __func__);
-    ESP_LOGI(TAG, "  >> adc unit: %x <<  ", adc);
-
-    TEST_ESP_OK( adc_digi_init() );
-    /* arbiter config */
-    adc_arbiter_t arb_cfg = {
-        .mode = ADC_ARB_MODE_FIX,
-        .dig_pri = 0,
-        .pwdet_pri = 2,
-        .rtc_pri = 1,
-    };
-    TEST_ESP_OK( adc_arbiter_config(ADC_UNIT_2, &arb_cfg) );   // If you want use force
-
-    adc_digi_config_t config = {
-        .conv_limit_en = false,
-        .conv_limit_num = 0,
-        .interval = TEST_ADC_TRIGGER_INTERVAL_DEFAULT,
-        .dig_clk.use_apll = 0,  // APB clk
-        .dig_clk.div_num = TEST_ADC_DIGI_CLK_DIV_DEFAULT,
-        .dig_clk.div_b = 0,
-        .dig_clk.div_a = 0,
-        .dma_eof_num = SAR_EOF_NUMBER((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM),
-    };
-    /* Config pattern table */
-    adc_digi_pattern_table_t adc1_patt[SOC_ADC_PATT_LEN_MAX] = {0};
-    adc_digi_pattern_table_t adc2_patt[SOC_ADC_PATT_LEN_MAX] = {0};
-    if (adc & ADC_UNIT_1) {
-        config.adc1_pattern_len = adc_test_num;
-        config.adc1_pattern = adc1_patt;
-        for (int i = 0; i < adc_test_num; i++) {
-            adc1_patt[i].atten = TEST_ADC_ATTEN_DEFAULT;
-            adc1_patt[i].channel = adc_list[i];
-            adc_gpio_init(ADC_UNIT_1, adc_list[i]);
-        }
-    }
-    if (adc & ADC_UNIT_2) {
-        config.adc2_pattern_len = adc_test_num;
-        config.adc2_pattern = adc2_patt;
-        for (int i = 0; i < adc_test_num; i++) {
-            adc2_patt[i].atten = TEST_ADC_ATTEN_DEFAULT;
-            adc2_patt[i].channel = adc_list[i];
-            adc_gpio_init(ADC_UNIT_2, adc_list[i]);
-        }
-    }
-    if (adc == ADC_UNIT_1) {
-        config.conv_mode = ADC_CONV_SINGLE_UNIT_1;
-        config.format = ADC_DIGI_FORMAT_12BIT;
-    } else if (adc == ADC_UNIT_2) {
-        config.conv_mode = ADC_CONV_SINGLE_UNIT_2;
-        config.format = ADC_DIGI_FORMAT_12BIT;
-    } else if (adc == ADC_UNIT_BOTH) {
-        config.conv_mode = ADC_CONV_BOTH_UNIT;
-        config.format = ADC_DIGI_FORMAT_11BIT;
-    } else if (adc == ADC_UNIT_ALTER) {
-        config.conv_mode = ADC_CONV_ALTER_UNIT;
-        config.format = ADC_DIGI_FORMAT_11BIT;
-    }
-    TEST_ESP_OK( adc_digi_controller_config(&config) );
-
-    /* ADC-DMA linker init */
-    if (que_adc == NULL) {
-        que_adc = xQueueCreate(5, sizeof(adc_dma_event_t));
-    } else {
-        xQueueReset(que_adc);
-    }
-    uint32_t int_mask = SPI_IN_SUC_EOF_INT_ENA;
-    uint32_t dma_addr = adc_dma_linker_init(adc, false);
-    adc_dac_dma_isr_register(adc_dma_isr, NULL, int_mask);
-    adc_dac_dma_linker_start(DMA_ONLY_ADC_INLINK, (void *)dma_addr, int_mask);
-
-    TEST_ESP_OK( adc_check_patt_table(adc, adc_test_num, adc_list[adc_test_num - 1]) );
-    adc_dma_data_multi_st_check(adc, (void *)dma_addr, int_mask);
-
-    adc_dac_dma_linker_deinit();
-    adc_dac_dma_isr_deregister(adc_dma_isr, NULL);
-    TEST_ESP_OK( adc_digi_deinit() );
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-
-    return 0;
-}
-
-TEST_CASE("ADC DMA single read", "[ADC]")
-{
-    test_adc_dig_dma_single_unit(ADC_UNIT_BOTH);
-
-    test_adc_dig_dma_single_unit(ADC_UNIT_ALTER);
-
-    test_adc_dig_dma_single_unit(ADC_UNIT_1);
-
-    test_adc_dig_dma_single_unit(ADC_UNIT_2);
-}
-
-#include "touch_scope.h"
-/**
- * 0: ADC1 channels raw data debug.
- * 1: ADC2 channels raw data debug.
- * 2: ADC1 one channel raw data debug.
- */
-#define SCOPE_DEBUG_TYPE            0
-#define SCOPE_DEBUG_CHANNEL_MAX    (10)
-#define SCOPE_DEBUG_ENABLE         (0)
-#define SCOPE_UART_BUADRATE        (256000)
-#define SCOPE_DEBUG_FREQ_MS        (50)
-#define SCOPE_OUTPUT_UART          (0)
-static float scope_temp[SCOPE_DEBUG_CHANNEL_MAX] = {0};  // max scope channel is 10.
-
-int test_adc_dig_scope_debug_unit(adc_unit_t adc)
-{
-    ESP_LOGI(TAG, "  >> %s <<  ", __func__);
-    ESP_LOGI(TAG, "  >> adc unit: %x <<  ", adc);
-
-    TEST_ESP_OK( adc_digi_init() );
-    if (adc & ADC_UNIT_2) {
-        /* arbiter config */
-        adc_arbiter_t arb_cfg = {
-            .mode = ADC_ARB_MODE_FIX,
-            .dig_pri = 0,
-            .pwdet_pri = 2,
-            .rtc_pri = 1,
-        };
-        TEST_ESP_OK( adc_arbiter_config(ADC_UNIT_2, &arb_cfg) );   // If you want use force
-    }
-    adc_digi_config_t config = {
-        .conv_limit_en = false,
-        .conv_limit_num = 0,
-        .interval = TEST_ADC_TRIGGER_INTERVAL_DEFAULT,
-        .dig_clk.use_apll = 0,  // APB clk
-        .dig_clk.div_num = TEST_ADC_DIGI_CLK_DIV_DEFAULT,
-        .dig_clk.div_a = 0,
-        .dig_clk.div_b = 0,
-        .dma_eof_num = SAR_EOF_NUMBER((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM),
-    };
-    /* Config pattern table */
-    adc_digi_pattern_table_t adc1_patt[SOC_ADC_PATT_LEN_MAX] = {0};
-    adc_digi_pattern_table_t adc2_patt[SOC_ADC_PATT_LEN_MAX] = {0};
-    if (adc & ADC_UNIT_1) {
-        config.adc1_pattern_len = adc_test_num;
-        config.adc1_pattern = adc1_patt;
-        for (int i = 0; i < adc_test_num; i++) {
-            adc1_patt[i].atten = TEST_ADC_ATTEN_DEFAULT;
-            adc1_patt[i].channel = adc_list[i];
-            adc_gpio_init(ADC_UNIT_1, adc_list[i]);
-        }
-    }
-    if (adc & ADC_UNIT_2) {
-        config.adc2_pattern_len = adc_test_num;
-        config.adc2_pattern = adc2_patt;
-        for (int i = 0; i < adc_test_num; i++) {
-            adc2_patt[i].atten = TEST_ADC_ATTEN_DEFAULT;
-            adc2_patt[i].channel = adc_list[i];
-            adc_gpio_init(ADC_UNIT_2, adc_list[i]);
-        }
-    }
-    if (adc == ADC_UNIT_1) {
-        config.conv_mode = ADC_CONV_SINGLE_UNIT_1;
-        config.format = ADC_DIGI_FORMAT_12BIT;
-    } else if (adc == ADC_UNIT_2) {
-        config.conv_mode = ADC_CONV_SINGLE_UNIT_2;
-        config.format = ADC_DIGI_FORMAT_12BIT;
-    } else if (adc == ADC_UNIT_BOTH) {
-        config.conv_mode = ADC_CONV_BOTH_UNIT;
-        config.format = ADC_DIGI_FORMAT_11BIT;
-    } else if (adc == ADC_UNIT_ALTER) {
-        config.conv_mode = ADC_CONV_ALTER_UNIT;
-        config.format = ADC_DIGI_FORMAT_11BIT;
-    }
-    TEST_ESP_OK( adc_digi_controller_config(&config) );
-
-        /* ADC-DMA linker init */
-    if (que_adc == NULL) {
-        que_adc = xQueueCreate(5, sizeof(adc_dma_event_t));
-    } else {
-        xQueueReset(que_adc);
-    }
-    uint32_t int_mask = SPI_IN_SUC_EOF_INT_ENA;
-    uint32_t dma_addr = adc_dma_linker_init(adc, false);
-    adc_dac_dma_isr_register(adc_dma_isr, NULL, int_mask);
-    adc_dac_dma_linker_start(DMA_ONLY_ADC_INLINK, (void *)dma_addr, int_mask);
-
-    ESP_LOGI(TAG, "adc IO fake tie middle, test ...");
-    for (int i = 0; i < adc_test_num; i++) {
-        adc_fake_tie_middle(adc, adc_list[i]);
-    }
-
-    return 0;
-}
-
-static void scope_output(int adc_num, int channel, int data)
-{
-    /** can replace by uart log.*/
-#if SCOPE_OUTPUT_UART
-    static int icnt = 0;
-    if (icnt++ % 8 == 0) {
-        esp_rom_printf("\n");
-    }
-    esp_rom_printf("[%d_%d_%04x] ", adc_num, channel, data);
-    return;
-#endif
-#if SCOPE_DEBUG_TYPE == 0
-    if (adc_num != 0) {
-        return;
-    }
-#elif SCOPE_DEBUG_TYPE == 1
-    if (adc_num != 1) {
-        return;
-    }
-#endif
-    int i;
-    /* adc Read */
-    for (i = 0; i < adc_test_num; i++) {
-        if (adc_list[i] == channel && scope_temp[i] == 0) {
-            scope_temp[i] = data;
-            break;
-        }
-    }
-    if (i == adc_test_num) {
-        test_tp_print_to_scope(scope_temp, adc_test_num);
-        vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_PERIOD_MS);
-        for (int i = 0; i < adc_test_num; i++) {
-            scope_temp[i] = 0;
-        }
-    }
-}
-
-/**
- * Manual test: Capture ADC-DMA data and display it on the serial oscilloscope. Used to observe the stability of the data.
- * Use step:
- *      1. Run this test from the unit test app.
- *      2. Use `ESP-Tuning Tool`(download from `www.espressif.com`) to capture.
- *      3. The readings of multiple channels will be displayed on the tool.
- */
-TEST_CASE("test_adc_digi_slope_debug", "[adc_dma][ignore]")
-{
-    adc_dma_event_t evt;
-    test_tp_scope_debug_init(0, -1, -1, SCOPE_UART_BUADRATE);
-    adc_unit_t adc = ADC_CONV_BOTH_UNIT;
-    test_adc_dig_scope_debug_unit(adc);
-    while (1) {
-        TEST_ESP_OK( adc_digi_start() );
-        TEST_ASSERT_EQUAL( xQueueReceive(que_adc, &evt, portMAX_DELAY), pdTRUE );
-        if (evt.int_msk & SPI_IN_SUC_EOF_INT_ST) {
-            TEST_ESP_OK( adc_digi_stop() );
-            adc_digi_reset();
-            for (int cnt = 0; cnt < 2; cnt++) {
-                esp_rom_printf("cnt%d\n", cnt);
-                for (int i = 0; i < SAR_DMA_DATA_SIZE((adc > 2) ? 2 : 1, SAR_SIMPLE_NUM); i += 2) {
-                    uint8_t h = link_buf[cnt % 2][i + 1], l = link_buf[cnt % 2][i];
-                    uint16_t temp = (h << 8 | l);
-                    adc_digi_output_data_t *data = (adc_digi_output_data_t *)&temp;
-                    if (adc > ADC_UNIT_2) {  //ADC_ENCODE_11BIT
-                        scope_output(data->type2.unit, data->type2.channel, data->type2.data);
-                    } else {        //ADC_ENCODE_12BIT
-                        if (adc == ADC_UNIT_1) {
-                            scope_output(0, data->type1.channel, data->type1.data);
-                        } else if (adc == ADC_UNIT_2) {
-                            scope_output(1, data->type1.channel, data->type1.data);
-                        }
-                    }
-                    link_buf[cnt % 2][i] = 0;
-                    link_buf[cnt % 2][i + 1] = 0;
-                }
-            }
-        }
-    }
-}
-
-#endif // CONFIG_IDF_TARGET_ESP32S2
-#endif  //#if !DISABLED_FOR_TARGETS(ESP32S2)

+ 0 - 1
components/driver/test/dac_dma_test/test_esp32s2.c

@@ -15,7 +15,6 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/queue.h"
-#include "driver/adc.h"
 #include "driver/rtc_io.h"
 #include "driver/gpio.h"
 #include "unity.h"

+ 1 - 1
components/driver/test/include/test/test_common_adc.h

@@ -6,7 +6,7 @@
 
 #pragma once
 
-#include "driver/adc.h"
+#include "hal/adc_types.h"
 
 /**@{*/
 /**

+ 0 - 608
components/driver/test/test_adc.c

@@ -1,608 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include "sdkconfig.h"
-#include <sys/param.h>
-#include <string.h>
-#include "esp_log.h"
-#include "test_utils.h"
-#include "esp_adc_cal.h"
-#include "driver/adc_common.h"
-#include "esp_cpu.h"
-
-__attribute__((unused)) static const char *TAG = "ADC";
-
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2)
-//TODO: IDF-3160
-
-#define TEST_COUNT      4096
-#define MAX_ARRAY_SIZE  4096
-#define TEST_ATTEN      ADC_ATTEN_MAX //Set to ADC_ATTEN_*db to test a single attenuation       only
-
-static int s_adc_count[MAX_ARRAY_SIZE]={};
-static int s_adc_offset = -1;
-
-static int insert_point(uint32_t value)
-{
-    const bool fixed_size = true;
-
-    if (s_adc_offset < 0) {
-        if (fixed_size) {
-            TEST_ASSERT_GREATER_OR_EQUAL(4096, MAX_ARRAY_SIZE);
-            s_adc_offset = 0;   //Fixed to 0 because the array can hold all the data in 12 bits
-        } else {
-            s_adc_offset = MAX((int)value - MAX_ARRAY_SIZE/2, 0);
-        }
-    }
-
-    if (!fixed_size && (value < s_adc_offset || value >= s_adc_offset + MAX_ARRAY_SIZE)) {
-        TEST_ASSERT_GREATER_OR_EQUAL(s_adc_offset, value);
-        TEST_ASSERT_LESS_THAN(s_adc_offset + MAX_ARRAY_SIZE, value);
-    }
-
-    s_adc_count[value - s_adc_offset] ++;
-    return value - s_adc_offset;
-}
-
-static void reset_array(void)
-{
-    memset(s_adc_count, 0, sizeof(s_adc_count));
-    s_adc_offset = -1;
-}
-
-static uint32_t get_average(void)
-{
-    uint32_t sum = 0;
-    int count = 0;
-    for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
-        sum += s_adc_count[i] * (s_adc_offset+i);
-        count += s_adc_count[i];
-    }
-    return sum/count;
-}
-
-static void print_summary(bool figure)
-{
-    const int MAX_WIDTH=20;
-    int max_count = 0;
-    int start = -1;
-    int end = -1;
-    uint32_t sum = 0;
-    int count = 0;
-    for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
-        if (s_adc_count[i] > max_count) {
-            max_count = s_adc_count[i];
-        }
-        if (s_adc_count[i] > 0 && start < 0) {
-            start = i;
-        }
-        if (s_adc_count[i] > 0) {
-            end = i;
-        }
-        count += s_adc_count[i];
-        sum += s_adc_count[i] * (s_adc_offset+i);
-    }
-
-    if (figure) {
-        for (int i = start; i <= end; i++) {
-            printf("%4d ", i+s_adc_offset);
-            int count = s_adc_count[i] * MAX_WIDTH / max_count;
-            for (int j = 0; j < count; j++) {
-                putchar('|');
-            }
-            printf("    %d\n", s_adc_count[i]);
-        }
-    }
-    float average = (float)sum/count;
-
-    float variation_square = 0;
-    for (int i = start; i <= end; i ++) {
-        if (s_adc_count[i] == 0) {
-            continue;
-        }
-        float delta = i + s_adc_offset - average;
-        variation_square += (delta * delta) * s_adc_count[i];
-    }
-
-    printf("%d points.\n", count);
-    printf("average: %.1f\n", (float)sum/count);
-    printf("std: %.2f\n", sqrt(variation_square/count));
-}
-
-static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num, adc_atten_t atten)
-{
-    adc_digi_init_config_t adc_dma_config = {
-        .max_store_buf_size = TEST_COUNT*2,
-        .conv_num_each_intr = 128,
-        .adc1_chan_mask = adc1_chan_mask,
-        .adc2_chan_mask = adc2_chan_mask,
-    };
-    TEST_ESP_OK(adc_digi_initialize(&adc_dma_config));
-
-    adc_digi_pattern_table_t adc_pattern[10] = {0};
-    adc_digi_config_t dig_cfg = {
-        .conv_limit_en = 0,
-        .conv_limit_num = 250,
-        .sample_freq_hz = 83333,
-    };
-
-    dig_cfg.adc_pattern_len = channel_num;
-    for (int i = 0; i < channel_num; i++) {
-        uint8_t unit = ((channel[i] >> 3) & 0x1);
-        uint8_t ch = channel[i] & 0x7;
-        adc_pattern[i].atten = atten;
-        adc_pattern[i].channel = ch;
-        adc_pattern[i].unit = unit;
-    }
-    dig_cfg.adc_pattern = adc_pattern;
-    TEST_ESP_OK(adc_digi_controller_config(&dig_cfg));
-}
-
-TEST_CASE("test_adc_dma", "[adc][ignore][manual]")
-{
-    uint16_t adc1_chan_mask = BIT(2);
-    uint16_t adc2_chan_mask = 0;
-    adc_channel_t channel[1] = {ADC1_CHANNEL_2};
-    adc_atten_t target_atten = TEST_ATTEN;
-
-    const int output_data_size = sizeof(adc_digi_output_data_t);
-
-    int buffer_size = TEST_COUNT*output_data_size;
-    uint8_t* read_buf = malloc(buffer_size);
-    TEST_ASSERT_NOT_NULL(read_buf);
-
-    adc_atten_t atten;
-    bool print_figure;
-    if (target_atten == ADC_ATTEN_MAX) {
-        atten = ADC_ATTEN_DB_0;
-        target_atten = ADC_ATTEN_DB_11;
-        print_figure = false;
-    } else {
-        atten = target_atten;
-        print_figure = true;
-    }
-
-    while (1) {
-        ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
-        memset(read_buf, 0xce, buffer_size);
-
-        bool do_calibration = false;
-
-        esp_adc_cal_characteristics_t chan1_char = {};
-        esp_adc_cal_value_t cal_ret = esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_12Bit, 0, &chan1_char);
-        if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
-            do_calibration = true;
-        }
-
-        continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t), atten);
-        adc_digi_start();
-
-        int remain_count = TEST_COUNT;
-        while (remain_count) {
-            int already_got = TEST_COUNT - remain_count;
-            uint32_t ret_num;
-            TEST_ESP_OK(adc_digi_read_bytes(read_buf + already_got*output_data_size,
-                                    remain_count*output_data_size, &ret_num, ADC_MAX_DELAY));
-
-            TEST_ASSERT((ret_num % output_data_size) == 0);
-            remain_count -= ret_num / output_data_size;
-        }
-
-        adc_digi_output_data_t *p = (void*)read_buf;
-        reset_array();
-        for (int i = 0; i < TEST_COUNT; i++) {
-            insert_point(p[i].type2.data);
-        }
-
-        print_summary(print_figure);
-
-        if (do_calibration) {
-            uint32_t raw = get_average();
-            uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(raw, &chan1_char);
-            printf("Voltage = %d mV\n", voltage_mv);
-        }
-
-        adc_digi_stop();
-        TEST_ESP_OK(adc_digi_deinitialize());
-
-        if (atten == target_atten) {
-            break;
-        }
-
-        atten++;
-    }
-
-    free(read_buf);
-}
-
-TEST_CASE("test_adc_single", "[adc][ignore][manual]")
-{
-    adc_atten_t target_atten = TEST_ATTEN;
-    adc_atten_t atten;
-    bool print_figure;
-    if (target_atten == ADC_ATTEN_MAX) {
-        atten = ADC_ATTEN_DB_0;
-        target_atten = ADC_ATTEN_DB_11;
-        print_figure = false;
-    } else {
-        atten = target_atten;
-        print_figure = true;
-    }
-
-    adc1_config_width(ADC_WIDTH_BIT_12);
-
-
-    while (1) {
-        ESP_LOGI("TEST_ADC", "Test with atten: %d", atten);
-
-        adc1_config_channel_atten(ADC1_CHANNEL_2, atten);
-
-        bool do_calibration = false;
-
-        esp_adc_cal_characteristics_t chan1_char = {};
-        esp_adc_cal_value_t cal_ret = esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_12Bit, 0, &chan1_char);
-        if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
-            do_calibration = true;
-        }
-
-
-        const int test_count = TEST_COUNT;
-        adc1_channel_t channel = ADC1_CHANNEL_2;
-        while (1) {
-
-            reset_array();
-
-            for (int i = 0; i < test_count; i++) {
-                uint32_t raw = adc1_get_raw(channel);
-                insert_point(raw);
-            }
-            print_summary(print_figure);
-            break;
-        }
-
-        if (do_calibration) {
-            uint32_t raw = get_average();
-            uint32_t voltage_mv = esp_adc_cal_raw_to_voltage(raw, &chan1_char);
-            printf("Voltage = %d mV\n", voltage_mv);
-        }
-
-
-        if (atten == target_atten) {
-            break;
-        }
-        atten++;
-    }
-}
-
-#endif  //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2)
-
-
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) //TODO IDF-3908
-
-/********************************************************************************
- *      ADC Speed Related Tests
- ********************************************************************************/
-
-#define RECORD_TIME_PREPARE() uint32_t __t1, __t2
-#define RECORD_TIME_START()             do {__t1 = esp_cpu_get_ccount();}while(0)
-#define RECORD_TIME_END(p_time)         do{__t2 = esp_cpu_get_ccount(); *p_time = (__t2-__t1);}while(0)
-#define GET_US_BY_CCOUNT(t)             ((double)t/CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
-
-
-//ADC Channels
-#if CONFIG_IDF_TARGET_ESP32
-#define ADC1_CALI_TEST_CHAN0            ADC1_CHANNEL_6
-#define ADC2_CALI_TEST_CHAN0            ADC2_CHANNEL_0
-#else
-#define ADC1_CALI_TEST_CHAN0            ADC1_CHANNEL_2
-#define ADC2_CALI_TEST_CHAN0            ADC2_CHANNEL_0
-#endif
-
-//ADC Calibration
-#if CONFIG_IDF_TARGET_ESP32
-#define ADC_TEST_CALI_SCHEME            ESP_ADC_CAL_VAL_EFUSE_VREF
-#elif CONFIG_IDF_TARGET_ESP32S2
-#define ADC_TEST_CALI_SCHEME            ESP_ADC_CAL_VAL_EFUSE_TP
-#elif CONFIG_IDF_TARGET_ESP32C3
-#define ADC_TEST_CALI_SCHEME            ESP_ADC_CAL_VAL_EFUSE_TP
-#elif CONFIG_IDF_TARGET_ESP32S3
-#define ADC_TEST_CALI_SCHEME            ESP_ADC_CAL_VAL_EFUSE_TP_FIT
-#endif
-
-#define TIMES_PER_ATTEN                 10
-
-static esp_adc_cal_characteristics_t adc1_chars;
-static esp_adc_cal_characteristics_t adc2_chars;
-
-static void adc_single_cali_init(adc_unit_t adc_n, adc_channel_t chan, uint32_t atten)
-{
-    esp_err_t ret;
-    esp_adc_cal_value_t ret_val = ESP_ADC_CAL_VAL_NOT_SUPPORTED;
-
-    ret = esp_adc_cal_check_efuse(ADC_TEST_CALI_SCHEME);
-    if (ret == ESP_ERR_NOT_SUPPORTED) {
-        ESP_LOGE(TAG, "Cali scheme not supported!");
-        TEST_ASSERT(ret != ESP_ERR_NOT_SUPPORTED);
-    } else if (ret != ESP_OK) {
-        ESP_LOGW(TAG, "No cali eFuse, but will run the test");
-    }
-
-    if (adc_n == ADC_UNIT_1) {
-        ret_val = esp_adc_cal_characterize(adc_n, atten, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
-        TEST_ESP_OK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));
-        TEST_ESP_OK(adc1_config_channel_atten((adc1_channel_t)chan, atten));
-    } else if (adc_n == ADC_UNIT_2) {
-        TEST_ESP_OK(adc2_config_channel_atten((adc2_channel_t)chan, atten));
-        ret_val = esp_adc_cal_characterize(adc_n, atten, ADC_WIDTH_BIT_DEFAULT, 0, &adc2_chars);
-    }
-    if (ret_val == ESP_ADC_CAL_VAL_NOT_SUPPORTED) {
-        ESP_LOGW(TAG, "No cali eFuse, or invalid arg, but will run the test");
-    }
-    ESP_LOGI(TAG, "ADC%d, channel%d, atten%d", adc_n, chan, atten);
-}
-
-static IRAM_ATTR NOINLINE_ATTR uint32_t get_cali_time_in_ccount(uint32_t adc_raw, esp_adc_cal_characteristics_t *chars)
-{
-    uint32_t time;
-
-    RECORD_TIME_PREPARE();
-    RECORD_TIME_START();
-    esp_adc_cal_raw_to_voltage(adc_raw, chars);
-    RECORD_TIME_END(&time);
-
-    return time;
-}
-
-TEST_CASE("test_adc_single_cali_time", "[adc][ignore][manual]")
-{
-    ESP_LOGI(TAG, "CPU FREQ is %dMHz", CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ);
-    uint32_t adc1_time_record[4][TIMES_PER_ATTEN] = {};
-    uint32_t adc2_time_record[4][TIMES_PER_ATTEN] = {};
-    int adc1_raw = 0;
-    int adc2_raw = 0;
-
-    //atten0 ~ atten3
-    for (int i = 0; i < 4; i++) {
-        ESP_LOGI(TAG, "----------------atten%d----------------", i);
-        adc_single_cali_init(ADC_UNIT_1, ADC1_CALI_TEST_CHAN0, i);
-        adc_single_cali_init(ADC_UNIT_2, ADC2_CALI_TEST_CHAN0, i);
-
-        for (int j = 0; j < TIMES_PER_ATTEN; j++) {
-
-            adc1_raw = adc1_get_raw(ADC1_CALI_TEST_CHAN0);
-            TEST_ESP_OK(adc2_get_raw(ADC2_CALI_TEST_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc2_raw));
-
-            adc1_time_record[i][j] = get_cali_time_in_ccount(adc1_raw, &adc1_chars);
-            adc2_time_record[i][j] = get_cali_time_in_ccount(adc2_raw, &adc2_chars);
-
-            IDF_LOG_PERFORMANCE("ADC1 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc1_time_record[i][j]));
-            IDF_LOG_PERFORMANCE("ADC2 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc2_time_record[i][j]));
-        }
-    }
-}
-
-
-/********************************************************************************
- *      ADC Single with Light Sleep
- ********************************************************************************/
-#include <inttypes.h>
-#include "esp_sleep.h"
-#include "esp_private/regi2c_ctrl.h"
-#if REGI2C_ANA_CALI_PD_WORKAROUND
-#include "soc/regi2c_saradc.h"
-#endif
-
-//ADC Channels
-#if CONFIG_IDF_TARGET_ESP32
-#define ADC1_SLEEP_TEST_CHAN          ADC1_CHANNEL_6
-#define ADC2_SLEEP_TEST_CHAN          ADC2_CHANNEL_0
-static const char *TAG_CH[2][10] = {{"ADC1_CH6"}, {"ADC2_CH0"}};
-#else
-#define ADC1_SLEEP_TEST_CHAN          ADC1_CHANNEL_2
-#define ADC2_SLEEP_TEST_CHAN          ADC2_CHANNEL_0
-static const char *TAG_CH[2][10] = {{"ADC1_CH2"}, {"ADC2_CH0"}};
-#endif
-
-//ADC Attenuation
-#define ADC_SLEEP_TEST_ATTEN           ADC_ATTEN_DB_6
-
-//ADC Calibration
-#if CONFIG_IDF_TARGET_ESP32
-#define ADC_SLEEP_TEST_CALI_SCHEME     ESP_ADC_CAL_VAL_EFUSE_VREF
-#elif CONFIG_IDF_TARGET_ESP32S2
-#define ADC_SLEEP_TEST_CALI_SCHEME     ESP_ADC_CAL_VAL_EFUSE_TP
-#elif CONFIG_IDF_TARGET_ESP32C3
-#define ADC_SLEEP_TEST_CALI_SCHEME     ESP_ADC_CAL_VAL_EFUSE_TP
-#elif CONFIG_IDF_TARGET_ESP32S3
-#define ADC_SLEEP_TEST_CALI_SCHEME     ESP_ADC_CAL_VAL_EFUSE_TP_FIT
-#endif
-
-static esp_adc_cal_characteristics_t adc1_chars;
-static esp_adc_cal_characteristics_t adc2_chars;
-
-
-static bool adc_calibration_init(void)
-{
-    esp_err_t ret;
-    bool cali_enable = false;
-
-    ret = esp_adc_cal_check_efuse(ADC_SLEEP_TEST_CALI_SCHEME);
-    if (ret == ESP_ERR_NOT_SUPPORTED) {
-        ESP_LOGW(TAG, "Calibration scheme not supported, skip software calibration");
-    } else if (ret == ESP_ERR_INVALID_VERSION) {
-        ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
-    } else if (ret == ESP_OK) {
-        cali_enable = true;
-        esp_adc_cal_characterize(ADC_UNIT_1, ADC_SLEEP_TEST_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
-        esp_adc_cal_characterize(ADC_UNIT_2, ADC_SLEEP_TEST_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc2_chars);
-    } else {
-        ESP_LOGE(TAG, "Invalid arg");
-    }
-
-    return cali_enable;
-}
-
-#define TEST_REGI2C_ANA_CALI_BYTE_NUM   8
-
-TEST_CASE("test ADC1 Single Read with Light Sleep", "[adc][manul][ignore]")
-{
-    //ADC1 config
-    TEST_ESP_OK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));
-    TEST_ESP_OK(adc1_config_channel_atten(ADC1_SLEEP_TEST_CHAN, ADC_SLEEP_TEST_ATTEN));
-
-    //ADC config calibration
-    bool cali_en = adc_calibration_init();
-
-    int raw_expected = 0;
-    uint32_t cali_expected = 0;
-    uint8_t regi2c_cali_val_before[TEST_REGI2C_ANA_CALI_BYTE_NUM] = {};
-
-    int raw_after_sleep = 0;
-    uint32_t cali_after_sleep = 0;
-    uint8_t regi2c_cali_val_after[TEST_REGI2C_ANA_CALI_BYTE_NUM] = {};
-
-    //---------------------------------Before Sleep-----------------------------------//
-    ESP_LOGI("Before", "Light Sleep");
-
-    //Read
-    raw_expected = adc1_get_raw(ADC1_SLEEP_TEST_CHAN);
-    if (cali_en) {
-        cali_expected = esp_adc_cal_raw_to_voltage(raw_expected, &adc1_chars);
-    }
-
-#if REGI2C_ANA_CALI_PD_WORKAROUND
-    //Print regi2c
-    for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
-        regi2c_cali_val_before[i] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i);
-        printf("regi2c cali val is 0x%x", regi2c_cali_val_before[i]);
-    }
-    printf("\n");
-#endif
-
-    //Print result
-    ESP_LOGI(TAG_CH[0][0], "ADC1 raw data: %d", raw_expected);
-    if (cali_en) {
-        ESP_LOGI(TAG_CH[0][0], "ADC1 cali data: %d", cali_expected);
-    }
-
-    //---------------------------------After Sleep-----------------------------------//
-    ESP_LOGI("After", "Light Sleep");
-    esp_sleep_enable_timer_wakeup(30 * 1000);
-    esp_light_sleep_start();
-    ESP_LOGI(TAG, "Wakeup from light sleep.");
-
-#if REGI2C_ANA_CALI_PD_WORKAROUND
-    //Print regi2c
-    for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
-        regi2c_cali_val_after[i] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i);
-        printf("regi2c cali val is 0x%x", regi2c_cali_val_after[i]);
-    }
-    printf("\n");
-#endif
-
-    //Read
-    raw_after_sleep = adc1_get_raw(ADC1_SLEEP_TEST_CHAN);
-    if (cali_en) {
-        cali_after_sleep = esp_adc_cal_raw_to_voltage(raw_after_sleep, &adc1_chars);
-    }
-
-    //Print result
-    ESP_LOGI(TAG_CH[0][0], "after light sleep, ADC1 cali data: %d", raw_after_sleep);
-    if (cali_en) {
-        ESP_LOGI(TAG_CH[0][0], "after light sleep, ADC1 cali data: %d", cali_after_sleep);
-    }
-
-    //Compare
-    int32_t raw_diff = raw_expected - raw_after_sleep;
-    IDF_LOG_PERFORMANCE("ADC1 raw diff after sleep", "%d", raw_diff);
-    if (cali_en) {
-        int32_t cali_diff = cali_expected - cali_after_sleep;
-        IDF_LOG_PERFORMANCE("ADC1 cali diff after sleep", "%d mV", cali_diff);
-    }
-
-    for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
-        TEST_ASSERT_EQUAL(regi2c_cali_val_before[i], regi2c_cali_val_after[i]);
-    }
-}
-
-TEST_CASE("test ADC2 Single Read with Light Sleep", "[adc][manul][ignore]")
-{
-    //ADC2 config
-    ESP_ERROR_CHECK(adc2_config_channel_atten(ADC2_SLEEP_TEST_CHAN, ADC_SLEEP_TEST_ATTEN));
-    //ADC config calibration
-    bool cali_en = adc_calibration_init();
-
-    int raw_expected = 0;
-    uint32_t cali_expected = 0;
-    uint8_t regi2c_cali_val_before[TEST_REGI2C_ANA_CALI_BYTE_NUM] = {};
-
-    int raw_after_sleep = 0;
-    uint32_t cali_after_sleep = 0;
-    uint8_t regi2c_cali_val_after[TEST_REGI2C_ANA_CALI_BYTE_NUM] = {};
-
-    //---------------------------------Before Sleep-----------------------------------//
-    ESP_LOGI("Before", "Light Sleep");
-
-    //Read
-    TEST_ESP_OK(adc2_get_raw(ADC2_SLEEP_TEST_CHAN, ADC_WIDTH_BIT_DEFAULT, &raw_expected));
-    if (cali_en) {
-        cali_expected = esp_adc_cal_raw_to_voltage(raw_expected, &adc2_chars);
-    }
-
-#if REGI2C_ANA_CALI_PD_WORKAROUND
-    //Print regi2c
-    for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
-        regi2c_cali_val_before[i] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i);
-        printf("regi2c cali val is 0x%x", regi2c_cali_val_before[i]);
-    }
-    printf("\n");
-#endif
-
-    //Print result
-    ESP_LOGI(TAG_CH[1][0], "ADC2 raw data: %d", raw_expected);
-    if (cali_en) {
-        ESP_LOGI(TAG_CH[1][0], "ADC2 cali data: %d", cali_expected);
-    }
-
-    //---------------------------------After Sleep-----------------------------------//
-    ESP_LOGI("After", "Light Sleep");
-    esp_sleep_enable_timer_wakeup(30 * 1000);
-    esp_light_sleep_start();
-    ESP_LOGI(TAG, "Wakeup from light sleep.");
-
-#if REGI2C_ANA_CALI_PD_WORKAROUND
-    //Print regi2c
-    for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
-        regi2c_cali_val_after[i] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i);
-        printf("regi2c cali val is 0x%x", regi2c_cali_val_after[i]);
-    }
-    printf("\n");
-#endif
-
-    //Read
-    TEST_ESP_OK(adc2_get_raw(ADC2_SLEEP_TEST_CHAN, ADC_WIDTH_BIT_DEFAULT, &raw_after_sleep));
-    if (cali_en) {
-        cali_after_sleep += esp_adc_cal_raw_to_voltage(raw_after_sleep, &adc2_chars);
-    }
-
-    //Print result
-    ESP_LOGI(TAG_CH[1][0], "after light sleep, ADC2 cali data: %d", raw_after_sleep);
-    if (cali_en) {
-        ESP_LOGI(TAG_CH[1][0], "after light sleep, ADC2 cali data: %d", cali_after_sleep);
-    }
-
-    //Compare
-    int32_t raw_diff = raw_expected - raw_after_sleep;
-    IDF_LOG_PERFORMANCE("ADC2 raw diff after sleep", "%d", raw_diff);
-    if (cali_en) {
-        int32_t cali_diff = cali_expected - cali_after_sleep;
-        IDF_LOG_PERFORMANCE("ADC2 cali diff after sleep", "%d mV", cali_diff);
-    }
-    for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
-        TEST_ASSERT_EQUAL(regi2c_cali_val_before[i], regi2c_cali_val_after[i]);
-    }
-}
-#endif   //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) //TODO IDF-3908

+ 4 - 3
components/driver/test/test_adc2_with_wifi.c

@@ -15,12 +15,13 @@
 #include "nvs_flash.h"
 #include "test_utils.h"
 #include "driver/gpio.h"
-#include "driver/adc.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "driver/gpio.h"
+#define CONFIG_ADC_SUPPRESS_DEPRECATE_WARN 1
+#include "driver/adc.h"
 
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3, ESP32S3, ESP32C2)
+#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3, ESP32C2)
 
 static const char* TAG = "test_adc2";
 
@@ -149,7 +150,7 @@ TEST_CASE("adc2 work with wifi","[adc]")
     bool test_list[TEST_NUM] ={1, 1, 0, 0, 1, 0, 1, 0};
 
     adc2_pad_get_io_num(ADC2_CHAN1, &test_adc_io);
-    TEST_ESP_OK(adc2_config_channel_atten(ADC2_CHAN1, ADC_ATTEN_0db));
+    TEST_ESP_OK(adc2_config_channel_atten(ADC2_CHAN1, ADC_ATTEN_DB_0));
     printf("test_adc_io is %d\n", test_adc_io);
 
     //---------------------------------GPIO init-----------------------------------//

+ 0 - 394
components/driver/test/test_adc_common.c

@@ -1,394 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-/*
- Tests for the adc device driver
-*/
-#include "esp_system.h"
-#include "driver/adc.h"
-#include "driver/rtc_io.h"
-#include "driver/gpio.h"
-#include "unity.h"
-#include "esp_system.h"
-#include "esp_event.h"
-#include "esp_wifi.h"
-#include "esp_log.h"
-#include "nvs_flash.h"
-#include "test_utils.h"
-#include "soc/adc_periph.h"
-
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3,ESP32C3, ESP32C2)
-#include "driver/dac.h"
-
-static const char *TAG = "test_adc";
-
-#ifdef CONFIG_IDF_TARGET_ESP32
-#define ADC1_TEST_WIDTH         ADC_WIDTH_BIT_12
-#define ADC2_TEST_WIDTH         ADC_WIDTH_BIT_12
-#elif defined CONFIG_IDF_TARGET_ESP32S2
-#define ADC1_TEST_WIDTH         ADC_WIDTH_BIT_13   //ESP32S2 only support 13 bit width
-#define ADC2_TEST_WIDTH         ADC_WIDTH_BIT_13   //ESP32S2 only support 13 bit width
-#endif
-
-#define ADC1_TEST_ATTEN         ADC_ATTEN_DB_11
-#define ADC2_TEST_ATTEN         ADC_ATTEN_DB_11
-
-#if CONFIG_IDF_TARGET_ESP32
-#define ADC1_TEST_CHANNEL_NUM   8
-#elif CONFIG_IDF_TARGET_ESP32S2
-#define ADC1_TEST_CHANNEL_NUM   10
-#endif
-#define ADC2_TEST_CHANNEL_NUM   6
-
-static const int adc1_ch[ADC1_TEST_CHANNEL_NUM] = {
-    ADC1_CHANNEL_0,
-    ADC1_CHANNEL_1,
-    ADC1_CHANNEL_2,
-    ADC1_CHANNEL_3,
-    ADC1_CHANNEL_4,
-    ADC1_CHANNEL_5,
-    ADC1_CHANNEL_6,
-    ADC1_CHANNEL_7,
-#if CONFIG_IDF_TARGET_ESP32S2
-    ADC1_CHANNEL_8,
-    ADC1_CHANNEL_9,
-#endif
-};
-
-static const int adc2_ch[ADC2_TEST_CHANNEL_NUM] = {
-    ADC2_CHANNEL_0,
-    ADC2_CHANNEL_1,
-    ADC2_CHANNEL_2,
-    ADC2_CHANNEL_3,
-    ADC2_CHANNEL_4,
-    ADC2_CHANNEL_5,
-};
-
-#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
-
-void adc_fake_tie_middle(adc_unit_t adc_unit, adc_channel_t channel)
-{
-    gpio_num_t gpio_num = 0;
-    if (adc_unit == ADC_UNIT_1) {
-        gpio_num = ADC_GET_IO_NUM(0, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_PULLDOWN));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
-    }
-    if (adc_unit == ADC_UNIT_2) {
-        gpio_num = ADC_GET_IO_NUM(1, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_PULLDOWN));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
-    }
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-}
-
-void adc_fake_tie_high(adc_unit_t adc_unit, adc_channel_t channel)
-{
-    gpio_num_t gpio_num = 0;
-    if (adc_unit == ADC_UNIT_1) {
-        gpio_num = ADC_GET_IO_NUM(0, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 1));
-    }
-    if (adc_unit == ADC_UNIT_2) {
-        gpio_num = ADC_GET_IO_NUM(1, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_en(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLUP_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 1));
-    }
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-}
-
-void adc_fake_tie_low(adc_unit_t adc_unit, adc_channel_t channel)
-{
-    gpio_num_t gpio_num = 0;
-    if (adc_unit == ADC_UNIT_1) {
-        gpio_num = ADC_GET_IO_NUM(0, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLDOWN_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 0));
-    }
-    if (adc_unit == ADC_UNIT_2) {
-        gpio_num = ADC_GET_IO_NUM(1, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_en(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_PULLDOWN_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_OUTPUT_ONLY));
-        TEST_ESP_OK(rtc_gpio_set_level(gpio_num, 0));
-    }
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-}
-
-void adc_io_normal(adc_unit_t adc_unit, adc_channel_t channel)
-{
-    gpio_num_t gpio_num = 0;
-    if (adc_unit == ADC_UNIT_1) {
-        gpio_num = ADC_GET_IO_NUM(0, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
-    }
-    if (adc_unit == ADC_UNIT_2) {
-        gpio_num = ADC_GET_IO_NUM(1, channel);
-        TEST_ESP_OK(rtc_gpio_init(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pullup_dis(gpio_num));
-        TEST_ESP_OK(rtc_gpio_pulldown_dis(gpio_num));
-        TEST_ESP_OK(gpio_set_pull_mode(gpio_num, GPIO_FLOATING));
-        TEST_ESP_OK(rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED));
-    }
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-}
-
-TEST_CASE("ADC1 rtc read", "[adc1]")
-{
-    int adc1_val[ADC1_TEST_CHANNEL_NUM] = {0};
-
-    /* adc1 Configure */
-    adc1_config_width(ADC1_TEST_WIDTH);
-    ESP_LOGI(TAG, "ADC1 [CH - GPIO]:");
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc1_config_channel_atten(adc1_ch[i], ADC1_TEST_ATTEN) );
-        ESP_LOGI(TAG, "[CH%d - IO%d]:", adc1_ch[i], ADC_GET_IO_NUM(0, adc1_ch[i]));
-    }
-    printf("ADC tie normal read: ");
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-
-    /* adc Read */
-    printf("ADC1: ");
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
-        printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
-    }
-    printf("\n");
-
-    /* tie high */
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_high(ADC_UNIT_1, adc1_ch[i]);
-    }
-    printf("ADC tie high read: ");
-    vTaskDelay(50 / portTICK_PERIOD_MS);
-    /* adc Read */
-    printf("ADC1: ");
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
-        printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-        TEST_ASSERT_EQUAL( adc1_val[i], 0x1fff );
-#endif
-    }
-    printf("\n");
-
-    /* tie low */
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_low(ADC_UNIT_1, adc1_ch[i]);
-    }
-    printf("ADC tie low  read: ");
-    vTaskDelay(50 / portTICK_PERIOD_MS);
-    /* adc Read */
-    printf("ADC1: ");
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
-        printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-        TEST_ASSERT_INT_WITHIN( 100, 0, adc1_val[i] );
-#endif
-    }
-    printf("\n");
-
-    /* tie midedle */
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_middle(ADC_UNIT_1, adc1_ch[i]);
-    }
-    printf("ADC tie mid  read: ");
-    vTaskDelay(50 / portTICK_PERIOD_MS);
-    /* adc Read */
-    printf("ADC1: ");
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc1_val[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
-        printf("CH%d-%d ", adc1_ch[i], adc1_val[i]);
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-        TEST_ASSERT_NOT_EQUAL( adc1_val[i], 0x1fff );
-        TEST_ASSERT_NOT_EQUAL( adc1_val[i], 0 );
-#endif
-    }
-    printf("\n");
-
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc_io_normal(ADC_UNIT_1, adc1_ch[i]);
-    }
-}
-
-TEST_CASE("ADC2 rtc read", "[adc2]")
-{
-    int adc2_val[ADC2_TEST_CHANNEL_NUM] = {0};
-
-    /* adc2 Configure */
-    ESP_LOGI(TAG, "ADC2 [CH - GPIO]:");
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc2_config_channel_atten(adc2_ch[i], ADC2_TEST_ATTEN) );
-        ESP_LOGI(TAG, "[CH%d - IO%d]:", adc2_ch[i], ADC_GET_IO_NUM(1, adc2_ch[i]));
-    }
-    printf("ADC float read: ");
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-
-    /* adc Read */
-    printf("ADC2: ");
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
-        printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
-    }
-    printf("\n");
-
-    /* tie high */
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_high(ADC_UNIT_2, adc2_ch[i]);
-    }
-    printf("ADC tie high read: ");
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-    /* adc Read */
-    printf("ADC2: ");
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
-        printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-        TEST_ASSERT_EQUAL( adc2_val[i], 0x1fff );
-#endif
-    }
-    printf("\n");
-
-    /* tie low */
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_low(ADC_UNIT_2, adc2_ch[i]);
-    }
-    printf("ADC tie low read: ");
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-    /* adc Read */
-    printf("ADC2: ");
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
-        printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-        TEST_ASSERT_INT_WITHIN( 100, 0, adc2_val[i] );
-#endif
-    }
-    printf("\n");
-
-    /* tie midedle */
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_middle(ADC_UNIT_2, adc2_ch[i]);
-    }
-    printf("ADC tie middle read: ");
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-    /* adc Read */
-    printf("ADC2: ");
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]) );
-        printf("CH%d-%d ", adc2_ch[i], adc2_val[i]);
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-        TEST_ASSERT_NOT_EQUAL( 0, adc2_val[i]  );
-        TEST_ASSERT_NOT_EQUAL( 0x1fff, adc2_val[i]  );
-#endif
-    }
-    printf("\n");
-
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc_io_normal(ADC_UNIT_1, adc1_ch[i]);
-    }
-}
-
-#include "touch_scope.h"
-/**
- * 0: ADC1 channels raw data debug.
- * 1: ADC2 channels raw data debug.
- */
-#define SCOPE_DEBUG_TYPE            1
-#define SCOPE_DEBUG_CHANNEL_MAX    (10)
-#define SCOPE_DEBUG_ENABLE         (0)
-#define SCOPE_UART_BUADRATE        (256000)
-#define SCOPE_DEBUG_FREQ_MS        (50)
-
-/**
- * Manual test: Capture ADC-DMA data and display it on the serial oscilloscope. Used to observe the stability of the data.
- * Use step:
- *      1. Call this function in `esp-idf/tools/unit-test-app/main/app_main.c`.
- *      2. Use `ESP-Tuning Tool`(download from `www.espressif.com`) to capture.
- *      3. The readings of multiple channels will be displayed on the tool.
- */
-void test_adc_slope_debug(void)
-{
-    float scope_temp[SCOPE_DEBUG_CHANNEL_MAX] = {0};  // max scope channel is 10.
-    test_tp_scope_debug_init(0, -1, -1, SCOPE_UART_BUADRATE);
-
-#if SCOPE_DEBUG_TYPE == 0
-    /* adc1 Configure */
-    adc1_config_width(ADC1_TEST_WIDTH);
-    ESP_LOGI(TAG, "ADC1 [CH - GPIO] atten %d:", ADC1_TEST_ATTEN);
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc1_config_channel_atten(adc1_ch[i], ADC1_TEST_ATTEN) );
-        ESP_LOGI(TAG, "[CH%d - IO%d]", adc1_ch[i], ADC_GET_IO_NUM(0, adc1_ch[i]));
-    }
-    /* tie midedle */
-    for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_middle(ADC_UNIT_1, adc1_ch[i]);
-    }
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-
-    while (1) {
-        /* adc Read */
-        for (int i = 0; i < ADC1_TEST_CHANNEL_NUM; i++) {
-            scope_temp[i] = adc1_get_raw((adc1_channel_t)adc1_ch[i]);
-        }
-        test_tp_print_to_scope(scope_temp, ADC1_TEST_CHANNEL_NUM);
-        vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_PERIOD_MS);
-    }
-#elif SCOPE_DEBUG_TYPE == 1
-    int adc2_val[ADC2_TEST_CHANNEL_NUM] = {0};
-
-    /* adc2 Configure */
-    ESP_LOGI(TAG, "ADC2 [CH - GPIO] atten %d:", ADC2_TEST_ATTEN);
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        TEST_ESP_OK( adc2_config_channel_atten(adc2_ch[i], ADC2_TEST_ATTEN) );
-        ESP_LOGI(TAG, "[CH%d - IO%d]:", adc2_ch[i], ADC_GET_IO_NUM(1, adc2_ch[i]));
-    }
-    /* tie midedle */
-    for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-        adc_fake_tie_middle(ADC_UNIT_2, adc2_ch[i]);
-    }
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-
-    while (1) {
-        /* adc Read */
-        printf("ADC2: ");
-        for (int i = 0; i < ADC2_TEST_CHANNEL_NUM; i++) {
-            adc2_get_raw((adc2_channel_t)adc2_ch[i], ADC2_TEST_WIDTH, &adc2_val[i]);
-            scope_temp[i] = adc2_val[i];
-        }
-
-        test_tp_print_to_scope(scope_temp, ADC2_TEST_CHANNEL_NUM);
-        vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_PERIOD_MS);
-    }
-#endif
-}
-
-#endif

+ 2 - 1
components/driver/test/test_dac.c

@@ -8,7 +8,6 @@
 */
 #include "esp_system.h"
 
-#include "driver/adc.h"
 #include "unity.h"
 #include "esp_system.h"
 #include "esp_event.h"
@@ -17,6 +16,8 @@
 #include "nvs_flash.h"
 #include "test_utils.h"
 #include "soc/soc_caps.h"
+#define CONFIG_ADC_SUPPRESS_DEPRECATE_WARN 1
+#include "driver/adc.h"
 
 #if SOC_DAC_SUPPORTED
 #include "driver/dac.h"

+ 0 - 1
components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/main/test_i2s_dac.c

@@ -13,7 +13,6 @@
 #if CONFIG_IDF_TARGET_ESP32
 
 #include "esp_system.h"
-#include "driver/adc.h"
 #include "unity.h"
 #include "esp_system.h"
 #include "esp_event.h"

+ 1 - 0
components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac/sdkconfig.defaults

@@ -1,3 +1,4 @@
 CONFIG_I2S_SUPPRESS_DEPRECATE_WARN=y
+CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y
 CONFIG_I2S_ENABLE_DEBUG_LOG=y
 CONFIG_ESP_TASK_WDT=n

+ 1 - 0
components/driver/test_apps/i2s_test_apps/legacy_i2s_driver/sdkconfig.defaults

@@ -1,3 +1,4 @@
 CONFIG_I2S_SUPPRESS_DEPRECATE_WARN=y
+CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y
 CONFIG_I2S_ENABLE_DEBUG_LOG=y
 CONFIG_ESP_TASK_WDT=n

+ 5 - 0
components/driver/test_apps/legacy_adc_driver/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.16)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(legacy_adc_driver_test)

+ 2 - 0
components/driver/test_apps/legacy_adc_driver/README.md

@@ -0,0 +1,2 @@
+| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- |

+ 5 - 0
components/driver/test_apps/legacy_adc_driver/main/CMakeLists.txt

@@ -0,0 +1,5 @@
+set(srcs "test_app_main.c"
+         "test_legacy_adc.c")
+
+idf_component_register(SRCS ${srcs}
+                       WHOLE_ARCHIVE)

+ 40 - 0
components/driver/test_apps/legacy_adc_driver/main/test_app_main.c

@@ -0,0 +1,40 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+#define TEST_MEMORY_LEAK_THRESHOLD (-300)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    unity_run_menu();
+}

+ 129 - 0
components/driver/test_apps/legacy_adc_driver/main/test_legacy_adc.c

@@ -0,0 +1,129 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "unity.h"
+#include "esp_log.h"
+#include "driver/adc.h"
+#include "driver/gpio.h"
+#include "driver/rtc_io.h"
+#include "soc/adc_periph.h"
+
+#define ADC_GET_IO_NUM(unit, channel) (adc_channel_io_map[unit][channel])
+
+/**
+ * We use weak pulldown, `ADC_TEST_LOW_THRESH` may vary.
+ * If connect to GND, `ADC_TEST_LOW_THRESH` will usually within 10
+ */
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      10
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_THRESH     10
+
+#elif CONFIG_IDF_TARGET_ESP32S2
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      25
+
+#define ADC_TEST_HIGH_VAL        8191
+#define ADC_TEST_HIGH_THRESH     10
+
+#elif CONFIG_IDF_TARGET_ESP32C3
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      30
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_THRESH     10
+
+#elif CONFIG_IDF_TARGET_ESP32S3
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      15
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_THRESH     0
+
+#elif CONFIG_IDF_TARGET_ESP32C2
+#define ADC_TEST_LOW_VAL         2147
+#define ADC_TEST_LOW_THRESH      50
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_THRESH     0
+
+#elif CONFIG_IDF_TARGET_ESP32H2
+#define ADC_TEST_LOW_VAL         2147
+#define ADC_TEST_LOW_THRESH      50
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_THRESH     0
+#endif
+
+//ADC Channels
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC1_TEST_CHAN0          ADC1_CHANNEL_4
+#define ADC2_TEST_CHAN0          ADC2_CHANNEL_0
+#elif (SOC_ADC_PERIPH_NUM >= 2)
+#define ADC1_TEST_CHAN0          ADC1_CHANNEL_2
+#define ADC2_TEST_CHAN0          ADC2_CHANNEL_0
+#else
+#define ADC1_TEST_CHAN0          ADC1_CHANNEL_2
+#endif
+
+const __attribute__((unused)) static char *TAG = "TEST_ADC_LEGACY";
+
+
+void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level)
+{
+    TEST_ASSERT(channel < SOC_ADC_CHANNEL_NUM(unit) && "invalid channel");
+
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+    uint32_t io_num = ADC_GET_IO_NUM(unit, channel);
+    TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY: GPIO_PULLDOWN_ONLY)));
+#else
+    gpio_num_t io_num = ADC_GET_IO_NUM(unit, channel);
+    if (level) {
+        TEST_ESP_OK(rtc_gpio_pullup_en(io_num));
+        TEST_ESP_OK(rtc_gpio_pulldown_dis(io_num));
+    } else {
+        TEST_ESP_OK(rtc_gpio_pullup_dis(io_num));
+        TEST_ESP_OK(rtc_gpio_pulldown_en(io_num));
+    }
+#endif
+}
+
+TEST_CASE("Legacy ADC oneshot high/low test", "[legacy_adc_oneshot]")
+{
+    int adc_raw = 0;
+    //ADC1 config
+    TEST_ESP_OK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));
+    TEST_ESP_OK(adc1_config_channel_atten(ADC1_TEST_CHAN0, ADC_ATTEN_DB_11));
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    //ADC2 config
+    TEST_ESP_OK(adc2_config_channel_atten(ADC2_TEST_CHAN0, ADC_ATTEN_DB_11));
+#endif
+
+    test_adc_set_io_level(ADC_UNIT_1, (adc1_channel_t)ADC1_TEST_CHAN0, 0);
+    adc_raw = adc1_get_raw(ADC1_TEST_CHAN0);
+    ESP_LOGI(TAG, "ADC%d Channel %d raw: %d\n", ADC_UNIT_1, ADC1_TEST_CHAN0, adc_raw);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw);
+
+    test_adc_set_io_level(ADC_UNIT_1, (adc1_channel_t)ADC1_TEST_CHAN0, 1);
+    adc_raw = adc1_get_raw(ADC1_TEST_CHAN0);
+    ESP_LOGI(TAG, "ADC%d Channel %d raw: %d\n", ADC_UNIT_1, ADC1_TEST_CHAN0, adc_raw);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw);
+
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    test_adc_set_io_level(ADC_UNIT_2, (adc2_channel_t)ADC2_TEST_CHAN0, 0);
+    TEST_ESP_OK(adc2_get_raw(ADC2_TEST_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc_raw));
+    ESP_LOGI(TAG, "ADC%d Channel %d raw: %d\n", ADC_UNIT_2, ADC2_TEST_CHAN0, adc_raw);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw);
+
+    test_adc_set_io_level(ADC_UNIT_2, (adc2_channel_t)ADC2_TEST_CHAN0, 1);
+    TEST_ESP_OK(adc2_get_raw(ADC2_TEST_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc_raw));
+    ESP_LOGI(TAG, "ADC%d Channel %d raw: %d\n", ADC_UNIT_2, ADC2_TEST_CHAN0, adc_raw);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw);
+#endif
+}

+ 24 - 0
components/driver/test_apps/legacy_adc_driver/pytest_legacy_adc.py

@@ -0,0 +1,24 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32
+@pytest.mark.esp32s2
+@pytest.mark.esp32s3
+@pytest.mark.esp32c3
+@pytest.mark.esp32c2
+@pytest.mark.generic
+@pytest.mark.parametrize(
+    'config',
+    [
+        'release',
+    ],
+    indirect=True,
+)
+def test_legacy_adc(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output(timeout=240)

+ 5 - 0
components/driver/test_apps/legacy_adc_driver/sdkconfig.ci.release

@@ -0,0 +1,5 @@
+CONFIG_PM_ENABLE=y
+CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

+ 3 - 0
components/driver/test_apps/legacy_adc_driver/sdkconfig.defaults

@@ -0,0 +1,3 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n
+CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y

+ 2 - 1
components/efuse/esp32c3/esp_efuse_rtc_calib.c

@@ -39,8 +39,9 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a
     return init_code + 1000;    // version 1 logic
 }
 
-esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* out_digi, uint32_t* out_vol_mv)
+esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t* out_digi, uint32_t* out_vol_mv)
 {
+    (void)adc_unit;    //On esp32c3,  V1 we don't have calibration data for ADC2, using the efuse data of ADC1
     const esp_efuse_desc_t** cal_vol_efuse;
     uint32_t calib_vol_expected_mv;
     if (version != 1) {

+ 2 - 1
components/efuse/esp32c3/include/esp_efuse_rtc_calib.h

@@ -35,6 +35,7 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a
  * @brief Get the calibration digits stored in the efuse, and the corresponding voltage.
  *
  * @param version Version of the stored efuse
+ * @param adc_unit      ADC unit (not used on ESP32C3, for compatibility)
  * @param atten         Attenuation to use
  * @param out_digi      Output buffer of the digits
  * @param out_vol_mv    Output of the voltage, in mV
@@ -42,7 +43,7 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a
  *      - ESP_ERR_INVALID_ARG: If efuse version or attenuation is invalid
  *      - ESP_OK: if success
  */
-esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* out_digi, uint32_t* out_vol_mv);
+esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t* out_digi, uint32_t* out_vol_mv);
 
 /**
  * @brief Get the temperature sensor calibration number delta_T stored in the efuse.

+ 39 - 0
components/esp_adc/CMakeLists.txt

@@ -0,0 +1,39 @@
+idf_build_get_property(target IDF_TARGET)
+
+set(includes "include" "interface" "${target}/include" "deprecated/include")
+
+set(srcs "adc_cali.c"
+         "adc_cali_curve_fitting.c"
+         "adc_oneshot.c"
+         "adc_common.c"
+         "adc_lock.c"
+         "deprecated/esp_adc_cal_common_legacy.c")
+
+if(CONFIG_SOC_ADC_DMA_SUPPORTED)
+    list(APPEND srcs "adc_continuous.c")
+endif()
+
+# init constructor for wifi
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/adc2_init_cal.c")
+    list(APPEND srcs "${target}/adc2_init_cal.c")
+endif()
+
+# line fitting scheme
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/adc_cali_line_fitting.c")
+    list(APPEND srcs "${target}/adc_cali_line_fitting.c")
+endif()
+
+# curve fitting scheme coefficients
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/curve_fitting_coefficients.c")
+    list(APPEND srcs "${target}/curve_fitting_coefficients.c")
+endif()
+
+# legacy calibration driver
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deprecated/${target}/esp_adc_cal_legacy.c")
+    list(APPEND srcs "deprecated/${target}/esp_adc_cal_legacy.c")
+endif()
+
+idf_component_register(SRCS ${srcs}
+                       INCLUDE_DIRS ${includes}
+                       PRIV_REQUIRES driver efuse
+                       LDFRAGMENTS linker.lf)

+ 47 - 0
components/esp_adc/Kconfig

@@ -0,0 +1,47 @@
+menu "ADC and ADC Calibration"
+
+    config ADC_ONESHOT_CTRL_FUNC_IN_IRAM
+        bool "Place ISR version ADC oneshot mode read function into IRAM"
+        default n
+        help
+            Place ISR version ADC oneshot mode read function into IRAM.
+
+    config ADC_CONTINUOUS_ISR_IRAM_SAFE
+        depends on SOC_ADC_DMA_SUPPORTED
+        bool "ADC continuous mode driver ISR IRAM-Safe"
+        default n
+        select GDMA_ISR_IRAM_SAFE if SOC_ADC_DMA_SUPPORTED && SOC_GDMA_SUPPORTED
+        help
+            Ensure the ADC continuous mode ISR is IRAM-Safe. When enabled, the ISR handler
+            will be available when the cache is disabled.
+
+    menu "ADC Calibration Configurations"
+        depends on IDF_TARGET_ESP32
+
+        config ADC_CALI_EFUSE_TP_ENABLE
+            bool "Use Two Point Values"
+            default "y"
+            help
+                Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.
+                This option will allow the ADC calibration component to characterize the
+                ADC-Voltage curve using Two Point values if they are available.
+
+        config ADC_CALI_EFUSE_VREF_ENABLE
+            bool "Use eFuse Vref"
+            default "y"
+            help
+                Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow
+                the ADC calibration component to characterize the ADC-Voltage curve using
+                eFuse Vref if it is available.
+
+        config ADC_CALI_LUT_ENABLE
+            bool "Use Lookup Tables"
+            default "y"
+            help
+                This option will allow the ADC calibration component to use Lookup Tables
+                to correct for non-linear behavior in 11db attenuation. Other attenuations
+                do not exhibit non-linear behavior hence will not be affected by this option.
+
+    endmenu
+
+endmenu

+ 45 - 0
components/esp_adc/adc_cali.c

@@ -0,0 +1,45 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <sys/cdefs.h>
+#include "esp_types.h"
+#include "sdkconfig.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_check.h"
+#include "esp_heap_caps.h"
+#include "hal/adc_types.h"
+#include "esp_adc/adc_cali.h"
+#include "adc_cali_interface.h"
+
+const __attribute__((unused)) static char *TAG = "adc_cali";
+
+
+esp_err_t adc_cali_check_scheme(adc_cali_scheme_ver_t *scheme_mask)
+{
+    ESP_RETURN_ON_FALSE(scheme_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    *scheme_mask = 0;
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+    *scheme_mask |= ADC_CALI_SCHEME_VER_LINE_FITTING;
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+    *scheme_mask |= ADC_CALI_SCHEME_VER_CURVE_FITTING;
+#endif
+
+    //Add your custom ADC calibration scheme here
+
+    ESP_RETURN_ON_FALSE((*scheme_mask) != 0, ESP_ERR_NOT_SUPPORTED, TAG, "no supported calibration scheme yet");
+
+    return ESP_OK;
+}
+
+esp_err_t adc_cali_raw_to_voltage(adc_cali_handle_t handle, int raw, int *voltage)
+{
+    ESP_RETURN_ON_FALSE(handle && voltage, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    ESP_RETURN_ON_FALSE(handle->ctx, ESP_ERR_INVALID_STATE, TAG, "no calibration scheme, create a scheme first");
+
+    return handle->raw_to_voltage(handle->ctx, raw, voltage);
+}

+ 247 - 0
components/esp_adc/adc_cali_curve_fitting.c

@@ -0,0 +1,247 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "esp_types.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_check.h"
+#include "esp_heap_caps.h"
+#include "soc/soc_caps.h"
+#include "esp_adc/adc_cali_scheme.h"
+#include "adc_cali_interface.h"
+#include "curve_fitting_coefficients.h"
+
+#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
+#include "esp_efuse_rtc_calib.h"
+
+const __attribute__((unused)) static char *TAG = "adc_cali";
+
+
+// coeff_a is actually a float number
+// it is scaled to put them into uint32_t so that the headers do not have to be changed
+static const int coeff_a_scaling = 65536;
+
+
+/* -------------------- Characterization Helper Data Types ------------------ */
+typedef struct {
+    uint32_t voltage;
+    uint32_t digi;
+} adc_calib_data_ver1_t;
+
+typedef struct {
+    char version_num;
+    adc_unit_t unit_id;
+    adc_atten_t atten;
+    union {
+        adc_calib_data_ver1_t ver1;
+    } ref_data;
+} adc_calib_info_t;
+
+
+/* ------------------------ Context Structure--------------------------- */
+typedef struct {
+    uint32_t coeff_a;    ///< Gradient of ADC-Voltage curve
+    uint32_t coeff_b;    ///< Offset of ADC-Voltage curve
+} cali_chars_first_step_t;
+
+typedef struct {
+    uint8_t  term_num;                                        ///< Term number of the algorithm formula
+    const uint64_t (*coeff)[COEFF_GROUP_NUM][TERM_MAX][2];    ///< Coeff of each term. See `adc_error_coef_atten` for details (and the magic number 2)
+    const int32_t  (*sign)[COEFF_GROUP_NUM][TERM_MAX];        ///< Sign of each term
+} cali_chars_second_step_t;
+
+typedef struct {
+    adc_unit_t unit_id;                            ///< ADC unit
+    adc_atten_t atten;                             ///< ADC attenuation
+    cali_chars_first_step_t chars_first_step;      ///< Calibration first step characteristics
+    cali_chars_second_step_t chars_second_step;    ///< Calibration second step characteristics
+} cali_chars_curve_fitting_t;
+
+
+/* ----------------------- Characterization Functions ----------------------- */
+static void get_first_step_reference_point(int version_num, adc_unit_t unit_id, adc_atten_t atten, adc_calib_info_t *calib_info);
+static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, cali_chars_curve_fitting_t *chars);
+static void calc_second_step_coefficients(const adc_cali_curve_fitting_config_t *config, cali_chars_curve_fitting_t *ctx);
+static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param, adc_atten_t atten);
+static esp_err_t check_valid(const adc_cali_curve_fitting_config_t *config);
+
+
+/* ------------------------ Interface Functions --------------------------- */
+static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage);
+
+/* ------------------------- Public API ------------------------------------- */
+esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_config_t *config, adc_cali_handle_t *ret_handle)
+{
+    esp_err_t ret = ESP_OK;
+    ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
+    ret = check_valid(config);
+    if (ret != ESP_OK) {
+        return ret;
+    }
+    // current version only accepts encoding ver 1.
+    uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
+    ESP_RETURN_ON_FALSE(adc_encoding_version == 1, ESP_ERR_NOT_SUPPORTED, TAG, "Calibration required eFuse bits not burnt");
+
+    adc_cali_scheme_t *scheme = (adc_cali_scheme_t *)heap_caps_calloc(1, sizeof(adc_cali_scheme_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    ESP_RETURN_ON_FALSE(scheme, ESP_ERR_NO_MEM, TAG, "no mem for adc calibration scheme");
+
+    cali_chars_curve_fitting_t *chars = (cali_chars_curve_fitting_t *)heap_caps_calloc(1, sizeof(cali_chars_curve_fitting_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    ESP_GOTO_ON_FALSE(chars, ESP_ERR_NO_MEM, err, TAG, "no memory for the calibration characteristics");
+
+    scheme->raw_to_voltage = cali_raw_to_voltage;
+    scheme->ctx = chars;
+
+    //Prepare calibration characteristics
+    adc_calib_info_t calib_info = {0};
+    //Set first step calibration context
+    get_first_step_reference_point(adc_encoding_version, config->unit_id, config->atten, &calib_info);
+    calc_first_step_coefficients(&calib_info, chars);
+    //Set second step calibration context
+    calc_second_step_coefficients(config, chars);
+    chars->unit_id = config->unit_id;
+    chars->atten = config->atten;
+
+    *ret_handle = scheme;
+
+    return ESP_OK;
+
+err:
+    if (scheme) {
+        free(scheme);
+    }
+    return ret;
+}
+
+esp_err_t adc_cali_delete_scheme_curve_fitting(adc_cali_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+
+    free(handle->ctx);
+    handle->ctx = NULL;
+
+    free(handle);
+    handle = NULL;
+
+    return ESP_OK;
+}
+
+
+/* ------------------------ Interface Functions --------------------------- */
+static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage)
+{
+    //pointers are checked in the upper layer
+
+    cali_chars_curve_fitting_t *ctx = arg;
+    uint64_t v_cali_1 = raw * ctx->chars_first_step.coeff_a / coeff_a_scaling + ctx->chars_first_step.coeff_b;
+    int32_t error = get_reading_error(v_cali_1, &(ctx->chars_second_step), ctx->atten);
+
+    *voltage = (int32_t)v_cali_1 - error;
+
+    return ESP_OK;
+}
+
+
+/* ----------------------- Characterization Functions ----------------------- */
+//To get the reference point (Dout, Vin)
+static void get_first_step_reference_point(int version_num, adc_unit_t unit_id, adc_atten_t atten, adc_calib_info_t *calib_info)
+{
+    assert(version_num == 1);
+    esp_err_t ret;
+
+    calib_info->version_num = version_num;
+    calib_info->unit_id = unit_id;
+    calib_info->atten = atten;
+
+    uint32_t voltage = 0;
+    uint32_t digi = 0;
+    ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, unit_id, atten, &digi, &voltage);
+    assert(ret == ESP_OK);
+    calib_info->ref_data.ver1.voltage = voltage;
+    calib_info->ref_data.ver1.digi = digi;
+}
+
+/*
+ * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
+ * with the previously done measurement when the chip was manufactured.
+ */
+static void calc_first_step_coefficients(const adc_calib_info_t *parsed_data, cali_chars_curve_fitting_t *ctx)
+{
+    ctx->chars_first_step.coeff_a = coeff_a_scaling * parsed_data->ref_data.ver1.voltage / parsed_data->ref_data.ver1.digi;
+    ctx->chars_first_step.coeff_b = 0;
+    ESP_LOGV(TAG, "Calib V1, Cal Voltage = %d, Digi out = %d, Coef_a = %d\n", parsed_data->ref_data.ver1.voltage, parsed_data->ref_data.ver1.digi, ctx->chars_first_step.coeff_a);
+}
+
+static void calc_second_step_coefficients(const adc_cali_curve_fitting_config_t *config, cali_chars_curve_fitting_t *ctx)
+{
+    ctx->chars_second_step.term_num = (config->atten == 3) ? 5 : 3;
+#if CONFIG_IDF_TARGET_ESP32C3
+    //On esp32c3, ADC1 and ADC2 share the second step coefficients
+    ctx->chars_second_step.coeff = &adc1_error_coef_atten;
+    ctx->chars_second_step.sign = &adc1_error_sign;
+#else
+    ctx->chars_second_step.coeff = (config->unit_id == ADC_UNIT_1) ? &adc1_error_coef_atten : &adc2_error_coef_atten;
+    ctx->chars_second_step.sign = (config->unit_id == ADC_UNIT_1) ? &adc1_error_sign : &adc2_error_sign;
+#endif
+}
+
+static int32_t get_reading_error(uint64_t v_cali_1, const cali_chars_second_step_t *param, adc_atten_t atten)
+{
+    if (v_cali_1 == 0) {
+        return 0;
+    }
+
+    uint8_t term_num = param->term_num;
+    int32_t error = 0;
+    uint64_t coeff = 0;
+    uint64_t variable[term_num];
+    uint64_t term[term_num];
+    memset(variable, 0, term_num * sizeof(uint64_t));
+    memset(term, 0, term_num * sizeof(uint64_t));
+
+    /**
+     * For atten0 ~ 2:
+     * error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2);
+     *
+     * For atten3:
+     * error = (K0 * X^0) + (K1 * X^1)  + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
+     */
+    variable[0] = 1;
+    coeff = (*param->coeff)[atten][0][0];
+    term[0] = variable[0] * coeff / (*param->coeff)[atten][0][1];
+    error = (int32_t)term[0] * (*param->sign)[atten][0];
+
+    for (int i = 1; i < term_num; i++) {
+        variable[i] = variable[i-1] * v_cali_1;
+        coeff = (*param->coeff)[atten][i][0];
+        term[i] = variable[i] * coeff;
+        ESP_LOGV(TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], i);
+
+        term[i] = term[i] / (*param->coeff)[atten][i][1];
+        error += (int32_t)term[i] * (*param->sign)[atten][i];
+        ESP_LOGV(TAG, "term%d is %llu, error is %d", i, term[i], error);
+    }
+
+    return error;
+}
+
+static esp_err_t check_valid(const adc_cali_curve_fitting_config_t *config)
+{
+    ESP_RETURN_ON_FALSE(config->unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid ADC unit");
+    ESP_RETURN_ON_FALSE(config->atten < SOC_ADC_ATTEN_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid ADC attenuation");
+
+    bool available_oneshot_bitwidth = (config->bitwidth >= SOC_ADC_RTC_MIN_BITWIDTH && config->bitwidth <= SOC_ADC_RTC_MAX_BITWIDTH);
+    bool available_dma_bitwidth = (config->bitwidth >= SOC_ADC_DIGI_MIN_BITWIDTH && config->bitwidth <= SOC_ADC_DIGI_MAX_BITWIDTH);
+    bool default_bitwidth_mark = (config->bitwidth == ADC_BITWIDTH_DEFAULT);
+    bool available_bitwidth = (available_oneshot_bitwidth || available_dma_bitwidth || default_bitwidth_mark);
+    ESP_RETURN_ON_FALSE(available_bitwidth, ESP_ERR_INVALID_ARG, TAG, "invalid bitwidth");
+
+    return ESP_OK;
+}
+
+#endif  //#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED

+ 208 - 0
components/esp_adc/adc_common.c

@@ -0,0 +1,208 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include "sdkconfig.h"
+#include "esp_log.h"
+#include "esp_check.h"
+#include "freertos/FreeRTOS.h"
+#include "esp_private/periph_ctrl.h"
+#include "esp_private/adc_private.h"
+#include "driver/gpio.h"
+#include "hal/adc_hal.h"
+#include "hal/adc_hal_common.h"
+#include "hal/adc_hal_conf.h"
+#include "soc/adc_periph.h"
+
+//For calibration
+#if CONFIG_IDF_TARGET_ESP32S2
+#include "esp_efuse_rtc_table.h"
+#elif SOC_ADC_CALIBRATION_V1_SUPPORTED
+#include "esp_efuse_rtc_calib.h"
+#endif
+
+static const char *TAG = "adc_common";
+static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
+extern portMUX_TYPE rtc_spinlock;
+
+/*------------------------------------------------------------------------------
+* For those who use APB_SARADC periph
+*----------------------------------------------------------------------------*/
+static int s_adc_digi_ctrlr_cnt;
+
+void adc_apb_periph_claim(void)
+{
+    portENTER_CRITICAL(&s_spinlock);
+    s_adc_digi_ctrlr_cnt++;
+    if (s_adc_digi_ctrlr_cnt == 1) {
+        //enable ADC digital part
+        periph_module_enable(PERIPH_SARADC_MODULE);
+        //reset ADC digital part
+        periph_module_reset(PERIPH_SARADC_MODULE);
+    }
+
+    portEXIT_CRITICAL(&s_spinlock);
+}
+
+void adc_apb_periph_free(void)
+{
+    portENTER_CRITICAL(&s_spinlock);
+    s_adc_digi_ctrlr_cnt--;
+    if (s_adc_digi_ctrlr_cnt == 0) {
+        periph_module_disable(PERIPH_SARADC_MODULE);
+    } else if (s_adc_digi_ctrlr_cnt < 0) {
+        portEXIT_CRITICAL(&s_spinlock);
+        ESP_LOGE(TAG, "%s called, but `s_adc_digi_ctrlr_cnt == 0`", __func__);
+        abort();
+    }
+
+    portEXIT_CRITICAL(&s_spinlock);
+}
+
+/*------------------------------------------------------------------------------
+* ADC Power
+*----------------------------------------------------------------------------*/
+// This gets incremented when adc_power_acquire() is called, and decremented when
+// adc_power_release() is called. ADC is powered down when the value reaches zero.
+// Should be modified within critical section (ADC_ENTER/EXIT_CRITICAL).
+static int s_adc_power_on_cnt;
+
+static void adc_power_on_internal(void)
+{
+    /* Set the power always on to increase precision. */
+    adc_hal_set_power_manage(ADC_POWER_SW_ON);
+}
+
+void adc_power_acquire(void)
+{
+    portENTER_CRITICAL(&rtc_spinlock);
+    s_adc_power_on_cnt++;
+    if (s_adc_power_on_cnt == 1) {
+        adc_power_on_internal();
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
+}
+
+static void adc_power_off_internal(void)
+{
+#if CONFIG_IDF_TARGET_ESP32
+    adc_hal_set_power_manage(ADC_POWER_SW_OFF);
+#else
+    adc_hal_set_power_manage(ADC_POWER_BY_FSM);
+#endif
+}
+
+void adc_power_release(void)
+{
+    portENTER_CRITICAL(&rtc_spinlock);
+    s_adc_power_on_cnt--;
+    /* Sanity check */
+    if (s_adc_power_on_cnt < 0) {
+        portEXIT_CRITICAL(&rtc_spinlock);
+        ESP_LOGE(TAG, "%s called, but s_adc_power_on_cnt == 0", __func__);
+        abort();
+    } else if (s_adc_power_on_cnt == 0) {
+        adc_power_off_internal();
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
+}
+
+/*---------------------------------------------------------------
+            ADC IOs
+---------------------------------------------------------------*/
+esp_err_t adc_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel)
+{
+    ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(io_num), ESP_ERR_INVALID_ARG, TAG, "invalid gpio number");
+    ESP_RETURN_ON_FALSE(unit_id && channel, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+
+    bool found = false;
+    for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
+        for (int j = 0; j < SOC_ADC_MAX_CHANNEL_NUM; j++) {
+            if (adc_channel_io_map[i][j] == io_num) {
+                *channel = j;
+                *unit_id = i;
+                found = true;
+            }
+        }
+    }
+    return (found) ? ESP_OK : ESP_ERR_NOT_FOUND;
+}
+
+esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num)
+{
+    ESP_RETURN_ON_FALSE(unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid unit");
+    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(unit_id), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
+    ESP_RETURN_ON_FALSE(io_num, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+
+    *io_num = adc_channel_io_map[unit_id][channel];
+    return ESP_OK;
+}
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+/*---------------------------------------------------------------
+            ADC Hardware Calibration
+---------------------------------------------------------------*/
+#if CONFIG_IDF_TARGET_ESP32S2
+#define esp_efuse_rtc_calib_get_ver()     esp_efuse_rtc_table_read_calib_version()
+
+static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
+{
+    int tag = esp_efuse_rtc_table_get_tag(version, adc_unit + 1, atten, RTCCALIB_V2_PARAM_VINIT);
+    return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
+}
+#endif
+
+static uint32_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {};
+
+void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
+{
+    if (s_adc_cali_param[adc_n][atten]) {
+        ESP_EARLY_LOGV(TAG, "Use calibrated val ADC%d atten=%d: %04X", adc_n + 1, atten, s_adc_cali_param[adc_n][atten]);
+        return ;
+    }
+
+    // check if we can fetch the values from eFuse.
+    int version = esp_efuse_rtc_calib_get_ver();
+
+    uint32_t init_code = 0;
+
+    if (version == ESP_EFUSE_ADC_CALIB_VER) {
+        init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
+    } else {
+        ESP_EARLY_LOGD(TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
+        adc_power_acquire();
+        portENTER_CRITICAL(&rtc_spinlock);
+        adc_ll_pwdet_set_cct(ADC_HAL_PWDET_CCT_DEFAULT);
+        const bool internal_gnd = true;
+        init_code = adc_hal_self_calibration(adc_n, atten, internal_gnd);
+        portEXIT_CRITICAL(&rtc_spinlock);
+        adc_power_release();
+    }
+
+    s_adc_cali_param[adc_n][atten] = init_code;
+    ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n + 1, atten, init_code);
+}
+
+void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
+{
+    adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]);
+}
+
+static __attribute__((constructor)) void adc_hw_calibration(void)
+{
+    //Calculate all ICode
+    for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
+        adc_hal_calibration_init(i);
+        for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
+            /**
+             * This may get wrong when attenuations are NOT consecutive on some chips,
+             * update this when bringing up the calibration on that chip
+             */
+            adc_calc_hw_calibration_code(i, j);
+        }
+    }
+}
+#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED

+ 630 - 0
components/esp_adc/adc_continuous.c

@@ -0,0 +1,630 @@
+/*
+ * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "sdkconfig.h"
+#include "esp_intr_alloc.h"
+#include "esp_log.h"
+#include "esp_pm.h"
+#include "esp_check.h"
+#include "esp_heap_caps.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/timers.h"
+#include "freertos/ringbuf.h"
+#include "esp_private/periph_ctrl.h"
+#include "esp_private/adc_private.h"
+#include "esp_private/adc_lock.h"
+#include "driver/gpio.h"
+#include "esp_adc/adc_continuous.h"
+#include "hal/adc_types.h"
+#include "hal/adc_hal.h"
+#include "hal/dma_types.h"
+//For DMA
+#if SOC_GDMA_SUPPORTED
+#include "esp_private/gdma.h"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "hal/spi_types.h"
+#include "esp_private/spi_common_internal.h"
+#elif CONFIG_IDF_TARGET_ESP32
+#include "hal/i2s_types.h"
+#include "driver/i2s_types.h"
+#include "soc/i2s_periph.h"
+#include "esp_private/i2s_platform.h"
+#endif
+
+static const char *ADC_TAG = "adc_continuous";
+
+#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
+
+extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
+#define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
+#define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
+
+#define INTERNAL_BUF_NUM      5
+
+typedef enum {
+    ADC_FSM_INIT,
+    ADC_FSM_STARTED,
+} adc_fsm_t;
+
+/*---------------------------------------------------------------
+            Continuous Mode Driverr Context
+---------------------------------------------------------------*/
+typedef struct adc_continuous_ctx_t {
+    uint8_t                         *rx_dma_buf;                //dma buffer
+    adc_hal_dma_ctx_t               hal;                        //hal context
+#if SOC_GDMA_SUPPORTED
+    gdma_channel_handle_t           rx_dma_channel;             //dma rx channel handle
+#elif CONFIG_IDF_TARGET_ESP32S2
+    spi_host_device_t               spi_host;                   //ADC uses this SPI DMA
+#elif CONFIG_IDF_TARGET_ESP32
+    i2s_port_t                      i2s_host;                   //ADC uses this I2S DMA
+#endif
+    intr_handle_t                   dma_intr_hdl;               //DMA Interrupt handler
+    RingbufHandle_t                 ringbuf_hdl;                //RX ringbuffer handler
+    void*                           ringbuf_storage;            //Ringbuffer storage buffer
+    void*                           ringbuf_struct;             //Ringbuffer structure buffer
+    intptr_t                        rx_eof_desc_addr;           //eof descriptor address of RX channel
+    adc_fsm_t                       fsm;                        //ADC continuous mode driver internal states
+    bool                            use_adc1;                   //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
+    bool                            use_adc2;                   //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
+    adc_atten_t                     adc1_atten;                 //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
+    adc_atten_t                     adc2_atten;                 //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
+    adc_hal_digi_ctrlr_cfg_t        hal_digi_ctrlr_cfg;         //Hal digital controller configuration
+    adc_continuous_evt_cbs_t    cbs;                        //Callbacks
+    void                            *user_data;                 //User context
+    esp_pm_lock_handle_t            pm_lock;                    //For power management
+} adc_continuous_ctx_t;
+
+#ifdef CONFIG_PM_ENABLE
+//Only for deprecated API
+extern esp_pm_lock_handle_t adc_digi_arbiter_lock;
+#endif  //CONFIG_PM_ENABLE
+
+/*---------------------------------------------------------------
+                   ADC Continuous Read Mode (via DMA)
+---------------------------------------------------------------*/
+//Function to address transaction
+static bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx);
+
+#if SOC_GDMA_SUPPORTED
+static bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
+#else
+static void adc_dma_intr_handler(void *arg);
+#endif
+
+static int8_t adc_digi_get_io_num(adc_unit_t adc_unit, uint8_t adc_channel)
+{
+    assert(adc_unit <= SOC_ADC_PERIPH_NUM);
+    uint8_t adc_n = (adc_unit == ADC_UNIT_1) ? 0 : 1;
+    return adc_channel_io_map[adc_n][adc_channel];
+}
+
+static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
+{
+    esp_err_t ret = ESP_OK;
+    uint64_t gpio_mask = 0;
+    uint32_t n = 0;
+    int8_t io = 0;
+
+    while (channel_mask) {
+        if (channel_mask & 0x1) {
+            io = adc_digi_get_io_num(adc_unit, n);
+            if (io < 0) {
+                return ESP_ERR_INVALID_ARG;
+            }
+            gpio_mask |= BIT64(io);
+        }
+        channel_mask = channel_mask >> 1;
+        n++;
+    }
+
+    gpio_config_t cfg = {
+        .pin_bit_mask = gpio_mask,
+        .mode = GPIO_MODE_DISABLE,
+    };
+    ret = gpio_config(&cfg);
+
+    return ret;
+}
+
+esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_config, adc_continuous_handle_t *ret_handle)
+{
+    esp_err_t ret = ESP_OK;
+    ESP_RETURN_ON_FALSE((hdl_config->conv_frame_size % SOC_ADC_DIGI_DATA_BYTES_PER_CONV == 0), ESP_ERR_INVALID_ARG, ADC_TAG, "conv_frame_size should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`");
+
+    adc_continuous_ctx_t *adc_ctx = heap_caps_calloc(1, sizeof(adc_continuous_ctx_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    if (adc_ctx == NULL) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //ringbuffer storage/struct buffer
+    adc_ctx->ringbuf_storage = heap_caps_calloc(1, hdl_config->max_store_buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    adc_ctx->ringbuf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    if (!adc_ctx->ringbuf_storage || !adc_ctx->ringbuf_struct) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //ringbuffer
+    adc_ctx->ringbuf_hdl = xRingbufferCreateStatic(hdl_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF, adc_ctx->ringbuf_storage, adc_ctx->ringbuf_struct);
+    if (!adc_ctx->ringbuf_hdl) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //malloc internal buffer used by DMA
+    adc_ctx->rx_dma_buf = heap_caps_calloc(1, hdl_config->conv_frame_size * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
+    if (!adc_ctx->rx_dma_buf) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //malloc dma descriptor
+    adc_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
+    if (!adc_ctx->hal.rx_desc) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //malloc pattern table
+    adc_ctx->hal_digi_ctrlr_cfg.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_config_t));
+    if (!adc_ctx->hal_digi_ctrlr_cfg.adc_pattern) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+#if CONFIG_PM_ENABLE
+    ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &adc_ctx->pm_lock);
+    if (ret != ESP_OK) {
+        goto cleanup;
+    }
+#endif //CONFIG_PM_ENABLE
+
+#if SOC_GDMA_SUPPORTED
+    //alloc rx gdma channel
+    gdma_channel_alloc_config_t rx_alloc_config = {
+        .direction = GDMA_CHANNEL_DIRECTION_RX,
+    };
+    ret = gdma_new_channel(&rx_alloc_config, &adc_ctx->rx_dma_channel);
+    if (ret != ESP_OK) {
+        goto cleanup;
+    }
+    gdma_connect(adc_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
+
+    gdma_strategy_config_t strategy_config = {
+        .auto_update_desc = true,
+        .owner_check = true
+    };
+    gdma_apply_strategy(adc_ctx->rx_dma_channel, &strategy_config);
+
+    gdma_rx_event_callbacks_t cbs = {
+        .on_recv_eof = adc_dma_in_suc_eof_callback
+    };
+    gdma_register_rx_event_callbacks(adc_ctx->rx_dma_channel, &cbs, adc_ctx);
+
+    int dma_chan;
+    gdma_get_channel_id(adc_ctx->rx_dma_channel, &dma_chan);
+
+#elif CONFIG_IDF_TARGET_ESP32S2
+    //ADC utilises SPI3 DMA on ESP32S2
+    bool spi_success = false;
+    uint32_t dma_chan = 0;
+
+    spi_success = spicommon_periph_claim(SPI3_HOST, "adc");
+    ret = spicommon_dma_chan_alloc(SPI3_HOST, SPI_DMA_CH_AUTO, &dma_chan, &dma_chan);
+    if (ret == ESP_OK) {
+        adc_ctx->spi_host = SPI3_HOST;
+    }
+    if (!spi_success || (adc_ctx->spi_host != SPI3_HOST)) {
+        goto cleanup;
+    }
+
+    ret = esp_intr_alloc(spicommon_irqdma_source_for_host(adc_ctx->spi_host), ESP_INTR_FLAG_IRAM, adc_dma_intr_handler,
+                        (void *)adc_ctx, &adc_ctx->dma_intr_hdl);
+    if (ret != ESP_OK) {
+        goto cleanup;
+    }
+
+#elif CONFIG_IDF_TARGET_ESP32
+    //ADC utilises I2S0 DMA on ESP32
+    uint32_t dma_chan = 0;
+    ret = i2s_platform_acquire_occupation(I2S_NUM_0, "adc");
+    if (ret != ESP_OK) {
+        ret = ESP_ERR_NOT_FOUND;
+        goto cleanup;
+    }
+
+    adc_ctx->i2s_host = I2S_NUM_0;
+    ret = esp_intr_alloc(i2s_periph_signal[adc_ctx->i2s_host].irq, ESP_INTR_FLAG_IRAM, adc_dma_intr_handler,
+                        (void *)adc_ctx, &adc_ctx->dma_intr_hdl);
+    if (ret != ESP_OK) {
+        goto cleanup;
+    }
+#endif
+
+    adc_hal_dma_config_t config = {
+#if SOC_GDMA_SUPPORTED
+        .dev = (void *)GDMA_LL_GET_HW(0),
+#elif CONFIG_IDF_TARGET_ESP32S2
+        .dev = (void *)SPI_LL_GET_HW(adc_ctx->spi_host),
+#elif CONFIG_IDF_TARGET_ESP32
+        .dev = (void *)I2S_LL_GET_HW(adc_ctx->i2s_host),
+#endif
+        .desc_max_num = INTERNAL_BUF_NUM,
+        .dma_chan = dma_chan,
+        .eof_num = hdl_config->conv_frame_size / SOC_ADC_DIGI_DATA_BYTES_PER_CONV
+    };
+    adc_hal_dma_ctx_config(&adc_ctx->hal, &config);
+
+    adc_ctx->fsm = ADC_FSM_INIT;
+    *ret_handle = adc_ctx;
+
+    //enable ADC digital part
+    periph_module_enable(PERIPH_SARADC_MODULE);
+    //reset ADC digital part
+    periph_module_reset(PERIPH_SARADC_MODULE);
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_hal_calibration_init(ADC_UNIT_1);
+    adc_hal_calibration_init(ADC_UNIT_2);
+#endif  //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+
+    return ret;
+
+cleanup:
+    adc_continuous_deinit(adc_ctx);
+    return ret;
+}
+
+#if SOC_GDMA_SUPPORTED
+static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
+{
+    assert(event_data);
+    adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)user_data;
+    ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
+    return s_adc_dma_intr(user_data);
+}
+#else
+static IRAM_ATTR void adc_dma_intr_handler(void *arg)
+{
+    adc_continuous_ctx_t *ctx = (adc_continuous_ctx_t *)arg;
+    bool need_yield = false;
+
+    bool conversion_finish = adc_hal_check_event(&ctx->hal, ADC_HAL_DMA_INTR_MASK);
+    if (conversion_finish) {
+        adc_hal_digi_clr_intr(&ctx->hal, ADC_HAL_DMA_INTR_MASK);
+
+        intptr_t desc_addr = adc_hal_get_desc_addr(&ctx->hal);
+
+        ctx->rx_eof_desc_addr = desc_addr;
+        need_yield = s_adc_dma_intr(ctx);
+    }
+
+    if (need_yield) {
+        portYIELD_FROM_ISR();
+    }
+}
+#endif
+
+static IRAM_ATTR bool s_adc_dma_intr(adc_continuous_ctx_t *adc_digi_ctx)
+{
+    portBASE_TYPE taskAwoken = 0;
+    bool need_yield = false;
+    BaseType_t ret;
+    adc_hal_dma_desc_status_t status = false;
+    dma_descriptor_t *current_desc = NULL;
+
+    while (1) {
+        status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &current_desc);
+        if (status != ADC_HAL_DMA_DESC_VALID) {
+            break;
+        }
+
+        ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
+        need_yield |= (taskAwoken == pdTRUE);
+
+        if (adc_digi_ctx->cbs.on_conv_done) {
+            adc_continuous_evt_data_t edata = {
+                .conv_frame_buffer = current_desc->buffer,
+                .size = current_desc->dw0.length,
+            };
+            if (adc_digi_ctx->cbs.on_conv_done(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) {
+                need_yield |= true;
+            }
+        }
+
+        if (ret == pdFALSE) {
+            //ringbuffer overflow
+            if (adc_digi_ctx->cbs.on_pool_ovf) {
+                adc_continuous_evt_data_t edata = {};
+                if (adc_digi_ctx->cbs.on_conv_done(adc_digi_ctx, &edata, adc_digi_ctx->user_data)) {
+                    need_yield |= true;
+                }
+            }
+        }
+    }
+
+    if (status == ADC_HAL_DMA_DESC_NULL) {
+        //start next turns of dma operation
+        adc_hal_digi_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
+    }
+
+    return need_yield;
+}
+
+esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
+    ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, ADC_TAG, "ADC continuous mode isn't in the init state, it's started already");
+
+    if (handle->pm_lock) {
+        ESP_RETURN_ON_ERROR(esp_pm_lock_acquire(handle->pm_lock), ADC_TAG, "acquire pm_lock failed");
+    }
+
+    handle->fsm = ADC_FSM_STARTED;
+    adc_power_acquire();
+    //reset flags
+    if (handle->use_adc1) {
+        adc_lock_acquire(ADC_UNIT_1);
+    }
+    if (handle->use_adc2) {
+        adc_lock_acquire(ADC_UNIT_2);
+    }
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    if (handle->use_adc1) {
+        adc_set_hw_calibration_code(ADC_UNIT_1, handle->adc1_atten);
+    }
+    if (handle->use_adc2) {
+        adc_set_hw_calibration_code(ADC_UNIT_2, handle->adc2_atten);
+    }
+#endif  //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+
+#if SOC_ADC_ARBITER_SUPPORTED
+    if (handle->use_adc2) {
+        adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
+        adc_hal_arbiter_config(&config);
+    }
+#endif  //#if SOC_ADC_ARBITER_SUPPORTED
+
+    if (handle->use_adc1) {
+        adc_hal_set_controller(ADC_UNIT_1, ADC_HAL_CONTINUOUS_READ_MODE);
+    }
+    if (handle->use_adc2) {
+        adc_hal_set_controller(ADC_UNIT_2, ADC_HAL_CONTINUOUS_READ_MODE);
+    }
+
+    adc_hal_digi_init(&handle->hal);
+    adc_hal_digi_controller_config(&handle->hal, &handle->hal_digi_ctrlr_cfg);
+
+    //start conversion
+    adc_hal_digi_start(&handle->hal, handle->rx_dma_buf);
+
+    return ESP_OK;
+}
+
+esp_err_t adc_continuous_stop(adc_continuous_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
+    ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_STARTED, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver is already stopped");
+
+    handle->fsm = ADC_FSM_INIT;
+    //disable the in suc eof intrrupt
+    adc_hal_digi_dis_intr(&handle->hal, ADC_HAL_DMA_INTR_MASK);
+    //clear the in suc eof interrupt
+    adc_hal_digi_clr_intr(&handle->hal, ADC_HAL_DMA_INTR_MASK);
+    //stop ADC
+    adc_hal_digi_stop(&handle->hal);
+
+    adc_hal_digi_deinit(&handle->hal);
+#if CONFIG_PM_ENABLE
+    if (handle->pm_lock) {
+        esp_pm_lock_release(handle->pm_lock);
+    }
+#endif  //CONFIG_PM_ENABLE
+
+    if (handle->use_adc2) {
+        adc_lock_release(ADC_UNIT_2);
+    }
+    if (handle->use_adc1) {
+        adc_lock_release(ADC_UNIT_1);
+    }
+    adc_power_release();
+
+    //release power manager lock
+    if (handle->pm_lock) {
+        ESP_RETURN_ON_ERROR(esp_pm_lock_release(handle->pm_lock), ADC_TAG, "release pm_lock failed");
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc_continuous_read(adc_continuous_handle_t handle, uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
+    ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_STARTED, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver is already stopped");
+
+    TickType_t ticks_to_wait;
+    esp_err_t ret = ESP_OK;
+    uint8_t *data = NULL;
+    size_t size = 0;
+
+    ticks_to_wait = timeout_ms / portTICK_PERIOD_MS;
+    if (timeout_ms == ADC_MAX_DELAY) {
+        ticks_to_wait = portMAX_DELAY;
+    }
+
+    data = xRingbufferReceiveUpTo(handle->ringbuf_hdl, &size, ticks_to_wait, length_max);
+    if (!data) {
+        ESP_LOGV(ADC_TAG, "No data, increase timeout");
+        ret = ESP_ERR_TIMEOUT;
+        *out_length = 0;
+        return ret;
+    }
+
+    memcpy(buf, data, size);
+    vRingbufferReturnItem(handle->ringbuf_hdl, data);
+    assert((size % 4) == 0);
+    *out_length = size;
+
+    return ret;
+}
+
+esp_err_t adc_continuous_deinit(adc_continuous_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
+    ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver is still running");
+
+    if (handle->ringbuf_hdl) {
+        vRingbufferDelete(handle->ringbuf_hdl);
+        handle->ringbuf_hdl = NULL;
+        free(handle->ringbuf_storage);
+        free(handle->ringbuf_struct);
+    }
+
+#if CONFIG_PM_ENABLE
+    if (handle->pm_lock) {
+        esp_pm_lock_delete(handle->pm_lock);
+    }
+#endif  //CONFIG_PM_ENABLE
+
+    free(handle->rx_dma_buf);
+    free(handle->hal.rx_desc);
+    free(handle->hal_digi_ctrlr_cfg.adc_pattern);
+#if SOC_GDMA_SUPPORTED
+    gdma_disconnect(handle->rx_dma_channel);
+    gdma_del_channel(handle->rx_dma_channel);
+#elif CONFIG_IDF_TARGET_ESP32S2
+    esp_intr_free(handle->dma_intr_hdl);
+    spicommon_dma_chan_free(handle->spi_host);
+    spicommon_periph_free(handle->spi_host);
+#elif CONFIG_IDF_TARGET_ESP32
+    esp_intr_free(handle->dma_intr_hdl);
+    i2s_platform_release_occupation(handle->i2s_host);
+#endif
+    free(handle);
+    handle = NULL;
+
+    periph_module_disable(PERIPH_SARADC_MODULE);
+
+    return ESP_OK;
+}
+
+/*---------------------------------------------------------------
+                    Digital controller setting
+---------------------------------------------------------------*/
+esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_continuous_config_t *config)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_STATE, ADC_TAG, "The driver isn't initialised");
+    ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, ADC_TAG, "ADC continuous mode isn't in the init state, it's started already");
+
+    //Pattern related check
+    ESP_RETURN_ON_FALSE(config->pattern_num <= SOC_ADC_PATT_LEN_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "Max pattern num is %d", SOC_ADC_PATT_LEN_MAX);
+#if CONFIG_IDF_TARGET_ESP32
+    for (int i = 0; i < config->pattern_num; i++) {
+        ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width >= SOC_ADC_DIGI_MIN_BITWIDTH && config->adc_pattern->bit_width <= SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported");
+        ESP_RETURN_ON_FALSE(config->adc_pattern[i].unit == 0, ESP_ERR_INVALID_ARG, ADC_TAG, "Only support using ADC1 DMA mode");
+    }
+#else
+    for (int i = 0; i < config->pattern_num; i++) {
+        ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width == SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported");
+    }
+#endif
+    ESP_RETURN_ON_FALSE(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC sampling frequency out of range");
+
+#if CONFIG_IDF_TARGET_ESP32
+    ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
+#elif CONFIG_IDF_TARGET_ESP32S2
+    if (config->conv_mode == ADC_CONV_BOTH_UNIT || config->conv_mode == ADC_CONV_ALTER_UNIT) {
+        ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
+    } else if (config->conv_mode == ADC_CONV_SINGLE_UNIT_1 || config->conv_mode == ADC_CONV_SINGLE_UNIT_2) {
+        ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
+    }
+#else
+    ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
+#endif
+
+    handle->hal_digi_ctrlr_cfg.adc_pattern_len = config->pattern_num;
+    handle->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz;
+    handle->hal_digi_ctrlr_cfg.conv_mode = config->conv_mode;
+    memcpy(handle->hal_digi_ctrlr_cfg.adc_pattern, config->adc_pattern, config->pattern_num * sizeof(adc_digi_pattern_config_t));
+
+    const int atten_uninitialized = 999;
+    handle->adc1_atten = atten_uninitialized;
+    handle->adc2_atten = atten_uninitialized;
+    handle->use_adc1 = 0;
+    handle->use_adc2 = 0;
+    uint32_t adc1_chan_mask = 0;
+    uint32_t adc2_chan_mask = 0;
+    for (int i = 0; i < config->pattern_num; i++) {
+        const adc_digi_pattern_config_t *pat = &config->adc_pattern[i];
+        if (pat->unit == ADC_UNIT_1) {
+            handle->use_adc1 = 1;
+            adc1_chan_mask |= BIT(pat->channel);
+
+            if (handle->adc1_atten == atten_uninitialized) {
+                handle->adc1_atten = pat->atten;
+            } else if (handle->adc1_atten != pat->atten) {
+                return ESP_ERR_INVALID_ARG;
+            }
+        } else if (pat->unit == ADC_UNIT_2) {
+            handle->use_adc2 = 1;
+            adc2_chan_mask |= BIT(pat->channel);
+
+            if (handle->adc2_atten == atten_uninitialized) {
+                handle->adc2_atten = pat->atten;
+            } else if (handle->adc2_atten != pat->atten) {
+                return ESP_ERR_INVALID_ARG;
+            }
+        }
+    }
+
+    if (handle->use_adc1) {
+        adc_digi_gpio_init(ADC_UNIT_1, adc1_chan_mask);
+    }
+    if (handle->use_adc2) {
+        adc_digi_gpio_init(ADC_UNIT_2, adc2_chan_mask);
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc_continuous_register_event_callbacks(adc_continuous_handle_t handle, const adc_continuous_evt_cbs_t *cbs, void *user_data)
+{
+    ESP_RETURN_ON_FALSE(handle && cbs, ESP_ERR_INVALID_ARG, ADC_TAG, "invalid argument");
+    ESP_RETURN_ON_FALSE(handle->fsm == ADC_FSM_INIT, ESP_ERR_INVALID_STATE, ADC_TAG, "ADC continuous mode isn't in the init state, it's started already");
+
+#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE
+    if (cbs->on_conv_done) {
+        ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_conv_done), ESP_ERR_INVALID_ARG, ADC_TAG, "on_conv_done callback not in IRAM");
+    }
+    if (cbs->on_pool_ovf) {
+        ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_pool_ovf), ESP_ERR_INVALID_ARG, ADC_TAG, "on_pool_ovf callback not in IRAM");
+    }
+#endif
+
+    handle->cbs.on_conv_done = cbs->on_conv_done;
+    handle->cbs.on_pool_ovf = cbs->on_pool_ovf;
+    handle->user_data = user_data;
+
+    return ESP_OK;
+}
+
+esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel)
+{
+    return adc_io_to_channel(io_num, unit_id, channel);
+}
+
+esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num)
+{
+    return adc_channel_to_io(unit_id, channel, io_num);
+}

+ 87 - 0
components/esp_adc/adc_lock.c

@@ -0,0 +1,87 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include "sdkconfig.h"
+#include "sys/lock.h"
+#include "esp_log.h"
+#include "esp_err.h"
+#include "esp_check.h"
+#include "hal/adc_types.h"
+
+#include "esp_private/adc_lock.h"
+#include "esp_private/adc2_wifi.h"
+
+
+static const char *TAG = "adc_lock";
+
+static _lock_t adc1_lock;
+static _lock_t adc2_lock;
+
+esp_err_t adc_lock_acquire(adc_unit_t unit_mask)
+{
+    if (unit_mask & ADC_UNIT_1) {
+        _lock_acquire(&adc1_lock);
+    }
+
+    if (unit_mask & ADC_UNIT_2) {
+        _lock_acquire(&adc2_lock);
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc_lock_release(adc_unit_t unit_mask)
+{
+    if (unit_mask & ADC_UNIT_2) {
+        ESP_RETURN_ON_FALSE(((uint32_t *)adc2_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc2 lock release without acquiring");
+        _lock_release(&adc2_lock);
+    }
+
+    if (unit_mask & ADC_UNIT_1) {
+        ESP_RETURN_ON_FALSE(((uint32_t *)adc1_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc1 lock release without acquiring");
+        _lock_release(&adc1_lock);
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc_lock_try_acquire(adc_unit_t unit_mask)
+{
+    if (unit_mask & ADC_UNIT_1) {
+        if (_lock_try_acquire(&adc1_lock) == -1) {
+            return ESP_ERR_TIMEOUT;
+        }
+    }
+
+    if (unit_mask & ADC_UNIT_2) {
+        if (_lock_try_acquire(&adc2_lock) == -1) {
+            return ESP_ERR_TIMEOUT;
+        }
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc2_wifi_acquire(void)
+{
+#if CONFIG_IDF_TARGET_ESP32
+    /* Wi-Fi module will use adc2. Use locks to avoid conflicts. */
+    adc_lock_acquire(ADC_UNIT_2);
+    ESP_LOGD(TAG, "Wi-Fi takes adc2 lock.");
+#endif
+
+    return ESP_OK;
+}
+
+esp_err_t adc2_wifi_release(void)
+{
+#if CONFIG_IDF_TARGET_ESP32
+    return adc_lock_release(ADC_UNIT_2);
+#endif
+
+    return ESP_OK;
+}

+ 260 - 0
components/esp_adc/adc_oneshot.c

@@ -0,0 +1,260 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include <sys/lock.h>
+#include "sdkconfig.h"
+#include "stdatomic.h"
+#include "esp_log.h"
+#include "esp_check.h"
+#include "esp_heap_caps.h"
+#include "freertos/FreeRTOS.h"
+#include "driver/gpio.h"
+#include "driver/rtc_io.h"
+#include "esp_adc/adc_oneshot.h"
+#include "esp_private/adc_private.h"
+#include "esp_private/adc_lock.h"
+#include "hal/adc_types.h"
+#include "hal/adc_oneshot_hal.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_hal_conf.h"
+#include "soc/adc_periph.h"
+
+
+#if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM
+#define ADC_MEM_ALLOC_CAPS   (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
+#else
+#define ADC_MEM_ALLOC_CAPS   MALLOC_CAP_DEFAULT
+#endif
+
+
+extern portMUX_TYPE rtc_spinlock;
+static const char *TAG = "adc_oneshot";
+
+
+typedef struct adc_oneshot_unit_ctx_t {
+    adc_oneshot_hal_ctx_t hal;
+    uint32_t unit_id;
+    adc_ulp_mode_t ulp_mode;
+} adc_oneshot_unit_ctx_t;
+
+typedef struct adc_oneshot_ctx_t {
+    _lock_t mutex;
+    adc_oneshot_unit_ctx_t *units[SOC_ADC_PERIPH_NUM];
+    int apb_periph_ref_cnts;       //For the chips that ADC oneshot mode using APB_SARADC periph
+} adc_oneshot_ctx_t;
+
+
+static adc_oneshot_ctx_t s_ctx;    //ADC oneshot mode context
+static atomic_bool s_adc_unit_claimed[SOC_ADC_PERIPH_NUM] = {ATOMIC_VAR_INIT(false),
+#if (SOC_ADC_PERIPH_NUM >= 2)
+ATOMIC_VAR_INIT(false)
+#endif
+};
+
+
+static bool s_adc_unit_claim(adc_unit_t unit);
+static bool s_adc_unit_free(adc_unit_t unit);
+static esp_err_t s_adc_io_init(adc_unit_t unit, adc_channel_t channel);
+
+
+esp_err_t adc_oneshot_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel)
+{
+    return adc_io_to_channel(io_num, unit_id, channel);
+}
+
+esp_err_t adc_oneshot_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num)
+{
+    return adc_channel_to_io(unit_id, channel, io_num);
+}
+
+esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, adc_oneshot_unit_handle_t *ret_unit)
+{
+    esp_err_t ret = ESP_OK;
+    adc_oneshot_unit_ctx_t *unit = NULL;
+    ESP_GOTO_ON_FALSE(init_config && ret_unit, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument: null pointer");
+    ESP_GOTO_ON_FALSE(init_config->unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, err, TAG, "invalid unit");
+
+    unit = heap_caps_calloc(1, sizeof(adc_oneshot_unit_ctx_t), ADC_MEM_ALLOC_CAPS);
+    ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no mem for unit");
+
+    bool success_claim = s_adc_unit_claim(init_config->unit_id);
+    ESP_GOTO_ON_FALSE(success_claim, ESP_ERR_NOT_FOUND, err, TAG, "adc%d is already in use", init_config->unit_id + 1);
+    _lock_acquire(&s_ctx.mutex);
+    s_ctx.units[init_config->unit_id] = unit;
+    _lock_release(&s_ctx.mutex);
+    unit->unit_id = init_config->unit_id;
+    unit->ulp_mode = init_config->ulp_mode;
+
+    adc_oneshot_hal_cfg_t config = {
+        .unit = init_config->unit_id,
+        .work_mode = (init_config->ulp_mode == ADC_ULP_MODE_FSM) ? ADC_HAL_ULP_FSM_MODE : ADC_HAL_SINGLE_READ_MODE,
+    };
+    adc_oneshot_hal_init(&(unit->hal), &config);
+
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+    //To enable the APB_SARADC periph if needed
+    _lock_acquire(&s_ctx.mutex);
+    s_ctx.apb_periph_ref_cnts++;
+    if (s_ctx.apb_periph_ref_cnts == 1) {
+        adc_apb_periph_claim();
+    }
+    _lock_release(&s_ctx.mutex);
+#endif
+
+    adc_power_acquire();
+
+    ESP_LOGD(TAG, "new adc unit%d is created", unit->unit_id);
+    *ret_unit = unit;
+    return ESP_OK;
+
+err:
+    if (unit) {
+        free(unit);
+    }
+    return ret;
+}
+
+esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, adc_channel_t channel, const adc_oneshot_chan_cfg_t *config)
+{
+    ESP_RETURN_ON_FALSE(handle && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    ESP_RETURN_ON_FALSE(config->atten < SOC_ADC_ATTEN_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid attenuation");
+    ESP_RETURN_ON_FALSE(((config->bitwidth >= SOC_ADC_RTC_MIN_BITWIDTH && config->bitwidth <= SOC_ADC_RTC_MAX_BITWIDTH) || config->bitwidth == ADC_BITWIDTH_DEFAULT), ESP_ERR_INVALID_ARG, TAG, "invalid bitwidth");
+    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(handle->unit_id), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
+
+    s_adc_io_init(handle->unit_id, channel);
+
+    adc_oneshot_hal_ctx_t *hal = &(handle->hal);
+    adc_oneshot_hal_chan_cfg_t cfg = {
+        .atten = config->atten,
+        .bitwidth = (config->bitwidth == ADC_BITWIDTH_DEFAULT) ? SOC_ADC_RTC_MAX_BITWIDTH : config->bitwidth,
+    };
+    portENTER_CRITICAL(&rtc_spinlock);
+    adc_oneshot_hal_channel_config(hal, &cfg, channel);
+    if (handle->ulp_mode) {
+        adc_oneshot_hal_setup(hal, channel);
+    }
+    portEXIT_CRITICAL(&rtc_spinlock);
+
+    return ESP_OK;
+}
+
+esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw)
+{
+    ESP_RETURN_ON_FALSE(handle && out_raw, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    ESP_RETURN_ON_FALSE(chan < SOC_ADC_CHANNEL_NUM(handle->unit_id), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
+
+    if (adc_lock_try_acquire(handle->unit_id) != ESP_OK) {
+        return ESP_ERR_TIMEOUT;
+    }
+    portENTER_CRITICAL(&rtc_spinlock);
+
+    adc_oneshot_hal_setup(&(handle->hal), chan);
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan);
+    adc_hal_calibration_init(handle->unit_id);
+    adc_set_hw_calibration_code(handle->unit_id, atten);
+#endif
+    bool valid = false;
+    valid = adc_oneshot_hal_convert(&(handle->hal), out_raw);
+
+    portEXIT_CRITICAL(&rtc_spinlock);
+    adc_lock_release(handle->unit_id);
+
+    return valid ? ESP_OK : ESP_ERR_TIMEOUT;
+}
+
+esp_err_t adc_oneshot_read_isr(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw)
+{
+    ESP_RETURN_ON_FALSE_ISR(handle && out_raw, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    ESP_RETURN_ON_FALSE_ISR(out_raw, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    ESP_RETURN_ON_FALSE_ISR(chan < SOC_ADC_CHANNEL_NUM(handle->unit_id), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
+
+    portENTER_CRITICAL_SAFE(&rtc_spinlock);
+
+    adc_oneshot_hal_setup(&(handle->hal), chan);
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+    adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan);
+    adc_hal_calibration_init(handle->unit_id);
+    adc_set_hw_calibration_code(handle->unit_id, atten);
+#endif
+
+    adc_oneshot_hal_convert(&(handle->hal), out_raw);
+
+    portEXIT_CRITICAL_SAFE(&rtc_spinlock);
+
+    return ESP_OK;
+}
+
+esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    bool success_free = s_adc_unit_free(handle->unit_id);
+    ESP_RETURN_ON_FALSE(success_free, ESP_ERR_NOT_FOUND, TAG, "adc%d isn't in use", handle->unit_id + 1);
+
+    _lock_acquire(&s_ctx.mutex);
+    s_ctx.units[handle->unit_id] = NULL;
+    _lock_release(&s_ctx.mutex);
+
+    ESP_LOGD(TAG, "adc unit%d is deleted", handle->unit_id);
+    free(handle);
+
+    adc_power_release();
+
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+    //To free the APB_SARADC periph if needed
+    _lock_acquire(&s_ctx.mutex);
+    s_ctx.apb_periph_ref_cnts--;
+    assert(s_ctx.apb_periph_ref_cnts >= 0);
+    if (s_ctx.apb_periph_ref_cnts == 0) {
+        adc_apb_periph_free();
+    }
+    _lock_release(&s_ctx.mutex);
+#endif
+
+    return ESP_OK;
+}
+
+
+#define ADC_GET_IO_NUM(unit, channel) (adc_channel_io_map[unit][channel])
+
+static esp_err_t s_adc_io_init(adc_unit_t unit, adc_channel_t channel)
+{
+    ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(unit), ESP_ERR_INVALID_ARG, TAG, "invalid channel");
+
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+
+    uint32_t io_num = ADC_GET_IO_NUM(unit, channel);
+    gpio_config_t cfg = {
+        .pin_bit_mask = BIT64(io_num),
+        .mode = GPIO_MODE_DISABLE,
+        .pull_up_en = GPIO_PULLUP_DISABLE,
+        .pull_down_en = GPIO_PULLDOWN_DISABLE,
+        .intr_type = GPIO_INTR_DISABLE,
+    };
+    ESP_RETURN_ON_ERROR(gpio_config(&cfg), TAG, "IO config fail");
+#else
+    gpio_num_t io_num = ADC_GET_IO_NUM(unit, channel);
+    ESP_RETURN_ON_ERROR(rtc_gpio_init(io_num), TAG, "IO config fail");
+    ESP_RETURN_ON_ERROR(rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_DISABLED), TAG, "IO config fail");
+    ESP_RETURN_ON_ERROR(rtc_gpio_pulldown_dis(io_num), TAG, "IO config fail");
+    ESP_RETURN_ON_ERROR(rtc_gpio_pullup_dis(io_num), TAG, "IO config fail");
+#endif
+
+    return ESP_OK;
+}
+
+static bool s_adc_unit_claim(adc_unit_t unit)
+{
+    bool false_var = false;
+    return atomic_compare_exchange_strong(&s_adc_unit_claimed[unit], &false_var, true);
+}
+
+static bool s_adc_unit_free(adc_unit_t unit)
+{
+    bool true_var = true;
+    return atomic_compare_exchange_strong(&s_adc_unit_claimed[unit], &true_var, false);
+}

+ 33 - 0
components/esp_adc/curve_fitting_coefficients.h

@@ -0,0 +1,33 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+#include <stdint.h>
+
+#define COEFF_GROUP_NUM    4
+#define TERM_MAX           5
+
+/**
+ * @note Error Calculation
+ * Coefficients for calculating the reading voltage error.
+ * Four sets of coefficients for atten0 ~ atten3 respectively.
+ *
+ * For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient.
+ *
+ * @note {0,0} stands for unused item
+ * @note In case of the overflow, these coeffcients are recorded as Absolute Value
+ * @note For atten0 ~ 2, error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2); For atten3, error = (K0 * X^0) + (K1 * X^1)  + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
+ * @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered.
+ * @note ADC1 and ADC2 use same coeffients
+ */
+extern const uint64_t adc1_error_coef_atten[COEFF_GROUP_NUM][TERM_MAX][2];
+extern const uint64_t adc2_error_coef_atten[COEFF_GROUP_NUM][TERM_MAX][2];
+
+/**
+ * Term sign
+ */
+extern const int32_t adc1_error_sign[COEFF_GROUP_NUM][TERM_MAX];
+extern const int32_t adc2_error_sign[COEFF_GROUP_NUM][TERM_MAX];

+ 4 - 3
components/esp_adc_cal/esp32/esp_adc_cal.c → components/esp_adc/deprecated/esp32/esp_adc_cal_legacy.c

@@ -6,12 +6,13 @@
 
 #include <stdint.h>
 #include "esp_types.h"
-#include "driver/adc.h"
-#include "hal/efuse_ll.h"
 #include "esp_err.h"
 #include "esp_check.h"
 #include "assert.h"
-#include "esp_adc_cal.h"
+#include "hal/efuse_ll.h"
+#include "hal/adc_types.h"
+#include "driver/adc_types_legacy.h"
+#include "esp_adc_cal_types_legacy.h"
 
 /* ----------------------------- Configuration ------------------------------ */
 #ifdef CONFIG_ADC_CAL_EFUSE_TP_ENABLE

+ 11 - 7
components/esp_adc_cal/esp32c3/esp_adc_cal.c → components/esp_adc/deprecated/esp32c3/esp_adc_cal_legacy.c

@@ -11,11 +11,12 @@
 #include "esp_err.h"
 #include "esp_log.h"
 #include "esp_check.h"
-#include "driver/adc.h"
-#include "hal/adc_ll.h"
 #include "esp_efuse_rtc_calib.h"
-#include "esp_adc_cal.h"
-#include "../esp_adc_cal_internal.h"
+#include "hal/adc_ll.h"
+#include "hal/adc_types.h"
+#include "driver/adc_types_legacy.h"
+#include "esp_adc_cal_types_legacy.h"
+#include "../esp_adc_cal_internal_legacy.h"
 
 const static char LOG_TAG[] = "ADC_CALI";
 
@@ -79,9 +80,12 @@ static esp_err_t prepare_calib_data_for(int version_num, adc_unit_t adc_num, adc
     parsed_data_storage->version_num = version_num;
     parsed_data_storage->adc_num = adc_num;
     parsed_data_storage->atten_level = atten;
-    // V1 we don't have calibration data for ADC2, using the efuse data of ADC1
     uint32_t voltage, digi;
-    ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, atten, &digi, &voltage);
+    /**
+     * V1 we don't have calibration data for ADC2, using the efuse data of ADC1.
+     * Here passing the `adc_num` is just for compatibility
+     */
+    ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, adc_num, atten, &digi, &voltage);
     if (ret != ESP_OK) {
         return ret;
     }
@@ -129,7 +133,7 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
     ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num");
     ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic");
     ESP_RETURN_ON_FALSE(bit_width == ADC_WIDTH_BIT_12, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid bit_width");
-    ESP_RETURN_ON_FALSE(atten < 4, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation");
+    ESP_RETURN_ON_FALSE(atten < SOC_ADC_ATTEN_NUM, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation");
 
     int version_num = esp_efuse_rtc_calib_get_ver();
     ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt");

+ 3 - 2
components/esp_adc_cal/esp32s2/esp_adc_cal.c → components/esp_adc/deprecated/esp32s2/esp_adc_cal_legacy.c

@@ -6,16 +6,17 @@
 
 #include <stdint.h>
 #include "esp_types.h"
-#include "driver/adc.h"
 #include "soc/efuse_periph.h"
 #include "esp_err.h"
 #include "esp_check.h"
 #include "assert.h"
-#include "esp_adc_cal.h"
 #include "esp_efuse.h"
 #include "esp_efuse_table.h"
 #include "esp_efuse_rtc_table.h"
 #include "hal/adc_hal.h"
+#include "hal/adc_types.h"
+#include "driver/adc_types_legacy.h"
+#include "esp_adc_cal_types_legacy.h"
 
 const static char LOG_TAG[] = "adc_calib";
 

+ 4 - 3
components/esp_adc_cal/esp32s3/esp_adc_cal.c → components/esp_adc/deprecated/esp32s3/esp_adc_cal_legacy.c

@@ -11,11 +11,12 @@
 #include "esp_err.h"
 #include "esp_log.h"
 #include "esp_check.h"
-#include "driver/adc.h"
 #include "hal/adc_types.h"
 #include "esp_efuse_rtc_calib.h"
-#include "esp_adc_cal.h"
-#include "../esp_adc_cal_internal.h"
+#include "hal/adc_types.h"
+#include "driver/adc_types_legacy.h"
+#include "esp_adc_cal_types_legacy.h"
+#include "../esp_adc_cal_internal_legacy.h"
 
 const static char LOG_TAG[] = "ADC_CALI";
 

+ 9 - 2
components/esp_adc_cal/esp_adc_cal_common.c → components/esp_adc/deprecated/esp_adc_cal_common_legacy.c

@@ -6,14 +6,18 @@
 
 #include <stdint.h>
 #include <string.h>
+#include "sdkconfig.h"
+
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
 #include "esp_types.h"
 #include "esp_err.h"
 #include "esp_log.h"
 #include "esp_check.h"
-#include "driver/adc.h"
 #include "hal/adc_types.h"
+#define CONFIG_ADC_SUPPRESS_DEPRECATE_WARN 1
 #include "esp_adc_cal.h"
-#include "esp_adc_cal_internal.h"
+#include "esp_adc_cal_internal_legacy.h"
+#include "driver/adc.h"
 
 const __attribute__((unused)) static char *TAG = "ADC_CALI";
 
@@ -41,6 +45,7 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
     return ret;
 }
 
+
 #if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED
 /*------------------------------------------------------------------------------
  * Private API
@@ -86,3 +91,5 @@ int32_t esp_adc_cal_get_reading_error(const esp_adc_error_calc_param_t *param, u
     return error;
 }
 #endif  //#if ESP_ADC_CAL_CURVE_FITTING_SUPPORTED
+
+#endif  //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3

+ 0 - 0
components/esp_adc_cal/esp_adc_cal_internal.h → components/esp_adc/deprecated/esp_adc_cal_internal_legacy.h


+ 12 - 34
components/esp_adc_cal/include/esp_adc_cal.h → components/esp_adc/deprecated/include/esp_adc_cal.h

@@ -4,46 +4,24 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#ifndef __ESP_ADC_CAL_H__
-#define __ESP_ADC_CAL_H__
+#pragma once
 
 #include <stdint.h>
+#include "sdkconfig.h"
 #include "esp_err.h"
-#include "driver/adc.h"
+#include "hal/adc_types.h"
+#include "driver/adc_types_legacy.h"
+#include "esp_adc_cal_types_legacy.h"
+
+#if !CONFIG_ADC_SUPPRESS_DEPRECATE_WARN
+#warning "legacy adc calibration driver is deprecated, please migrate to use esp_adc/adc_cali.h and esp_adc/adc_cali_scheme.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/**
- * @brief Type of calibration value used in characterization
- */
-typedef enum {
-    ESP_ADC_CAL_VAL_EFUSE_VREF = 0,         /**< Characterization based on reference voltage stored in eFuse*/
-    ESP_ADC_CAL_VAL_EFUSE_TP = 1,           /**< Characterization based on Two Point values stored in eFuse*/
-    ESP_ADC_CAL_VAL_DEFAULT_VREF = 2,       /**< Characterization based on default reference voltage*/
-    ESP_ADC_CAL_VAL_EFUSE_TP_FIT = 3,       /**< Characterization based on Two Point values and fitting curve coefficients stored in eFuse */
-    ESP_ADC_CAL_VAL_MAX,
-    ESP_ADC_CAL_VAL_NOT_SUPPORTED = ESP_ADC_CAL_VAL_MAX,
-} esp_adc_cal_value_t;
-
-/**
- * @brief Structure storing characteristics of an ADC
- *
- * @note Call esp_adc_cal_characterize() to initialize the structure
- */
-typedef struct {
-    adc_unit_t adc_num;                     /**< ADC unit*/
-    adc_atten_t atten;                      /**< ADC attenuation*/
-    adc_bits_width_t bit_width;             /**< ADC bit width */
-    uint32_t coeff_a;                       /**< Gradient of ADC-Voltage curve*/
-    uint32_t coeff_b;                       /**< Offset of ADC-Voltage curve*/
-    uint32_t vref;                          /**< Vref used by lookup table*/
-    const uint32_t *low_curve;              /**< Pointer to low Vref curve of lookup table (NULL if unused)*/
-    const uint32_t *high_curve;             /**< Pointer to high Vref curve of lookup table (NULL if unused)*/
-    uint8_t version;                        /**< ADC Calibration */
-} esp_adc_cal_characteristics_t;
-
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
 /**
  * @brief Checks if ADC calibration values are burned into eFuse
  *
@@ -128,8 +106,8 @@ uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_char
  */
 esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, const esp_adc_cal_characteristics_t *chars, uint32_t *voltage);
 
+#endif  //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+
 #ifdef __cplusplus
 }
 #endif
-
-#endif /* __ESP_ADC_CAL_H__ */

+ 50 - 0
components/esp_adc/deprecated/include/esp_adc_cal_types_legacy.h

@@ -0,0 +1,50 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "sdkconfig.h"
+#include "driver/adc_types_legacy.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+/**
+ * @brief Type of calibration value used in characterization
+ */
+typedef enum {
+    ESP_ADC_CAL_VAL_EFUSE_VREF = 0,         /**< Characterization based on reference voltage stored in eFuse*/
+    ESP_ADC_CAL_VAL_EFUSE_TP = 1,           /**< Characterization based on Two Point values stored in eFuse*/
+    ESP_ADC_CAL_VAL_DEFAULT_VREF = 2,       /**< Characterization based on default reference voltage*/
+    ESP_ADC_CAL_VAL_EFUSE_TP_FIT = 3,       /**< Characterization based on Two Point values and fitting curve coefficients stored in eFuse */
+    ESP_ADC_CAL_VAL_MAX,
+    ESP_ADC_CAL_VAL_NOT_SUPPORTED = ESP_ADC_CAL_VAL_MAX,
+} esp_adc_cal_value_t;
+
+/**
+ * @brief Structure storing characteristics of an ADC
+ *
+ * @note Call esp_adc_cal_characterize() to initialize the structure
+ */
+typedef struct {
+    adc_unit_t adc_num;                     /**< ADC unit*/
+    adc_atten_t atten;                      /**< ADC attenuation*/
+    adc_bits_width_t bit_width;             /**< ADC bit width */
+    uint32_t coeff_a;                       /**< Gradient of ADC-Voltage curve*/
+    uint32_t coeff_b;                       /**< Offset of ADC-Voltage curve*/
+    uint32_t vref;                          /**< Vref used by lookup table*/
+    const uint32_t *low_curve;              /**< Pointer to low Vref curve of lookup table (NULL if unused)*/
+    const uint32_t *high_curve;             /**< Pointer to high Vref curve of lookup table (NULL if unused)*/
+    uint8_t version;                        /**< ADC Calibration */
+} esp_adc_cal_characteristics_t;
+#endif  //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+
+
+#ifdef __cplusplus
+}
+#endif

+ 435 - 0
components/esp_adc/esp32/adc_cali_line_fitting.c

@@ -0,0 +1,435 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "sdkconfig.h"
+#include "assert.h"
+#include "esp_types.h"
+#include "esp_err.h"
+#include "esp_check.h"
+#include "esp_heap_caps.h"
+#include "hal/adc_types.h"
+#include "hal/efuse_ll.h"
+#include "soc/soc_caps.h"
+#include "esp_adc/adc_cali_scheme.h"
+#include "adc_cali_interface.h"
+
+/* ----------------------------- Configuration ------------------------------ */
+#ifdef CONFIG_ADC_CALI_EFUSE_TP_ENABLE
+#define EFUSE_TP_ENABLED        1
+#else
+#define EFUSE_TP_ENABLED        0
+#endif
+
+#ifdef CONFIG_ADC_CALI_EFUSE_VREF_ENABLE
+#define EFUSE_VREF_ENABLED      1
+#else
+#define EFUSE_VREF_ENABLED      0
+#endif
+
+#ifdef CONFIG_ADC_CALI_LUT_ENABLE
+#define LUT_ENABLED             1
+#else
+#define LUT_ENABLED             0
+#endif
+
+/* ESP32s with both Two Point Values and Vref burned into eFuse are required to
+ * also burn the EFUSE_BLK3_PART_RESERVE flag. A limited set of ESP32s
+ * (not available through regular sales channel) DO NOT have the
+ * EFUSE_BLK3_PART_RESERVE burned. Moreover, this set of ESP32s represents Vref
+ * in Two's Complement format. If this is the case, modify the preprocessor
+ * definitions below as follows...
+ * #define CHECK_BLK3_FLAG         0        //Do not check BLK3 flag as it is not burned
+ * #define VREF_FORMAT             1        //eFuse Vref is in Two's Complement format
+ */
+#define CHECK_BLK3_FLAG         1
+#define VREF_FORMAT             0
+
+/* ------------------------------ eFuse Access ----------------------------- */
+#define VREF_MASK                       0x1F
+#define VREF_STEP_SIZE                  7
+#define VREF_OFFSET                     1100
+
+#define TP_LOW1_OFFSET                  278
+#define TP_LOW2_OFFSET                  421
+#define TP_LOW_MASK                     0x7F
+#define TP_LOW_VOLTAGE                  150
+#define TP_HIGH1_OFFSET                 3265
+#define TP_HIGH2_OFFSET                 3406
+#define TP_HIGH_MASK                    0x1FF
+#define TP_HIGH_VOLTAGE                 850
+#define TP_STEP_SIZE                    4
+
+/* ----------------------- Raw to Voltage Constants ------------------------- */
+#define LIN_COEFF_A_SCALE               65536
+#define LIN_COEFF_A_ROUND               (LIN_COEFF_A_SCALE/2)
+
+#define LUT_VREF_LOW                    1000
+#define LUT_VREF_HIGH                   1200
+#define LUT_ADC_STEP_SIZE               64
+#define LUT_POINTS                      20
+#define LUT_LOW_THRESH                  2880
+#define LUT_HIGH_THRESH                 (LUT_LOW_THRESH + LUT_ADC_STEP_SIZE)
+#define ADC_12_BIT_RES                  4096
+
+/* ------------------------ Characterization Constants ---------------------- */
+static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310};
+static const uint32_t adc2_tp_atten_scale[4] = {65467, 86861, 120416, 224708};
+static const uint32_t adc1_tp_atten_offset[4] = {0, 1, 27, 54};
+static const uint32_t adc2_tp_atten_offset[4] = {0, 9, 26, 66};
+
+static const uint32_t adc1_vref_atten_scale[4] = {57431, 76236, 105481, 196602};
+static const uint32_t adc2_vref_atten_scale[4] = {57236, 76175, 105678, 197170};
+static const uint32_t adc1_vref_atten_offset[4] = {75, 78, 107, 142};
+static const uint32_t adc2_vref_atten_offset[4] = {63, 66, 89, 128};
+
+//20 Point lookup tables, covering ADC readings from 2880 to 4096, step size of 64
+static const uint32_t lut_adc1_low[LUT_POINTS] = {2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709,
+                                                  2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060};
+static const uint32_t lut_adc1_high[LUT_POINTS] = {2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956,
+                                                   2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209};
+static const uint32_t lut_adc2_low[LUT_POINTS] = {2238, 2293, 2347, 2399, 2451, 2507, 2561, 2613, 2662, 2710,
+                                                  2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059};
+static const uint32_t lut_adc2_high[LUT_POINTS] = {2657, 2698, 2738, 2774, 2807, 2838, 2867, 2894, 2921, 2946,
+                                                   2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185};
+
+const __attribute__((unused)) static char *TAG = "adc_cali";
+
+
+/* ----------------------- EFuse Access Functions --------------------------- */
+static bool check_efuse_vref(void);
+static bool check_efuse_tp(void);
+static inline int decode_bits(uint32_t bits, uint32_t mask, bool is_twos_compl);
+static uint32_t read_efuse_vref(void);
+static uint32_t read_efuse_tp_low(adc_unit_t unit_id);
+static uint32_t read_efuse_tp_high(adc_unit_t unit_id);
+
+
+/* ----------------------- Characterization Functions ----------------------- */
+static void characterize_using_two_point(adc_unit_t unit_id,
+                                         adc_atten_t atten,
+                                         uint32_t high,
+                                         uint32_t low,
+                                         uint32_t *coeff_a,
+                                         uint32_t *coeff_b);
+static void characterize_using_vref(adc_unit_t unit_id,
+                                    adc_atten_t atten,
+                                    uint32_t vref,
+                                    uint32_t *coeff_a,
+                                    uint32_t *coeff_b);
+
+
+/* ------------------------ Conversion Functions --------------------------- */
+static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b);
+//Only call when ADC reading is above threshold
+static uint32_t calculate_voltage_lut(uint32_t adc, uint32_t vref, const uint32_t *low_vref_curve, const uint32_t *high_vref_curve);
+
+static inline uint32_t interpolate_two_points(uint32_t y1, uint32_t y2, uint32_t x_step, uint32_t x)
+{
+    //Interpolate between two points (x1,y1) (x2,y2) between 'lower' and 'upper' separated by 'step'
+    return ((y1 * x_step) + (y2 * x) - (y1 * x) + (x_step / 2)) / x_step;
+}
+
+
+/* ------------------------ Interface Functions --------------------------- */
+static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage);
+
+
+/* ------------------------ Context Structure--------------------------- */
+typedef struct {
+    adc_unit_t unit_id;                             ///< ADC unit
+    adc_atten_t atten;                              ///< ADC attenuation
+    adc_bitwidth_t bitwidth;                        ///< ADC bit width
+    uint32_t coeff_a;                               ///< Gradient of ADC-Voltage curve
+    uint32_t coeff_b;                               ///< Offset of ADC-Voltage curve
+    uint32_t vref;                                  ///< Vref used by lookup table
+    const uint32_t *low_curve;                      ///< Pointer to low Vref curve of lookup table (NULL if unused)
+    const uint32_t *high_curve;                     ///< Pointer to high Vref curve of lookup table (NULL if unused)
+    adc_cali_line_fitting_efuse_val_t efuse_val;    ///< Type of calibration value used in characterization
+} cali_chars_line_fitting_t;
+
+
+/* ------------------------- Public API ------------------------------------- */
+esp_err_t adc_cali_create_scheme_line_fitting(const adc_cali_line_fitting_config_t *config, adc_cali_handle_t *ret_handle)
+{
+    esp_err_t ret = ESP_OK;
+    ESP_RETURN_ON_FALSE(config && config, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+    ESP_RETURN_ON_FALSE(config->unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid ADC unit");
+    ESP_RETURN_ON_FALSE(config->atten < SOC_ADC_ATTEN_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid ADC attenuation");
+    ESP_RETURN_ON_FALSE(((config->bitwidth >= SOC_ADC_RTC_MIN_BITWIDTH && config->bitwidth <= SOC_ADC_RTC_MAX_BITWIDTH) || config->bitwidth == ADC_BITWIDTH_DEFAULT), ESP_ERR_INVALID_ARG, TAG, "invalid bitwidth");
+
+    adc_cali_scheme_t *scheme = (adc_cali_scheme_t *)heap_caps_calloc(1, sizeof(adc_cali_scheme_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    ESP_RETURN_ON_FALSE(scheme, ESP_ERR_NO_MEM, TAG, "no mem for adc calibration scheme");
+
+    cali_chars_line_fitting_t *chars = (cali_chars_line_fitting_t *)heap_caps_calloc(1, sizeof(cali_chars_line_fitting_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    ESP_GOTO_ON_FALSE(chars, ESP_ERR_NO_MEM, err, TAG, "no memory for the calibration characteristics");
+
+    //Check eFuse if enabled to do so
+    if (check_efuse_tp() && EFUSE_TP_ENABLED) {
+        //Characterize based on Two Point values
+        chars->efuse_val = ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP;
+        //Characterize based on Two Point values
+        uint32_t high = read_efuse_tp_high(config->unit_id);
+        uint32_t low = read_efuse_tp_low(config->unit_id);
+        characterize_using_two_point(config->unit_id, config->atten, high, low, &chars->coeff_a, &chars->coeff_b);
+    } else if (check_efuse_vref() && EFUSE_VREF_ENABLED) {
+        //Characterize based on eFuse Vref
+        chars->efuse_val = ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF;
+        chars->vref = read_efuse_vref();
+        characterize_using_vref(config->unit_id, config->atten, chars->vref, &chars->coeff_a, &chars->coeff_b);
+    } else {
+        //Characterized based on default Vref
+        chars->efuse_val = ADC_CALI_LINE_FITTING_EFUSE_VAL_DEFAULT_VREF;
+        ESP_GOTO_ON_FALSE(config->default_vref, ESP_ERR_INVALID_ARG, err, TAG, "default vref didn't set");
+        chars->vref = config->default_vref;
+        characterize_using_vref(config->unit_id, config->atten, chars->vref, &chars->coeff_a, &chars->coeff_b);
+    }
+
+    chars->unit_id = config->unit_id;
+    chars->atten = config->atten;
+    chars->bitwidth = (config->bitwidth == ADC_BITWIDTH_DEFAULT) ? ADC_BITWIDTH_12 : config->bitwidth;
+    //Initialize fields for lookup table if necessary
+    if (LUT_ENABLED && config->atten == ADC_ATTEN_DB_11) {
+        chars->low_curve = (config->unit_id == ADC_UNIT_1) ? lut_adc1_low : lut_adc2_low;
+        chars->high_curve = (config->unit_id == ADC_UNIT_1) ? lut_adc1_high : lut_adc2_high;
+    } else {
+        chars->low_curve = NULL;
+        chars->high_curve = NULL;
+    }
+    scheme->raw_to_voltage = cali_raw_to_voltage;
+    scheme->ctx = chars;
+    *ret_handle = scheme;
+
+    return ESP_OK;
+
+err:
+    if (scheme) {
+        free(scheme);
+    }
+    return ret;
+}
+
+esp_err_t adc_cali_scheme_line_fitting_check_efuse(adc_cali_line_fitting_efuse_val_t *cali_val)
+{
+    ESP_RETURN_ON_FALSE(cali_val, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+
+    if (check_efuse_tp()) {
+        *cali_val = ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP;
+    } else if (check_efuse_vref()) {
+        *cali_val = ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF;
+    } else {
+        *cali_val = ADC_CALI_LINE_FITTING_EFUSE_VAL_DEFAULT_VREF;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc_cali_delete_scheme_line_fitting(adc_cali_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+
+    free(handle->ctx);
+    handle->ctx = NULL;
+
+    free(handle);
+    handle = NULL;
+
+    return ESP_OK;
+}
+
+/* ------------------------ Interface Functions --------------------------- */
+static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage)
+{
+    //pointers are checked in the upper layer
+
+    cali_chars_line_fitting_t *ctx = arg;
+
+    //Scale adc_rading if not 12 bits wide
+    raw = (raw << (ADC_BITWIDTH_12 - ctx->bitwidth));
+    if (raw > ADC_12_BIT_RES - 1) {
+        raw = ADC_12_BIT_RES - 1;    //Set to 12bit res max
+    }
+
+    if (LUT_ENABLED && (ctx->atten == ADC_ATTEN_DB_11) && (raw >= LUT_LOW_THRESH)) {  //Check if in non-linear region
+        //Use lookup table to get voltage in non linear portion of ADC_ATTEN_DB_11
+        uint32_t lut_voltage = calculate_voltage_lut(raw, ctx->vref, ctx->low_curve, ctx->high_curve);
+        if (raw <= LUT_HIGH_THRESH) {   //If ADC is transitioning from linear region to non-linear region
+            //Linearly interpolate between linear voltage and lut voltage
+            uint32_t linear_voltage = calculate_voltage_linear(raw, ctx->coeff_a, ctx->coeff_b);
+            *voltage = interpolate_two_points(linear_voltage, lut_voltage, LUT_ADC_STEP_SIZE, (raw - LUT_LOW_THRESH));
+        } else {
+            *voltage = lut_voltage;
+        }
+    } else {
+        *voltage = calculate_voltage_linear(raw, ctx->coeff_a, ctx->coeff_b);
+    }
+
+    return ESP_OK;
+}
+
+/* ----------------------- EFuse Access Functions --------------------------- */
+static bool check_efuse_vref(void)
+{
+    //Check if Vref is burned in eFuse
+    return (efuse_ll_get_adc_vref() != 0) ? true : false;
+}
+
+static bool check_efuse_tp(void)
+{
+    //Check if Two Point values are burned in eFuse
+    if (CHECK_BLK3_FLAG && (efuse_ll_get_blk3_part_reserve() == 0)) {
+        return false;
+    }
+    //All TP cal values must be non zero
+    return efuse_ll_get_adc1_tp_low() &&
+           efuse_ll_get_adc2_tp_low() &&
+           efuse_ll_get_adc1_tp_high() &&
+           efuse_ll_get_adc2_tp_high();
+}
+
+static inline int decode_bits(uint32_t bits, uint32_t mask, bool is_twos_compl)
+{
+    int ret;
+    if (bits & (~(mask >> 1) & mask)) {      //Check sign bit (MSB of mask)
+        //Negative
+        if (is_twos_compl) {
+            ret = -(((~bits) + 1) & (mask >> 1));   //2's complement
+        } else {
+            ret = -(bits & (mask >> 1));    //Sign-magnitude
+        }
+    } else {
+        //Positive
+        ret = bits & (mask >> 1);
+    }
+    return ret;
+}
+
+static uint32_t read_efuse_vref(void)
+{
+    //eFuse stores deviation from ideal reference voltage
+    uint32_t ret = VREF_OFFSET;       //Ideal vref
+    uint32_t bits = efuse_ll_get_adc_vref();
+    ret += decode_bits(bits, VREF_MASK, VREF_FORMAT) * VREF_STEP_SIZE;
+    return ret;     //ADC Vref in mV
+}
+
+static uint32_t read_efuse_tp_low(adc_unit_t unit_id)
+{
+    //ADC reading at 150mV stored in two's complement format
+    uint32_t ret;
+    uint32_t bits;
+
+    if (unit_id == ADC_UNIT_1) {
+        ret = TP_LOW1_OFFSET;
+        bits = efuse_ll_get_adc1_tp_low();
+    } else {
+        ret = TP_LOW2_OFFSET;
+        bits = efuse_ll_get_adc2_tp_low();
+    }
+    ret += decode_bits(bits, TP_LOW_MASK, true) * TP_STEP_SIZE;
+    return ret;     //Reading of ADC at 150mV
+}
+
+static uint32_t read_efuse_tp_high(adc_unit_t unit_id)
+{
+    //ADC reading at 850mV stored in two's complement format
+    uint32_t ret;
+    uint32_t bits;
+
+    if (unit_id == ADC_UNIT_1) {
+        ret = TP_HIGH1_OFFSET;
+        bits = efuse_ll_get_adc1_tp_high();
+    } else {
+        ret = TP_HIGH2_OFFSET;
+        bits = efuse_ll_get_adc2_tp_high();
+    }
+    ret += decode_bits(bits, TP_HIGH_MASK, true) * TP_STEP_SIZE;
+    return ret;     //Reading of ADC at 850mV
+}
+
+
+/* ----------------------- Characterization Functions ----------------------- */
+static void characterize_using_two_point(adc_unit_t unit_id,
+                                         adc_atten_t atten,
+                                         uint32_t high,
+                                         uint32_t low,
+                                         uint32_t *coeff_a,
+                                         uint32_t *coeff_b)
+{
+    const uint32_t *atten_scales;
+    const uint32_t *atten_offsets;
+
+    if (unit_id == ADC_UNIT_1) { //Using ADC 1
+        atten_scales = adc1_tp_atten_scale;
+        atten_offsets = adc1_tp_atten_offset;
+    } else {    //Using ADC 2
+        atten_scales = adc2_tp_atten_scale;
+        atten_offsets = adc2_tp_atten_offset;
+    }
+    //Characterize ADC-Voltage curve as y = (coeff_a * x) + coeff_b
+    uint32_t delta_x = high - low;
+    uint32_t delta_v = TP_HIGH_VOLTAGE - TP_LOW_VOLTAGE;
+    //Where coeff_a = (delta_v/delta_x) * atten_scale
+    *coeff_a = (delta_v * atten_scales[atten] + (delta_x / 2)) / delta_x;   //+(delta_x/2) for rounding
+    //Where coeff_b = high_v - ((delta_v/delta_x) * high_x) + atten_offset
+    *coeff_b = TP_HIGH_VOLTAGE - ((delta_v * high + (delta_x / 2)) / delta_x) + atten_offsets[atten];
+}
+
+static void characterize_using_vref(adc_unit_t unit_id,
+                                    adc_atten_t atten,
+                                    uint32_t vref,
+                                    uint32_t *coeff_a,
+                                    uint32_t *coeff_b)
+{
+    const uint32_t *atten_scales;
+    const uint32_t *atten_offsets;
+
+    if (unit_id == ADC_UNIT_1) { //Using ADC 1
+        atten_scales = adc1_vref_atten_scale;
+        atten_offsets = adc1_vref_atten_offset;
+    } else {    //Using ADC 2
+        atten_scales = adc2_vref_atten_scale;
+        atten_offsets = adc2_vref_atten_offset;
+    }
+    //Characterize ADC-Voltage curve as y = (coeff_a * x) + coeff_b
+    //Where coeff_a = (vref/4096) * atten_scale
+    *coeff_a = (vref * atten_scales[atten]) / (ADC_12_BIT_RES);
+    *coeff_b = atten_offsets[atten];
+}
+
+
+/* ------------------------ Conversion Functions --------------------------- */
+static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b)
+{
+    //Where voltage = coeff_a * adc_reading + coeff_b
+    return (((coeff_a * adc_reading) + LIN_COEFF_A_ROUND) / LIN_COEFF_A_SCALE) + coeff_b;
+}
+
+//Only call when ADC reading is above threshold
+static uint32_t calculate_voltage_lut(uint32_t adc, uint32_t vref, const uint32_t *low_vref_curve, const uint32_t *high_vref_curve)
+{
+    //Get index of lower bound points of LUT
+    uint32_t i = (adc - LUT_LOW_THRESH) / LUT_ADC_STEP_SIZE;
+
+    //Let the X Axis be Vref, Y axis be ADC reading, and Z be voltage
+    int x2dist = LUT_VREF_HIGH - vref;                 //(x2 - x)
+    int x1dist = vref - LUT_VREF_LOW;                  //(x - x1)
+    int y2dist = ((i + 1) * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH - adc;  //(y2 - y)
+    int y1dist = adc - ((i * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH);        //(y - y1)
+
+    //For points for bilinear interpolation
+    int q11 = low_vref_curve[i];                    //Lower bound point of low_vref_curve
+    int q12 = low_vref_curve[i + 1];                //Upper bound point of low_vref_curve
+    int q21 = high_vref_curve[i];                   //Lower bound point of high_vref_curve
+    int q22 = high_vref_curve[i + 1];               //Upper bound point of high_vref_curve
+
+    //Bilinear interpolation
+    //Where z = 1/((x2-x1)*(y2-y1)) * ( (q11*x2dist*y2dist) + (q21*x1dist*y2dist) + (q12*x2dist*y1dist) + (q22*x1dist*y1dist) )
+    int voltage = (q11 * x2dist * y2dist) + (q21 * x1dist * y2dist) + (q12 * x2dist * y1dist) + (q22 * x1dist * y1dist);
+    voltage += ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE) / 2; //Integer division rounding
+    voltage /= ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE);    //Divide by ((x2-x1)*(y2-y1))
+    return (uint32_t)voltage;
+}

+ 15 - 0
components/esp_adc/esp32/include/adc_cali_schemes.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**
+ * @file adc_cali_schemes.h
+ *
+ * @brief Supported calibration schemes
+ */
+
+#define ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED    1

+ 15 - 0
components/esp_adc/esp32c2/include/adc_cali_schemes.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**
+ * @file adc_cali_schemes.h
+ *
+ * @brief Supported calibration schemes
+ */
+
+//No scheme supported

+ 11 - 5
components/driver/esp32c3/adc2_init_cal.c → components/esp_adc/esp32c3/adc2_init_cal.c

@@ -8,9 +8,13 @@
 The linker will link constructor (adc2_init_code_calibration) only when any sections inside the same file (adc2_cal_include) is used.
 Don't put any other code into this file. */
 
-#include "hal/adc_hal.h"
+#include "freertos/FreeRTOS.h"
+#include "hal/adc_types.h"
+#include "hal/adc_hal_common.h"
 #include "esp_private/adc2_wifi.h"
-#include "esp_private/adc_cali.h"
+#include "esp_private/adc_private.h"
+
+extern portMUX_TYPE rtc_spinlock;
 
 /**
  * @brief Set initial code to ADC2 after calibration. ADC2 RTC and ADC2 PWDET controller share the initial code.
@@ -18,9 +22,11 @@ Don't put any other code into this file. */
  */
 static __attribute__((constructor)) void adc2_init_code_calibration(void)
 {
-    const adc_unit_t adc_n = ADC_UNIT_2;
-    const adc_atten_t atten = ADC_ATTEN_DB_11;
-    adc_cal_offset(adc_n, atten);
+    adc_hal_calibration_init(ADC_UNIT_2);
+    adc_calc_hw_calibration_code(ADC_UNIT_2, ADC_ATTEN_DB_11);
+    portENTER_CRITICAL(&rtc_spinlock);
+    adc_set_hw_calibration_code(ADC_UNIT_2, ADC_ATTEN_DB_11);
+    portEXIT_CRITICAL(&rtc_spinlock);
 }
 
 /** Don't call `adc2_cal_include` in user code. */

+ 36 - 0
components/esp_adc/esp32c3/curve_fitting_coefficients.c

@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+
+/**
+ * @note Error Calculation
+ * Coefficients for calculating the reading voltage error.
+ * Four sets of coefficients for atten0 ~ atten3 respectively.
+ *
+ * For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient.
+ *
+ * @note {0,0} stands for unused item
+ * @note In case of the overflow, these coeffcients are recorded as Absolute Value
+ * @note For atten0 ~ 2, error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2); For atten3, error = (K0 * X^0) + (K1 * X^1)  + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
+ * @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered.
+ * @note ADC1 and ADC2 use same coeffients
+ */
+const uint64_t adc1_error_coef_atten[4][5][2] = {
+                                                {{225966470500043, 1e15}, {7265418501948, 1e16}, {109410402681, 1e16}, {0, 0}, {0, 0}},                         //atten0
+                                                {{4229623392600516, 1e16}, {731527490903, 1e16}, {88166562521, 1e16}, {0, 0}, {0, 0}},                          //atten1
+                                                {{1017859239236435, 1e15}, {97159265299153, 1e16}, {149794028038, 1e16}, {0, 0}, {0, 0}},                       //atten2
+                                                {{14912262772850453, 1e16}, {228549975564099, 1e16}, {356391935717, 1e16}, {179964582, 1e16}, {42046, 1e16}}    //atten3
+                                                };
+/**
+ * Term sign
+ */
+const int32_t adc1_error_sign[4][5] = {
+                                        {-1, -1, 1,  0,  0}, //atten0
+                                        { 1, -1, 1,  0,  0}, //atten1
+                                        {-1, -1, 1,  0,  0}, //atten2
+                                        {-1, -1, 1, -1,  1}  //atten3
+                                    };

+ 15 - 0
components/esp_adc/esp32c3/include/adc_cali_schemes.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**
+ * @file adc_cali_schemes.h
+ *
+ * @brief Supported calibration schemes
+ */
+
+#define ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED    1

+ 15 - 0
components/esp_adc/esp32h2/include/adc_cali_schemes.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**
+ * @file adc_cali_schemes.h
+ *
+ * @brief Supported calibration schemes
+ */
+
+//Now no scheme supported

+ 11 - 5
components/driver/esp32s2/adc2_init_cal.c → components/esp_adc/esp32s2/adc2_init_cal.c

@@ -8,9 +8,13 @@
 The linker will link constructor (adc2_init_code_calibration) only when any sections inside the same file (adc2_cal_include) is used.
 Don't put any other code into this file. */
 
-#include "hal/adc_hal.h"
+#include "freertos/FreeRTOS.h"
+#include "hal/adc_types.h"
+#include "hal/adc_hal_common.h"
 #include "esp_private/adc2_wifi.h"
-#include "esp_private/adc_cali.h"
+#include "esp_private/adc_private.h"
+
+extern portMUX_TYPE rtc_spinlock;
 
 /**
  * @brief Set initial code to ADC2 after calibration. ADC2 RTC and ADC2 PWDET controller share the initial code.
@@ -18,9 +22,11 @@ Don't put any other code into this file. */
  */
 static __attribute__((constructor)) void adc2_init_code_calibration(void)
 {
-    const adc_unit_t adc_n = ADC_UNIT_2;
-    const adc_atten_t atten = ADC_ATTEN_DB_11;
-    adc_cal_offset(adc_n, atten);
+    adc_hal_calibration_init(ADC_UNIT_2);
+    adc_calc_hw_calibration_code(ADC_UNIT_2, ADC_ATTEN_DB_11);
+    portENTER_CRITICAL(&rtc_spinlock);
+    adc_set_hw_calibration_code(ADC_UNIT_2, ADC_ATTEN_DB_11);
+    portEXIT_CRITICAL(&rtc_spinlock);
 }
 
 /** Don't call `adc2_cal_include` in user code. */

+ 255 - 0
components/esp_adc/esp32s2/adc_cali_line_fitting.c

@@ -0,0 +1,255 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "assert.h"
+#include "esp_types.h"
+#include "esp_err.h"
+#include "esp_check.h"
+#include "esp_heap_caps.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+#include "esp_efuse_rtc_table.h"
+#include "hal/adc_types.h"
+#include "soc/efuse_periph.h"
+#include "soc/soc_caps.h"
+#include "esp_adc/adc_cali_scheme.h"
+#include "adc_cali_interface.h"
+
+const __attribute__((unused)) static char *TAG = "adc_cali";
+
+/* ------------------------ Characterization Constants ---------------------- */
+// coeff_a and coeff_b are actually floats
+// they are scaled to put them into uint32_t so that the headers do not have to be changed
+static const int coeff_a_scaling = 65536;
+static const int coeff_b_scaling = 1024;
+
+
+/* -------------------- Characterization Helper Data Types ------------------ */
+typedef struct {
+    int adc_calib_high;
+    int adc_calib_low;
+} adc_calib_data_ver1_t;
+
+typedef struct {
+    int adc_calib_high;         // the reading of adc ...
+    int adc_calib_high_voltage; // ... at this voltage (mV)
+} adc_calib_data_ver2_t;
+
+typedef struct {
+    char version_num;
+    adc_unit_t unit_id;
+    adc_atten_t atten_level;
+    union {
+        adc_calib_data_ver1_t ver1;
+        adc_calib_data_ver2_t ver2;
+    } efuse_data;
+} adc_calib_parsed_info_t;
+
+
+/* ------------------------ Context Structure--------------------------- */
+typedef struct {
+    adc_unit_t unit_id;                     ///< ADC unit
+    adc_atten_t atten;                      ///< ADC attenuation
+    uint32_t coeff_a;                       ///< Gradient of ADC-Voltage curve
+    uint32_t coeff_b;                       ///< Offset of ADC-Voltage curve
+} cali_chars_line_fitting_t;
+
+
+/* ----------------------- Characterization Functions ----------------------- */
+static bool prepare_calib_data_for(adc_unit_t unit_id, adc_atten_t atten, adc_calib_parsed_info_t *parsed_data_storage);
+/**
+ *  (Used in V1 of calibration scheme)
+ *  The Two Point calibration measures the reading at two specific input voltages, and calculates the (assumed linear) relation
+ *  between input voltage and ADC response. (Response = A * Vinput + B)
+ *  A and B are scaled ints.
+ *  @param high The ADC response at the higher voltage of the corresponding attenuation (600mV, 800mV, 1000mV, 2000mV).
+ *  @param low The ADC response at the lower voltage of the corresponding attenuation (all 250mV).
+ *
+ */
+static void characterize_using_two_point(adc_unit_t unit_id,
+        adc_atten_t atten,
+        uint32_t high,
+        uint32_t low,
+        uint32_t *coeff_a,
+        uint32_t *coeff_b);
+/*
+ * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
+ * with the previously done measurement when the chip was manufactured.
+ * */
+static bool calculate_characterization_coefficients(const adc_calib_parsed_info_t *parsed_data, cali_chars_line_fitting_t *ctx);
+
+
+/* ------------------------ Interface Functions --------------------------- */
+static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage);
+
+
+/* ------------------------- Public API ------------------------------------- */
+esp_err_t adc_cali_create_scheme_line_fitting(const adc_cali_line_fitting_config_t *config, adc_cali_handle_t *ret_handle)
+{
+    esp_err_t ret = ESP_OK;
+    ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
+    ESP_RETURN_ON_FALSE(config->unit_id < SOC_ADC_PERIPH_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid ADC unit");
+    ESP_RETURN_ON_FALSE(config->atten < SOC_ADC_ATTEN_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid ADC attenuation");
+    //S2 Oneshot read only supports 13 bits, DMA read only supports 12 bits
+    ESP_RETURN_ON_FALSE(((config->bitwidth == SOC_ADC_RTC_MAX_BITWIDTH || config->bitwidth == SOC_ADC_DIGI_MAX_BITWIDTH) || config->bitwidth == ADC_BITWIDTH_DEFAULT), ESP_ERR_INVALID_ARG, TAG, "invalid bitwidth");
+    // current version only accepts encoding ver 1 and ver 2.
+    uint8_t adc_encoding_version = esp_efuse_rtc_table_read_calib_version();
+    ESP_RETURN_ON_FALSE(((adc_encoding_version == 1) || (adc_encoding_version == 2)), ESP_ERR_NOT_SUPPORTED, TAG, "Calibration required eFuse bits not burnt");
+
+    adc_cali_scheme_t *scheme = (adc_cali_scheme_t *)heap_caps_calloc(1, sizeof(adc_cali_scheme_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    ESP_RETURN_ON_FALSE(scheme, ESP_ERR_NO_MEM, TAG, "no mem for adc calibration scheme");
+
+    cali_chars_line_fitting_t *chars = (cali_chars_line_fitting_t *)heap_caps_calloc(1, sizeof(cali_chars_line_fitting_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+    ESP_GOTO_ON_FALSE(chars, ESP_ERR_NO_MEM, err, TAG, "no memory for the calibration characteristics");
+
+    scheme->raw_to_voltage = cali_raw_to_voltage;
+    scheme->ctx = chars;
+
+    adc_calib_parsed_info_t efuse_parsed_data = {0};
+    bool success = prepare_calib_data_for(config->unit_id, config->atten, &efuse_parsed_data);
+    assert(success);
+    success = calculate_characterization_coefficients(&efuse_parsed_data, chars);
+    assert(success);
+    ESP_LOGD(TAG, "adc%d (atten leven %d) calibration done: A:%d B:%d\n", config->unit_id, config->atten, chars->coeff_a, chars->coeff_b);
+    chars->unit_id = config->unit_id;
+    chars->atten = config->atten;
+
+    *ret_handle = scheme;
+
+    return ESP_OK;
+
+err:
+    if (scheme) {
+        free(scheme);
+    }
+    return ret;
+}
+
+esp_err_t adc_cali_delete_scheme_line_fitting(adc_cali_handle_t handle)
+{
+    ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
+
+    free(handle->ctx);
+    handle->ctx = NULL;
+
+    free(handle);
+    handle = NULL;
+
+    return ESP_OK;
+}
+
+
+/* ------------------------ Interface Functions --------------------------- */
+static esp_err_t cali_raw_to_voltage(void *arg, int raw, int *voltage)
+{
+    //pointers are checked in the upper layer
+
+    cali_chars_line_fitting_t *ctx = arg;
+    *voltage = raw * ctx->coeff_a / coeff_a_scaling + ctx->coeff_b / coeff_b_scaling;
+
+    return ESP_OK;
+}
+
+
+/* ----------------------- Characterization Functions ----------------------- */
+static bool prepare_calib_data_for(adc_unit_t unit_id, adc_atten_t atten, adc_calib_parsed_info_t *parsed_data_storage)
+{
+    int version_num = esp_efuse_rtc_table_read_calib_version();
+    int tag;
+    parsed_data_storage->version_num = version_num;
+    parsed_data_storage->unit_id = unit_id;
+    parsed_data_storage->atten_level = atten;
+    switch (version_num) {
+    case 1:
+        // note: use the unit_id as in hal, which start from 0.
+        tag = esp_efuse_rtc_table_get_tag(version_num, unit_id, atten, RTCCALIB_V1_PARAM_VLOW);
+        parsed_data_storage->efuse_data.ver1.adc_calib_low = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
+        tag = esp_efuse_rtc_table_get_tag(version_num, unit_id, atten, RTCCALIB_V1_PARAM_VHIGH);
+        parsed_data_storage->efuse_data.ver1.adc_calib_high = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
+        break;
+    case 2:
+        tag = esp_efuse_rtc_table_get_tag(version_num, unit_id, atten, RTCCALIB_V2_PARAM_VHIGH);
+        parsed_data_storage->efuse_data.ver2.adc_calib_high = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
+        switch (parsed_data_storage->atten_level) {
+        case ADC_ATTEN_DB_0:
+            parsed_data_storage->efuse_data.ver2.adc_calib_high_voltage = 600;
+            break;
+        case ADC_ATTEN_DB_2_5:
+            parsed_data_storage->efuse_data.ver2.adc_calib_high_voltage = 800;
+            break;
+        case ADC_ATTEN_DB_6:
+            parsed_data_storage->efuse_data.ver2.adc_calib_high_voltage = 1000;
+            break;
+        case ADC_ATTEN_DB_11:
+            parsed_data_storage->efuse_data.ver2.adc_calib_high_voltage = 2000;
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        // fall back to case 1 with zeros as params.
+        parsed_data_storage->version_num = 1;
+        tag = esp_efuse_rtc_table_get_tag(version_num, unit_id, atten, RTCCALIB_V1_PARAM_VLOW);
+        parsed_data_storage->efuse_data.ver1.adc_calib_high = esp_efuse_rtc_table_get_parsed_efuse_value(tag, true);
+        tag = esp_efuse_rtc_table_get_tag(version_num, unit_id, atten, RTCCALIB_V1_PARAM_VHIGH);
+        parsed_data_storage->efuse_data.ver1.adc_calib_low = esp_efuse_rtc_table_get_parsed_efuse_value(tag, true);
+        break;
+    }
+    return true;
+}
+
+/**
+ *  (Used in V1 of calibration scheme)
+ *  The Two Point calibration measures the reading at two specific input voltages, and calculates the (assumed linear) relation
+ *  between input voltage and ADC response. (Response = A * Vinput + B)
+ *  A and B are scaled ints.
+ *  @param high The ADC response at the higher voltage of the corresponding attenuation (600mV, 800mV, 1000mV, 2000mV).
+ *  @param low The ADC response at the lower voltage of the corresponding attenuation (all 250mV).
+ *
+ */
+static void characterize_using_two_point(adc_unit_t unit_id,
+        adc_atten_t atten,
+        uint32_t high,
+        uint32_t low,
+        uint32_t *coeff_a,
+        uint32_t *coeff_b)
+{
+    // once we have recovered the reference high(Dhigh) and low(Dlow) readings, we can calculate a and b from
+    // the measured high and low readings
+    static const uint32_t v_high[] = {600, 800, 1000, 2000};
+    static const uint32_t v_low = 250;
+    *coeff_a = coeff_a_scaling * (v_high[atten] - v_low) / (high - low);
+    *coeff_b = coeff_b_scaling * (v_low * high - v_high[atten] * low) / (high - low);
+}
+
+/*
+ * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
+ * with the previously done measurement when the chip was manufactured.
+ * */
+static bool calculate_characterization_coefficients(const adc_calib_parsed_info_t *parsed_data, cali_chars_line_fitting_t *ctx)
+{
+    switch (parsed_data->version_num) {
+    case 1:
+        ESP_LOGD(TAG, "Calib V1, low%dmV, high%dmV\n", parsed_data->efuse_data.ver1.adc_calib_low, parsed_data->efuse_data.ver1.adc_calib_high);
+
+        characterize_using_two_point(parsed_data->unit_id, parsed_data->atten_level,
+                                     parsed_data->efuse_data.ver1.adc_calib_high, parsed_data->efuse_data.ver1.adc_calib_low,
+                                     &(ctx->coeff_a), &(ctx->coeff_b));
+        break;
+    case 2:
+        ESP_LOGD(TAG, "Calib V2, volt%dmV\n", parsed_data->efuse_data.ver2.adc_calib_high);
+        ctx->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver2.adc_calib_high_voltage /
+                         parsed_data->efuse_data.ver2.adc_calib_high;
+        ctx->coeff_b = 0;
+        break;
+    default:
+        return false;
+        break;
+    }
+    return true;
+}

+ 15 - 0
components/esp_adc/esp32s2/include/adc_cali_schemes.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**
+ * @file adc_cali_schemes.h
+ *
+ * @brief Supported calibration schemes
+ */
+
+#define ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED    1

+ 48 - 0
components/esp_adc/esp32s3/curve_fitting_coefficients.c

@@ -0,0 +1,48 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+
+
+/**
+ * @note Error Calculation
+ * Coefficients for calculating the reading voltage error.
+ * Four sets of coefficients for atten0 ~ atten3 respectively.
+ *
+ * For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient.
+ *
+ * @note {0,0} stands for unused item
+ * @note In case of the overflow, these coeffcients are recorded as Absolute Value
+ * @note For atten0 ~ 2, error = (K0 * X^0) + (K1 * X^1) + (K2 * X^2); For atten3, error = (K0 * X^0) + (K1 * X^1)  + (K2 * X^2) + (K3 * X^3) + (K4 * X^4);
+ * @note Above formula is rewritten from the original documentation, please note that the coefficients are re-ordered.
+ */
+const uint64_t adc1_error_coef_atten[4][5][2] = {
+                                                    {{27856531419538344, 1e16}, {50871540569528, 1e16}, {9798249589, 1e15}, {0, 0}, {0, 0}},                       //ADC1 atten0
+                                                    {{29831022915028695, 1e16}, {49393185868806, 1e16}, {101379430548, 1e16}, {0, 0}, {0, 0}},                     //ADC1 atten1
+                                                    {{23285545746296417, 1e16}, {147640181047414, 1e16}, {208385525314, 1e16}, {0, 0}, {0, 0}},                    //ADC1 atten2
+                                                    {{644403418269478, 1e15}, {644334888647536, 1e16}, {1297891447611, 1e16}, {70769718, 1e15}, {13515, 1e15}}     //ADC1 atten3
+                                                };
+const uint64_t adc2_error_coef_atten[4][5][2] = {
+                                                    {{25668651654328927, 1e16}, {1353548869615, 1e16}, {36615265189, 1e16}, {0, 0}, {0, 0}},                       //ADC2 atten0
+                                                    {{23690184690298404, 1e16}, {66319894226185, 1e16}, {118964995959, 1e16}, {0, 0}, {0, 0}},                     //ADC2 atten1
+                                                    {{9452499397020617, 1e16}, {200996773954387, 1e16}, {259011467956, 1e16}, {0, 0}, {0, 0}},                     //ADC2 atten2
+                                                    {{12247719764336924,1e16}, {755717904943462, 1e16}, {1478791187119, 1e16}, {79672528, 1e15}, {15038, 1e15}}    //ADC2 atten3
+                                                };
+/**
+ * Term sign
+ */
+const int32_t adc1_error_sign[4][5] = {
+                                        {-1, -1, 1, 0,  0},  //ADC1 atten0
+                                        {-1, -1, 1, 0,  0},  //ADC1 atten1
+                                        {-1, -1, 1, 0,  0},  //ADC1 atten2
+                                        {-1, -1, 1, -1, 1}   //ADC1 atten3
+                                    };
+const int32_t adc2_error_sign[4][5] = {
+                                        {-1,  1, 1,  0, 0},  //ADC2 atten0
+                                        {-1, -1, 1,  0, 0},  //ADC2 atten1
+                                        {-1, -1, 1,  0, 0},  //ADC2 atten2
+                                        { 1, -1, 1, -1, 1}   //ADC2 atten3
+                                    };

+ 15 - 0
components/esp_adc/esp32s3/include/adc_cali_schemes.h

@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+/**
+ * @file adc_cali_schemes.h
+ *
+ * @brief Supported calibration schemes
+ */
+
+#define ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED    1

+ 59 - 0
components/esp_adc/include/esp_adc/adc_cali.h

@@ -0,0 +1,59 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "esp_err.h"
+#include "esp_bit_defs.h"
+#include "hal/adc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief ADC calibration handle
+ */
+typedef struct adc_cali_scheme_t *adc_cali_handle_t;
+
+/**
+ * @brief ADC calibration scheme
+ */
+typedef enum {
+    ADC_CALI_SCHEME_VER_LINE_FITTING  = BIT(0),      ///< Line fitting scheme
+    ADC_CALI_SCHEME_VER_CURVE_FITTING = BIT(1),      ///< Curve fitting scheme
+} adc_cali_scheme_ver_t;
+
+/**
+ * @brief Check the supported ADC calibration scheme
+ *
+ * @param[out] scheme_mask    Supported ADC calibration scheme(s)
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid argument
+ *        - ESP_ERR_NOT_SUPPORTED: No supported calibration scheme
+ */
+esp_err_t adc_cali_check_scheme(adc_cali_scheme_ver_t *scheme_mask);
+
+/**
+ * @brief Convert ADC raw data to calibrated voltage
+ *
+ * @param[in]  handle     ADC calibration handle
+ * @param[in]  raw        ADC raw data
+ * @param[out] voltage    Calibrated ADC voltage (in mV)
+ *
+ * @return
+ *         - ESP_OK:                On success
+ *         - ESP_ERR_INVALID_ARG:   Invalid argument
+ *         - ESP_ERR_INVALID_STATE: Invalid state, scheme didn't registered
+ */
+esp_err_t adc_cali_raw_to_voltage(adc_cali_handle_t handle, int raw, int *voltage);
+
+
+#ifdef __cplusplus
+}
+#endif

+ 135 - 0
components/esp_adc/include/esp_adc/adc_cali_scheme.h

@@ -0,0 +1,135 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include "sdkconfig.h"
+#include "esp_adc/adc_cali.h"
+#include "adc_cali_schemes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
+/*---------------------------------------------------------------
+            Curve Fitting Calibration Scheme
+---------------------------------------------------------------*/
+typedef struct {
+    adc_unit_t unit_id;         ///< ADC unit
+    adc_atten_t atten;          ///< ADC attenuation
+    adc_bitwidth_t bitwidth;    ///< ADC raw output bitwidth
+} adc_cali_curve_fitting_config_t;
+
+/**
+ * @brief Create a Curve Fitting calibration scheme
+ *
+ * After creating, you'll get a handle to this scheme. Then you can use the driver APIS in `esp_adc/adc_cali.h` to do the
+ * ADC calibration via the handle you get.
+ *
+ * @param[in]  config  Initial configurations
+ * @param[out] handle  ADC calibration handle
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid argument
+ *        - ESP_ERR_NO_MEM:        No enough memory
+ *        - ESP_ERR_NOT_SUPPORTED: Scheme required eFuse bits not burnt
+ */
+esp_err_t adc_cali_create_scheme_curve_fitting(const adc_cali_curve_fitting_config_t *config, adc_cali_handle_t *ret_handle);
+
+/**
+ * @brief Delete the Curve Fitting calibration scheme handle
+ *
+ * @param[in] handle ADC calibration handle
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid argument
+ */
+esp_err_t adc_cali_delete_scheme_curve_fitting(adc_cali_handle_t handle);
+#endif  //  #if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
+
+
+#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
+/*---------------------------------------------------------------
+            Line Fitting Calibration Scheme
+---------------------------------------------------------------*/
+/**
+ * @brief Type of calibration value used in line fitting scheme characterization
+ */
+typedef enum {
+    ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF = 0,        ///< Characterization based on reference voltage stored in eFuse
+    ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP = 1,          ///< Characterization based on Two Point values stored in eFuse
+    ADC_CALI_LINE_FITTING_EFUSE_VAL_DEFAULT_VREF = 2,      ///< Characterization based on default reference voltage
+} adc_cali_line_fitting_efuse_val_t;
+
+typedef struct {
+    adc_unit_t unit_id;         ///< ADC unit
+    adc_atten_t atten;          ///< ADC attenuation
+    adc_bitwidth_t bitwidth;    ///< ADC raw output bitwidth
+#if CONFIG_IDF_TARGET_ESP32
+    /**
+     * @brief Default ADC reference voltage in mV.
+     *
+     * Use this when the ADC calibration value is `ADC_CALI_LINE_FITTING_EFUSE_VAL_DEFAULT_VREF`.
+     * If others, driver will use the calibration code burnt in the eFuse for calibration.
+     */
+    uint32_t default_vref;
+#endif
+} adc_cali_line_fitting_config_t;
+
+/**
+ * @brief Create a Line Fitting calibration scheme
+ *
+ * After creating, you'll get a handle to this scheme. Then you can use the driver APIS in `esp_adc/adc_cali.h` to do the
+ * ADC calibration via the handle you get.
+ *
+ * @param[in]  config  Initial configurations
+ * @param[out] handle  ADC calibration handle
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid argument
+ *        - ESP_ERR_NO_MEM:        No enough memory
+ *        - ESP_ERR_NOT_SUPPORTED: Scheme required eFuse bits not burnt
+ */
+esp_err_t adc_cali_create_scheme_line_fitting(const adc_cali_line_fitting_config_t *config, adc_cali_handle_t *ret_handle);
+
+/**
+ * @brief Delete the Line Fitting calibration scheme handle
+ *
+ * @param[in] handle ADC calibration handle
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid argument
+ */
+esp_err_t adc_cali_delete_scheme_line_fitting(adc_cali_handle_t handle);
+
+#if CONFIG_IDF_TARGET_ESP32
+/**
+ * @brief Helper function to quickly check the ADC calibration code burnt on your eFuse
+ *
+ * @note If `cali_val` equals to `ESP_ADC_CALI_VAL_DEFAULT_VREF`, please set the `default_vref`
+ *       when creating this scheme (See `ESP_ADC_CALI_SCHEME_VER_LINE_FITTING_init_t`)
+ *
+ * @param[out] cali_val See `esp_adc_cali_value_t`
+ *
+ * @return
+ *         - ESP_OK:                On success
+ *         - ESP_ERR_INVALID_ARG:   Invalid argument
+ *         - ESP_ERR_NOT_SUPPORTED: Scheme required eFuse bits not burnt
+ */
+esp_err_t adc_cali_scheme_line_fitting_check_efuse(adc_cali_line_fitting_efuse_val_t *cali_val);
+#endif  // CONFIG_IDF_TARGET_ESP32
+#endif //  #if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
+
+#ifdef __cplusplus
+}
+#endif

+ 232 - 0
components/esp_adc/include/esp_adc/adc_continuous.h

@@ -0,0 +1,232 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+#include "sdkconfig.h"
+#include "hal/adc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if SOC_ADC_DMA_SUPPORTED
+
+/**
+ * @brief Driver Backgrounds
+ *
+ * --------------------------------------------------------------------------------------------------------
+ * |                              Conversion Frame                                                        |
+ * --------------------------------------------------------------------------------------------------------
+ * | Conversion Result | Conversion Result | Conversion Result | Conversion Result |  ...                 |
+ * --------------------------------------------------------------------------------------------------------
+ *
+ * ADC continuous mode conversion is made up with multiple Conversion Frames.
+ * - Conversion Frame:      One Conversion Frame contains multiple Conversion Results.
+ *                          Conversion Frame size is configured in `adc_continuous_handle_cfg_t:conv_frame_size`, in bytes.
+ *                          Each time driver see an interrupt event, this means one Conversion Frame is generated by the hardware.
+ * - Conversion Result:     One Conversion Result contains multiple bytes (see `SOC_ADC_DIGI_RESULT_BYTES`). Its
+ *                          structure is `adc_digi_output_data_t`, including ADC Unit, ADC Channel and Raw Data.
+ *
+ * For example:
+ * conv_frame_size = 100,
+ * then one Conversion Frame contains (100 / `SOC_ADC_DIGI_RESULT_BYTES`) pieces of Conversion Results
+ */
+
+/**
+ * @brief ADC read max timeout value, it may make the ``adc_continuous_read`` block forever if the OS supports
+ */
+#define ADC_MAX_DELAY UINT32_MAX
+
+/**
+ * @brief Type of adc continuous mode driver handle
+ */
+typedef struct adc_continuous_ctx_t *adc_continuous_handle_t;
+
+/**
+ * @brief ADC continuous mode driver initial configurations
+ */
+typedef struct {
+    uint32_t max_store_buf_size;    ///< Max length of the conversion Results that driver can store, in bytes.
+    uint32_t conv_frame_size;       ///< Conversion frame size, in bytes. This should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`.
+} adc_continuous_handle_cfg_t;
+
+/**
+ * @brief ADC continuous mode driver configurations
+ */
+typedef struct {
+    uint32_t pattern_num;                   ///< Number of ADC channels that will be used
+    adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used
+    uint32_t sample_freq_hz;                /*!< The expected ADC sampling frequency in Hz. Please refer to `soc/soc_caps.h` to know available sampling frequency range*/
+    adc_digi_convert_mode_t conv_mode;      ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
+    adc_digi_output_format_t format;        ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
+} adc_continuous_config_t;
+
+/**
+ * @brief Event data structure
+ * @note The `conv_frame_buffer` is maintained by the driver itself, so never free this piece of memory.
+ */
+typedef struct {
+    uint8_t *conv_frame_buffer;             ///< Pointer to conversion result buffer for one conversion frame
+    uint32_t size;                          ///< Conversion frame size
+} adc_continuous_evt_data_t;
+
+/**
+ * @brief Prototype of ADC continuous mode event callback
+ *
+ * @param[in] handle    ADC continuous mode driver handle
+ * @param[in] edata     Pointer to ADC contunuous mode event data
+ * @param[in] user_data User registered context, registered when in `adc_continuous_register_event_callbacks()`
+ *
+ * @return Whether a high priority task is woken up by this function
+ */
+typedef bool (*adc_continuous_callback_t)(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data);
+
+/**
+ * @brief Group of ADC continuous mode callbacks
+ *
+ * @note These callbacks are all running in an ISR environment.
+ * @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
+ *       Involved variables should be in internal RAM as well.
+ */
+typedef struct {
+    adc_continuous_callback_t on_conv_done;    ///< Event callback, invoked when one conversion frame is done. See `@brief Driver Backgrounds` to konw `conversion frame` concept.
+    adc_continuous_callback_t on_pool_ovf;     ///< Event callback, invoked when the internal pool is full.
+} adc_continuous_evt_cbs_t;
+
+/**
+ * @brief Initialize ADC continuous driver and get a handle to it
+ *
+ * @param[in]  hdl_config  Pointer to ADC initilization config. Refer to ``adc_continuous_handle_cfg_t``.
+ * @param[out] ret_handle  ADC continuous mode driver handle
+ *
+ * @return
+ *         - ESP_ERR_INVALID_ARG   If the combination of arguments is invalid.
+ *         - ESP_ERR_NOT_FOUND     No free interrupt found with the specified flags
+ *         - ESP_ERR_NO_MEM        If out of memory
+ *         - ESP_OK                On success
+ */
+esp_err_t adc_continuous_new_handle(const adc_continuous_handle_cfg_t *hdl_config, adc_continuous_handle_t *ret_handle);
+
+/**
+ * @brief Set ADC continuous mode required configurations
+ *
+ * @param[in] handle ADC continuous mode driver handle
+ * @param[in] config Refer to ``adc_digi_config_t``.
+ *
+ * @return
+ *      - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
+ *      - ESP_ERR_INVALID_ARG:   If the combination of arguments is invalid.
+ *      - ESP_OK:                On success
+ */
+esp_err_t adc_continuous_config(adc_continuous_handle_t handle, const adc_continuous_config_t *config);
+
+/**
+ * @brief Register callbacks
+ *
+ * @note User can deregister a previously registered callback by calling this function and setting the to-be-deregistered callback member int
+ *       the `cbs` structure to NULL.
+ * @note When CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM.
+ *       Involved variables (including `user_data`) should be in internal RAM as well.
+ * @note You should only call this API when the ADC continuous mode driver isn't started. Check return value to know this.
+ *
+ * @param[in] handle    ADC continuous mode driver handle
+ * @param[in] cbs       Group of callback functions
+ * @param[in] user_data User data, which will be delivered to the callback functions directly
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid arguments
+ *        - ESP_ERR_INVALID_STATE: Driver state is invalid, you shouldn't call this API at this moment
+ */
+esp_err_t adc_continuous_register_event_callbacks(adc_continuous_handle_t handle, const adc_continuous_evt_cbs_t *cbs, void *user_data);
+
+/**
+ * @brief Start the ADC under continuous mode. After this, the hardware starts working.
+ *
+ * @param[in]  handle              ADC continuous mode driver handle
+ *
+ * @return
+ *         - ESP_ERR_INVALID_STATE Driver state is invalid.
+ *         - ESP_OK                On success
+ */
+esp_err_t adc_continuous_start(adc_continuous_handle_t handle);
+
+/**
+ * @brief Read bytes from ADC under continuous mode.
+ *
+ * @param[in]  handle              ADC continuous mode driver handle
+ * @param[out] buf                 Conversion result buffer to read from ADC. Suggest convert to `adc_digi_output_data_t` for `ADC Conversion Results`.
+ *                                 See `@brief Driver Backgrounds` to know this concept.
+ * @param[in]  length_max          Expected length of the Conversion Results read from the ADC, in bytes.
+ * @param[out] out_length          Real length of the Conversion Results read from the ADC via this API, in bytes.
+ * @param[in]  timeout_ms          Time to wait for data via this API, in millisecond.
+ *
+ * @return
+ *         - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate.
+ *         - ESP_ERR_TIMEOUT       Operation timed out
+ *         - ESP_OK                On success
+ */
+esp_err_t adc_continuous_read(adc_continuous_handle_t handle, uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms);
+
+/**
+ * @brief Stop the ADC. After this, the hardware stops working.
+ *
+ * @param[in]  handle              ADC continuous mode driver handle
+ *
+ * @return
+ *         - ESP_ERR_INVALID_STATE Driver state is invalid.
+ *         - ESP_OK                On success
+ */
+esp_err_t adc_continuous_stop(adc_continuous_handle_t handle);
+
+/**
+ * @brief Deinitialize the ADC continuous driver.
+ *
+ * @param[in]  handle              ADC continuous mode driver handle
+ *
+ * @return
+ *         - ESP_ERR_INVALID_STATE Driver state is invalid.
+ *         - ESP_OK                On success
+ */
+esp_err_t adc_continuous_deinit(adc_continuous_handle_t handle);
+
+/**
+ * @brief Get ADC channel from the given GPIO number
+ *
+ * @param[in]  io_num     GPIO number
+ * @param[out] unit_id    ADC unit
+ * @param[out] channel    ADC channel
+ *
+ * @return
+ *        - ESP_OK:              On success
+ *        - ESP_ERR_INVALID_ARG: Invalid argument
+ *        - ESP_ERR_NOT_FOUND:   The IO is not a valid ADC pad
+ */
+esp_err_t adc_continuous_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel);
+
+/**
+ * @brief Get GPIO number from the given ADC channel
+ *
+ * @param[in]  unit_id    ADC unit
+ * @param[in]  channel    ADC channel
+ * @param[out] io_num     GPIO number
+ *
+ * @param
+ *       - ESP_OK:              On success
+ *       - ESP_ERR_INVALID_ARG: Invalid argument
+ */
+esp_err_t adc_continuous_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num);
+
+#endif  //  #if SOC_ADC_DMA_SUPPORTED
+
+
+#ifdef __cplusplus
+}
+#endif

+ 130 - 0
components/esp_adc/include/esp_adc/adc_oneshot.h

@@ -0,0 +1,130 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+#include "hal/adc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Type of ADC unit handle for oneshot mode
+ */
+typedef struct adc_oneshot_unit_ctx_t *adc_oneshot_unit_handle_t;
+
+/**
+ * @brief ADC oneshot driver initial configurations
+ */
+typedef struct {
+    adc_unit_t unit_id;             ///< ADC unit
+    adc_ulp_mode_t ulp_mode;        ///< ADC controlled by ULP, see `adc_ulp_mode_t`
+} adc_oneshot_unit_init_cfg_t;
+
+/**
+ * @brief ADC channel configurations
+ */
+typedef struct {
+    adc_atten_t atten;              ///< ADC attenuation
+    adc_bitwidth_t bitwidth;        ///< ADC conversion result bits
+} adc_oneshot_chan_cfg_t;
+
+/**
+ * @brief Create a handle to a specific ADC unit
+ *
+ * @note This API is thread-safe. For more details, see ADC programming guide
+ *
+ * @param[in]  init_config    Driver initial configurations
+ * @param[out] ret_unit       ADC unit handle
+ *
+ * @return
+ *        - ESP_OK:              On success
+ *        - ESP_ERR_INVALID_ARG: Invalid arguments
+ *        - ESP_ERR_NO_MEM:      No memory
+ *        - ESP_ERR_NOT_FOUND:   The ADC peripheral to be claimed is already in use
+ */
+esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, adc_oneshot_unit_handle_t *ret_unit);
+
+/**
+ * @brief Set ADC oneshot mode required configurations
+ *
+ * @note This API is thread-safe. For more details, see ADC programming guide
+ *
+ * @param[in] handle    ADC handle
+ * @param[in] channel   ADC channel to be configured
+ * @param[in] config    ADC configurations
+ *
+ * @return
+ *        - ESP_OK:              On success
+ *        - ESP_ERR_INVALID_ARG: Invalid arguments
+ */
+esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, adc_channel_t channel, const adc_oneshot_chan_cfg_t *config);
+
+/**
+ * @brief Get one ADC conversion raw result
+ *
+ * @note This API is thread-safe. For more details, see ADC programming guide
+ * @note This API should NOT be called in an ISR context
+ *
+ * @param[in] handle    ADC handle
+ * @param[in] chan      ADC channel
+ * @param[out] out_raw  ADC conversion raw result
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid arguments
+ *        - ESP_ERR_TIMEOUT:       Timeout, the ADC result is invalid
+ */
+esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw);
+
+/**
+ * @brief Delete the ADC unit handle
+ *
+ * @note This API is thread-safe. For more details, see ADC programming guide
+ *
+ * @param[in] handle    ADC handle
+ *
+ * @return
+ *        - ESP_OK:              On success
+ *        - ESP_ERR_INVALID_ARG: Invalid arguments
+ *        - ESP_ERR_NOT_FOUND:   The ADC peripheral to be disclaimed isn't in use
+ */
+esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle);
+
+/**
+ * @brief Get ADC channel from the given GPIO number
+ *
+ * @param[in]  io_num     GPIO number
+ * @param[out] unit_id    ADC unit
+ * @param[out] channel    ADC channel
+ *
+ * @return
+ *        - ESP_OK:              On success
+ *        - ESP_ERR_INVALID_ARG: Invalid argument
+ *        - ESP_ERR_NOT_FOUND:   The IO is not a valid ADC pad
+ */
+esp_err_t adc_oneshot_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel);
+
+/**
+ * @brief Get GPIO number from the given ADC channel
+ *
+ * @param[in]  unit_id    ADC unit
+ * @param[in]  channel    ADC channel
+ * @param[out] io_num     GPIO number
+ *
+ * @param
+ *       - ESP_OK:              On success
+ *       - ESP_ERR_INVALID_ARG: Invalid argument
+ */
+esp_err_t adc_oneshot_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num);
+
+#ifdef __cplusplus
+}
+#endif

+ 5 - 4
components/driver/include/esp_private/adc2_wifi.h → components/esp_adc/include/esp_private/adc2_wifi.h

@@ -21,19 +21,20 @@ extern "C" {
  * The WIFI module may have to wait for a short time for the current conversion (if exist) to finish.
  *
  * @return
- *      - ESP_OK success
- *      - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
+ *        - ESP_OK success
+ *        - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
  */
 esp_err_t adc2_wifi_acquire(void);
 
-
 /**
  * @brief For WIFI module to let other tasks use the ADC2 when WIFI is not work.
  *
  * Other tasks will be forbidden to use ADC2 between ``adc2_wifi_acquire`` and ``adc2_wifi_release``.
  * Call this function to release the occupation of ADC2 by WIFI.
  *
- * @return always return ESP_OK.
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_STATE: The lock(s) isn't acquired yet
  */
 esp_err_t adc2_wifi_release(void);
 

+ 60 - 0
components/esp_adc/include/esp_private/adc_lock.h

@@ -0,0 +1,60 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "esp_err.h"
+#include "hal/adc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Acquire ADC lock by unit
+ *
+ * The lock acquiring sequence will be: ADC1, ADC2, ...
+ *
+ * @note If any of the locks are taken, this API will wait until the lock is successfully acquired.
+ *
+ * @param[in] unit_mask    ADC unit mask
+ *
+ * @return
+ *        - ESP_OK: On success
+ */
+esp_err_t adc_lock_acquire(adc_unit_t unit_mask);
+
+/**
+ * @brief Release ADC lock by unit
+ *
+ * The lock releasing sequence will be: ..., ADC2, ADC1
+ *
+ * @param[in] unit_mask    ADC unit mask
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_STATE: The lock(s) isn't acquired yet
+ */
+esp_err_t adc_lock_release(adc_unit_t unit_mask);
+
+/**
+ * @brief Try to acquire ADC lock by unit
+ *
+ * The lock acquiring sequence will be: ADC1, ADC2, ...
+ *
+ * @note If any of the locks are taken, this API will return immediately with an error `ESP_ERR_TIMEOUT`
+ *
+ * @param[in] unit_mask    ADC unit mask
+ *
+ * @return
+ *        - ESP_OK:          On success
+ *        - ESP_ERR_TIMEOUT: Lock(s) is taken already
+ */
+esp_err_t adc_lock_try_acquire(adc_unit_t unit_mask);
+
+#ifdef __cplusplus
+}
+#endif

+ 130 - 0
components/esp_adc/include/esp_private/adc_private.h

@@ -0,0 +1,130 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// DO NOT USE THESE APIS IN ANY APPLICATIONS
+
+#pragma once
+#include "esp_err.h"
+#include "hal/adc_types.h"
+#include "soc/soc_caps.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+* For those who use APB_SARADC periph
+*----------------------------------------------------------------------------*/
+/**
+ * @brief Claim the usage of the APB_SARADC periph
+ *
+ * Reference count inside
+ */
+void adc_apb_periph_claim(void);
+
+/**
+ * @brief Free the usage of the APB_SARADC periph
+ *
+ * Reference count inside
+ */
+void adc_apb_periph_free(void);
+
+
+/*------------------------------------------------------------------------------
+* ADC Power
+*----------------------------------------------------------------------------*/
+/**
+ * @brief Acquire the ADC Power
+ */
+void adc_power_acquire(void);
+
+/**
+ * @brief Release the ADC Power
+ */
+void adc_power_release(void);
+
+
+/*---------------------------------------------------------------
+            ADC IOs
+---------------------------------------------------------------*/
+/**
+ * @brief Get ADC channel from the given GPIO number
+ *
+ * @param[in]  io_num     GPIO number
+ * @param[out] unit_id    ADC unit
+ * @param[out] channel    ADC channel
+ *
+ * @return
+ *        - ESP_OK:              On success
+ *        - ESP_ERR_INVALID_ARG: Invalid argument
+ *        - ESP_ERR_NOT_FOUND:   The IO is not a valid ADC pad
+ */
+esp_err_t adc_io_to_channel(int io_num, adc_unit_t *unit_id, adc_channel_t *channel);
+
+/**
+ * @brief Get GPIO number from the given ADC channel
+ *
+ * @param[in]  unit_id    ADC unit
+ * @param[in]  channel    ADC channel
+ * @param[out] io_num     GPIO number
+ *
+ * @param
+ *       - ESP_OK:              On success
+ *       - ESP_ERR_INVALID_ARG: Invalid argument
+ */
+esp_err_t adc_channel_to_io(adc_unit_t unit_id, adc_channel_t channel, int *io_num);
+
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+/*---------------------------------------------------------------
+            ADC Hardware Calibration
+---------------------------------------------------------------*/
+/**
+ * @brief Calculate the ADC HW calibration code. (Based on the pre-stored efuse or actual calibration)
+ *
+ * @param adc_n ADC unit to calibrate
+ * @param atten Attenuation to use
+ */
+void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten);
+
+/**
+ * @brief Set the ADC HW calibration code.
+ *
+ * @param adc_n ADC unit to calibrate
+ * @param atten Attenuation to use
+ */
+void adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten);
+#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+
+/*---------------------------------------------------------------
+            ADC Oneshot Read API ISR Version
+---------------------------------------------------------------*/
+typedef struct adc_oneshot_unit_ctx_t *adc_oneshot_unit_handle_t;
+/**
+ * @brief ISR version to get one ADC conversion raw result
+ *
+ * @note This API only provide atomic register settings, without hardware resources protection. When other drivers are using
+ *       SAR-ADCs, calling this API may get wrong ADC result.
+ * @note This API can be called in an ISR context.
+ * @note Strongly suggest using this function when there's no concurrent hardware usage to the ADC. You can refer to ADC Oneshot
+ *       Programming Guide to know ADC Hardware Limitations
+ *
+ * @param[in] handle    ADC handle
+ * @param[in] chan      ADC channel
+ * @param[out] out_raw  ADC conversion raw result
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_ERR_INVALID_ARG:   Invalid arguments
+ *        - ESP_ERR_INVALID_STATE: Invalid state, the ADC result is invalid
+ */
+esp_err_t adc_oneshot_read_isr(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw);
+
+
+#ifdef __cplusplus
+}
+#endif

+ 46 - 0
components/esp_adc/interface/adc_cali_interface.h

@@ -0,0 +1,46 @@
+/*
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+#include "esp_types.h"
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct adc_cali_scheme_t adc_cali_scheme_t;
+
+/**
+ * @brief ADC Calibration Scheme Interface and Context
+ */
+struct adc_cali_scheme_t {
+
+    /**
+     * @brief Convert ADC raw data to calibrated voltage
+     *
+     * @param[in]  arg        ///< ADC calibration scheme specific context
+     * @param[in]  raw        ///< ADC raw data
+     * @param[out] voltage    ///< Calibrated ADC voltage (in mV)
+     *
+     * @return
+     *         - ESP_OK:                On success
+     *         - ESP_ERR_INVALID_ARG:   Invalid argument
+     *         - ESP_ERR_INVALID_STATE: Invalid state, scheme didn't registered
+     */
+    esp_err_t (*raw_to_voltage)(void *arg, int raw, int *voltage);
+
+    /**
+     * @brief ADC calibration specific contexts
+     * Can be customized to difference calibration schemes
+     */
+    void *ctx;
+
+};
+
+#ifdef __cplusplus
+}
+#endif

+ 5 - 0
components/esp_adc/linker.lf

@@ -0,0 +1,5 @@
+[mapping:esp_adc]
+archive: libesp_adc.a
+entries:
+    if ADC_ONESHOT_CTRL_FUNC_IN_IRAM = y:
+        adc_oneshot: adc_oneshot_read_isr (noflash)

+ 20 - 0
components/esp_adc/test_apps/adc/CMakeLists.txt

@@ -0,0 +1,20 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.16)
+
+set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(adc_test)
+
+if(CONFIG_COMPILER_DUMP_RTL_FILES)
+    add_custom_target(check_test_app_sections ALL
+                      COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
+                      --rtl-dir ${CMAKE_BINARY_DIR}/esp-idf/esp_adc/
+                      --elf-file ${CMAKE_BINARY_DIR}/adc_test.elf
+                      find-refs
+                      --from-sections=.iram0.text
+                      --to-sections=.flash.text,.flash.rodata
+                      --exit-code
+                      DEPENDS ${elf}
+                      )
+endif()

+ 2 - 0
components/esp_adc/test_apps/adc/README.md

@@ -0,0 +1,2 @@
+| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- |

+ 11 - 0
components/esp_adc/test_apps/adc/main/CMakeLists.txt

@@ -0,0 +1,11 @@
+set(srcs "test_app_main.c"
+         "test_adc.c"
+         "test_adc_performance.c"
+         "test_adc_driver.c"
+         "test_adc_driver_iram.c"
+         "test_common_adc.c")
+
+# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
+# the component can be registered as WHOLE_ARCHIVE
+idf_component_register(SRCS ${srcs}
+                       WHOLE_ARCHIVE)

+ 260 - 0
components/esp_adc/test_apps/adc/main/test_adc.c

@@ -0,0 +1,260 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unity.h"
+#include "esp_log.h"
+#include "soc/adc_periph.h"
+#include "esp_adc/adc_oneshot.h"
+#include "driver/gpio.h"
+#include "driver/rtc_io.h"
+#include "test_common_adc.h"
+
+const __attribute__((unused)) static char *TAG = "TEST_ADC";
+
+/*---------------------------------------------------------------
+        ADC General Macros
+---------------------------------------------------------------*/
+//ADC Channels
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC1_TEST_CHAN0          ADC_CHANNEL_4
+#define ADC1_TEST_CHAN1          ADC_CHANNEL_5
+#define ADC2_TEST_CHAN0          ADC_CHANNEL_0
+static const char *TAG_CH[2][10] = {{"ADC1_CH4", "ADC1_CH5"}, {"ADC2_CH0"}};
+#else
+#define ADC1_TEST_CHAN0          ADC_CHANNEL_2
+#define ADC1_TEST_CHAN1          ADC_CHANNEL_3
+#define ADC2_TEST_CHAN0          ADC_CHANNEL_0
+static const char *TAG_CH[2][10] = {{"ADC1_CH2", "ADC1_CH3"}, {"ADC2_CH0"}};
+#endif
+
+
+/*---------------------------------------------------------------
+        ADC Oneshot High / Low test
+---------------------------------------------------------------*/
+TEST_CASE("ADC oneshot high/low test", "[adc_oneshot]")
+{
+    static int adc_raw[2][10];
+
+    //-------------ADC1 Init---------------//
+    adc_oneshot_unit_handle_t adc1_handle;
+    adc_oneshot_unit_init_cfg_t init_config1 = {
+        .unit_id = ADC_UNIT_1,
+        .ulp_mode = false,
+    };
+    TEST_ESP_OK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
+
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    //-------------ADC2 Init---------------//
+    adc_oneshot_unit_handle_t adc2_handle;
+    adc_oneshot_unit_init_cfg_t init_config2 = {
+        .unit_id = ADC_UNIT_2,
+        .ulp_mode = false,
+    };
+    TEST_ESP_OK(adc_oneshot_new_unit(&init_config2, &adc2_handle));
+#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
+
+    //-------------ADC1 TEST Channel 0 Config---------------//
+    adc_oneshot_chan_cfg_t config = {
+        .bitwidth = ADC_BITWIDTH_DEFAULT,
+        .atten = ADC_ATTEN_DB_11,
+    };
+    TEST_ESP_OK(adc_oneshot_config_channel(adc1_handle, ADC1_TEST_CHAN0, &config));
+
+    //-------------ADC1 TEST Channel 1 Config---------------//
+    TEST_ESP_OK(adc_oneshot_config_channel(adc1_handle, ADC1_TEST_CHAN1, &config));
+
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    //-------------ADC2 TEST Channel 0 Config---------------//
+    TEST_ESP_OK(adc_oneshot_config_channel(adc2_handle, ADC2_TEST_CHAN0, &config));
+#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
+
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 0);
+    TEST_ESP_OK(adc_oneshot_read(adc1_handle, ADC1_TEST_CHAN0, &adc_raw[0][0]));
+    ESP_LOGI(TAG_CH[0][0], "raw  data: %d", adc_raw[0][0]);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw[0][0]);
+
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN1, 1);
+    TEST_ESP_OK(adc_oneshot_read(adc1_handle, ADC1_TEST_CHAN1, &adc_raw[0][1]));
+    ESP_LOGI(TAG_CH[0][1], "raw  data: %d", adc_raw[0][1]);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw[0][1]);
+
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    test_adc_set_io_level(ADC_UNIT_2, ADC2_TEST_CHAN0, 0);
+    TEST_ESP_OK(adc_oneshot_read(adc2_handle, ADC2_TEST_CHAN0, &adc_raw[1][0]));
+    ESP_LOGI(TAG_CH[1][0], "raw  data: %d", adc_raw[1][0]);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw[1][0]);
+#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
+
+
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1);
+    TEST_ESP_OK(adc_oneshot_read(adc1_handle, ADC1_TEST_CHAN0, &adc_raw[0][0]));
+    ESP_LOGI(TAG_CH[0][0], "raw  data: %d", adc_raw[0][0]);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw[0][0]);
+
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN1, 0);
+    TEST_ESP_OK(adc_oneshot_read(adc1_handle, ADC1_TEST_CHAN1, &adc_raw[0][1]));
+    ESP_LOGI(TAG_CH[0][1], "raw  data: %d", adc_raw[0][1]);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw[0][1]);
+
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    test_adc_set_io_level(ADC_UNIT_2, ADC2_TEST_CHAN0, 1);
+    TEST_ESP_OK(adc_oneshot_read(adc2_handle, ADC2_TEST_CHAN0, &adc_raw[1][0]));
+    ESP_LOGI(TAG_CH[1][0], "raw  data: %d", adc_raw[1][0]);
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw[1][0]);
+#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
+
+
+    TEST_ESP_OK(adc_oneshot_del_unit(adc1_handle));
+#if (SOC_ADC_PERIPH_NUM >= 2)
+    TEST_ESP_OK(adc_oneshot_del_unit(adc2_handle));
+#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
+}
+
+
+
+#if SOC_ADC_CALIBRATION_V1_SUPPORTED
+/*---------------------------------------------------------------
+        ADC Oneshot with Light Sleep
+---------------------------------------------------------------*/
+#include <inttypes.h>
+#include "esp_sleep.h"
+#include "esp_private/regi2c_ctrl.h"
+#include "soc/regi2c_saradc.h"
+
+#define TEST_REGI2C_ANA_CALI_BYTE_NUM   8
+
+static void s_adc_oneshot_with_sleep(adc_unit_t unit_id, adc_channel_t channel)
+{
+    adc_atten_t atten[SOC_ADC_ATTEN_NUM] = {ADC_ATTEN_DB_0, ADC_ATTEN_DB_2_5, ADC_ATTEN_DB_6, ADC_ATTEN_DB_11};
+    //-------------ADC Init---------------//
+    adc_oneshot_unit_handle_t adc_handle;
+    adc_oneshot_unit_init_cfg_t init_config = {
+        .unit_id = unit_id,
+        .ulp_mode = false,
+    };
+    TEST_ESP_OK(adc_oneshot_new_unit(&init_config, &adc_handle));
+
+    //-------------ADC Channel Config---------------//
+    adc_oneshot_chan_cfg_t config = {
+        .bitwidth = SOC_ADC_RTC_MAX_BITWIDTH,
+    };
+
+    //-------------ADC Calibration Init---------------//
+    bool do_calibration = false;
+    adc_cali_handle_t cali_handle[SOC_ADC_ATTEN_NUM] = {};
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+        do_calibration = test_adc_calibration_init(unit_id, i, SOC_ADC_RTC_MAX_BITWIDTH, &cali_handle[i]);
+    }
+    if (!do_calibration) {
+        ESP_LOGW(TAG, "No efuse bits burnt, only test the regi2c analog register values");
+    }
+
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+
+        //-------------ADC Channel Config---------------//
+        config.atten = atten[i];
+        TEST_ESP_OK(adc_oneshot_config_channel(adc_handle, channel, &config));
+        printf("Test with atten: %d\n", atten[i]);
+
+        //---------------------------------Before Sleep-----------------------------------//
+        printf("Before Light Sleep\n");
+        int raw_expected = 0;
+        int cali_expected = 0;
+        uint8_t regi2c_cali_val_before[TEST_REGI2C_ANA_CALI_BYTE_NUM] = {};
+
+        //Read
+        TEST_ESP_OK(adc_oneshot_read(adc_handle, channel, &raw_expected));
+        if (do_calibration) {
+            TEST_ESP_OK(adc_cali_raw_to_voltage(cali_handle[i], raw_expected, &cali_expected));
+        }
+
+        //Print regi2c
+        printf("regi2c cali val is: ");
+        for (int j = 0; j < TEST_REGI2C_ANA_CALI_BYTE_NUM; j++) {
+            regi2c_cali_val_before[j] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, j);
+            printf("0x%x ", regi2c_cali_val_before[j]);
+        }
+        printf("\n");
+
+        //Print result
+        ESP_LOGI(TAG, "ADC%d Chan%d: raw  data: %d", unit_id + 1, channel, raw_expected);
+        ESP_LOGI(TAG, "ADC%d Chan%d: cali data: %d", unit_id + 1, channel, cali_expected);
+
+        //---------------------------------Sleep-----------------------------------//
+        esp_sleep_enable_timer_wakeup(30 * 1000);
+        esp_light_sleep_start();
+
+        //---------------------------------After Sleep-----------------------------------//
+        printf("After Light Sleep\n");
+        int raw_after_sleep = 0;
+        int cali_after_sleep = 0;
+        uint8_t regi2c_cali_val_after[TEST_REGI2C_ANA_CALI_BYTE_NUM] = {};
+
+        //Print regi2c
+        printf("regi2c cali val is: ");
+        for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
+            regi2c_cali_val_after[i] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i);
+            printf("0x%x ", regi2c_cali_val_after[i]);
+        }
+        printf("\n");
+
+        //Read
+        TEST_ESP_OK(adc_oneshot_read(adc_handle, channel, &raw_after_sleep));
+        if (do_calibration) {
+            TEST_ESP_OK(adc_cali_raw_to_voltage(cali_handle[i], raw_after_sleep, &cali_after_sleep));
+        }
+
+        //Print result
+        ESP_LOGI(TAG, "ADC%d Chan%d: raw  data: %d", unit_id + 1, channel, raw_after_sleep);
+        if (do_calibration) {
+            ESP_LOGI(TAG, "ADC%d Chan%d: cali data: %d", unit_id + 1, channel, cali_after_sleep);
+        }
+
+        //Compare
+        int32_t raw_diff = raw_expected - raw_after_sleep;
+        ESP_LOGI(TAG, "ADC%d Chan%d: raw difference: %d", unit_id + 1, channel, raw_diff);
+
+        if (do_calibration) {
+                int32_t cali_diff = cali_expected - cali_after_sleep;
+                ESP_LOGI(TAG, "ADC%d Chan%d: cali difference: %d", unit_id + 1, channel, cali_diff);
+        }
+
+        //Test Calibration registers
+        for (int i = 0; i < TEST_REGI2C_ANA_CALI_BYTE_NUM; i++) {
+            TEST_ASSERT_EQUAL(regi2c_cali_val_before[i], regi2c_cali_val_after[i]);
+        }
+        ESP_LOGI(TAG, "Cali register settings unchanged\n");
+
+    }
+    TEST_ESP_OK(adc_oneshot_del_unit(adc_handle));
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+        if (cali_handle[i]) {
+            test_adc_calibration_deinit(cali_handle[i]);
+        }
+    }
+}
+
+//ADC Channels
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC1_SLEEP_TEST_CHAN          ADC_CHANNEL_6
+#define ADC2_SLEEP_TEST_CHAN          ADC_CHANNEL_0
+#else
+#define ADC1_SLEEP_TEST_CHAN          ADC_CHANNEL_2
+#define ADC2_SLEEP_TEST_CHAN          ADC_CHANNEL_0
+#endif
+
+TEST_CASE("test ADC1 Single Read with Light Sleep", "[adc][manul][ignore]")
+{
+    s_adc_oneshot_with_sleep(ADC_UNIT_1, ADC1_SLEEP_TEST_CHAN);
+}
+
+TEST_CASE("test ADC2 Single Read with Light Sleep", "[adc][manul][ignore]")
+{
+    s_adc_oneshot_with_sleep(ADC_UNIT_2, ADC2_SLEEP_TEST_CHAN);
+}
+#endif  //#if SOC_ADC_CALIBRATION_V1_SUPPORTED

+ 128 - 0
components/esp_adc/test_apps/adc/main/test_adc_driver.c

@@ -0,0 +1,128 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unity.h"
+#include "esp_log.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/gptimer.h"
+#include "esp_rom_sys.h"
+#include "esp_adc/adc_oneshot.h"
+#include "test_common_adc.h"
+
+const __attribute__((unused)) static char *TAG = "TEST_ADC";
+
+/*---------------------------------------------------------------
+        ADC General Macros
+---------------------------------------------------------------*/
+//ADC Channels
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC1_TEST_CHAN0          ADC_CHANNEL_4
+#else
+#define ADC1_TEST_CHAN0          ADC_CHANNEL_2
+#endif
+
+/*---------------------------------------------------------------
+        ADC work with ISR
+---------------------------------------------------------------*/
+typedef struct {
+    TaskHandle_t task_handle;    //Task handle
+    adc_oneshot_unit_handle_t adc_handle;    //ADC handle
+    bool level;    //ADC level
+} test_adc_isr_ctx_t;
+
+static bool IRAM_ATTR s_alarm_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
+{
+    test_adc_isr_ctx_t *test_ctx = (test_adc_isr_ctx_t *)user_data;
+    BaseType_t high_task_wakeup;
+    int adc_raw = 0;
+
+    /**
+     * This test won't disable the cache, so having some code on Flash is OK.
+     * If you copy this test callback with cache disabled, do remeber to put all code in internal RAM.
+     */
+
+    esp_rom_printf("alarm isr count=%llu\r\n", edata->count_value);
+    TEST_ESP_OK(adc_oneshot_read_isr(test_ctx->adc_handle, ADC1_TEST_CHAN0, &adc_raw));
+    esp_rom_printf("adc raw: %d\r\n", adc_raw);
+    if (test_ctx->level) {
+        TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, adc_raw);
+    } else {
+        TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, adc_raw);
+    }
+
+
+    // check the count value at alarm event
+    vTaskNotifyGiveFromISR(test_ctx->task_handle, &high_task_wakeup);
+    return high_task_wakeup == pdTRUE;
+}
+
+
+TEST_CASE("ADC oneshot fast work with ISR", "[adc_oneshot]")
+{
+    static test_adc_isr_ctx_t isr_test_ctx = {};
+    isr_test_ctx.adc_handle = NULL;
+    isr_test_ctx.task_handle = xTaskGetCurrentTaskHandle();
+
+    //-------------ADC1 Init---------------//
+    adc_oneshot_unit_init_cfg_t init_config1 = {
+        .unit_id = ADC_UNIT_1,
+        .ulp_mode = false,
+    };
+    TEST_ESP_OK(adc_oneshot_new_unit(&init_config1, &isr_test_ctx.adc_handle));
+
+    //-------------ADC1 TEST Channel 0 Config---------------//
+    adc_oneshot_chan_cfg_t config = {
+        .bitwidth = ADC_BITWIDTH_DEFAULT,
+        .atten = ADC_ATTEN_DB_11,
+    };
+    TEST_ESP_OK(adc_oneshot_config_channel(isr_test_ctx.adc_handle, ADC1_TEST_CHAN0, &config));
+
+    //-------------GPTimer Init & Config---------------//
+    gptimer_handle_t timer = NULL;
+    gptimer_config_t timer_config = {
+        .resolution_hz = 1 * 1000 * 1000,
+        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
+        .direction = GPTIMER_COUNT_UP,
+    };
+    TEST_ESP_OK(gptimer_new_timer(&timer_config, &timer));
+
+    gptimer_event_callbacks_t cbs = {
+        .on_alarm = s_alarm_callback,
+    };
+    gptimer_alarm_config_t alarm_config = {
+        .reload_count = 0,
+        .alarm_count = 100000, // 100ms
+    };
+    TEST_ESP_OK(gptimer_set_alarm_action(timer, &alarm_config));
+    TEST_ESP_OK(gptimer_register_event_callbacks(timer, &cbs, &isr_test_ctx));
+
+    //ADC IO tile low
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 0);
+    isr_test_ctx.level = 0;
+    printf("start timer\r\n");
+    TEST_ESP_OK(gptimer_enable(timer));
+    TEST_ESP_OK(gptimer_start(timer));
+    TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
+    TEST_ESP_OK(gptimer_stop(timer));
+
+
+    //ADC IO tile high
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1);
+    isr_test_ctx.level = 1;
+    //Reset counter value to zero
+    TEST_ESP_OK(gptimer_set_raw_count(timer, 0));
+    printf("start timer\r\n");
+    TEST_ESP_OK(gptimer_start(timer));
+    TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
+
+    //Tear Down
+    TEST_ESP_OK(gptimer_disable(timer));
+    TEST_ESP_OK(gptimer_del_timer(timer));
+    TEST_ESP_OK(adc_oneshot_del_unit(isr_test_ctx.adc_handle));
+}

+ 266 - 0
components/esp_adc/test_apps/adc/main/test_adc_driver_iram.c

@@ -0,0 +1,266 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unity.h"
+#include "esp_log.h"
+#include "esp_attr.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/gptimer.h"
+#include "esp_rom_sys.h"
+#include "test_common_adc.h"
+#include "esp_adc/adc_oneshot.h"
+
+const __attribute__((unused)) static char *TAG = "TEST_ADC";
+
+/*---------------------------------------------------------------
+        ADC General Macros
+---------------------------------------------------------------*/
+//ADC Channels
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC1_TEST_CHAN0          ADC_CHANNEL_4
+#else
+#define ADC1_TEST_CHAN0          ADC_CHANNEL_2
+#endif
+
+typedef struct {
+    void *adc_handle;                            //ADC handle, could be oneshot / continuous handle
+    bool level;                                  //ADC level
+    int adc_raw_high;                            //ADC reading raw when IO tie high
+    int cb_exe_times_high;                       //Callback running times when IO tie high and $ disabled
+    int adc_raw_low;                             //ADC reading raw when IO tie low
+    int cb_exe_times_low;                        //Callback running times when IO tie low and $ disabled
+    bool cache_disable_flag;                     //Indicating cache is disabled
+} test_adc_iram_ctx_t;
+
+extern void spi_flash_disable_interrupts_caches_and_other_cpu(void);
+extern void spi_flash_enable_interrupts_caches_and_other_cpu(void);
+__attribute__((unused))
+static void s_test_cache_disable_period_us(test_adc_iram_ctx_t *ctx, uint32_t period_us);
+
+
+#if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM && CONFIG_GPTIMER_ISR_IRAM_SAFE
+/*---------------------------------------------------------------
+        ADC oneshot work with cache safe ISR
+---------------------------------------------------------------*/
+static bool IRAM_ATTR NOINLINE_ATTR s_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
+{
+    test_adc_iram_ctx_t *test_ctx = (test_adc_iram_ctx_t *)user_data;
+    adc_oneshot_unit_handle_t oneshot_handle = *(adc_oneshot_unit_handle_t *)(test_ctx->adc_handle);
+
+    if (test_ctx->cache_disable_flag) {
+
+        if (test_ctx->level) {
+            adc_oneshot_read_isr(oneshot_handle, ADC1_TEST_CHAN0, &test_ctx->adc_raw_high);
+            esp_rom_printf(DRAM_STR("adc raw: %d\n"), test_ctx->adc_raw_high);
+            test_ctx->cb_exe_times_high++;
+        } else {
+            adc_oneshot_read_isr(oneshot_handle, ADC1_TEST_CHAN0, &test_ctx->adc_raw_low);
+            esp_rom_printf(DRAM_STR("adc raw: %d\n"), test_ctx->adc_raw_low);
+            test_ctx->cb_exe_times_low++;
+        }
+    }
+
+    return false;
+}
+
+TEST_CASE("ADC oneshot fast work with ISR and Flash", "[adc_oneshot]")
+{
+    adc_oneshot_unit_handle_t oneshot_handle;
+    static DRAM_ATTR test_adc_iram_ctx_t isr_test_ctx = {};
+    isr_test_ctx.adc_handle = &oneshot_handle;
+
+    //-------------ADC1 Init---------------//
+    adc_oneshot_unit_init_cfg_t init_config1 = {
+        .unit_id = ADC_UNIT_1,
+        .ulp_mode = false,
+    };
+    TEST_ESP_OK(adc_oneshot_new_unit(&init_config1, &oneshot_handle));
+
+    //-------------ADC1 TEST Channel 0 Config---------------//
+    adc_oneshot_chan_cfg_t config = {
+        .bitwidth = ADC_BITWIDTH_DEFAULT,
+        .atten = ADC_ATTEN_DB_11,
+    };
+    TEST_ESP_OK(adc_oneshot_config_channel(oneshot_handle, ADC1_TEST_CHAN0, &config));
+
+    //-------------GPTimer Init & Config---------------//
+    gptimer_handle_t timer = NULL;
+    gptimer_config_t timer_config = {
+        .resolution_hz = 1 * 1000 * 1000,
+        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
+        .direction = GPTIMER_COUNT_UP,
+    };
+    TEST_ESP_OK(gptimer_new_timer(&timer_config, &timer));
+
+    gptimer_event_callbacks_t cbs = {
+        .on_alarm = s_alarm_cb,
+    };
+    gptimer_alarm_config_t alarm_config = {
+        .reload_count = 0,
+        .alarm_count = 100000, // 100ms
+        .flags.auto_reload_on_alarm = true,
+    };
+    TEST_ESP_OK(gptimer_set_alarm_action(timer, &alarm_config));
+    TEST_ESP_OK(gptimer_register_event_callbacks(timer, &cbs, &isr_test_ctx));
+
+    //ADC IO tile low
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 0);
+    isr_test_ctx.level = 0;
+    printf("start timer\r\n");
+    TEST_ESP_OK(gptimer_enable(timer));
+    TEST_ESP_OK(gptimer_start(timer));
+    s_test_cache_disable_period_us(&isr_test_ctx, 100 * 1000);
+    TEST_ESP_OK(gptimer_stop(timer));
+    //Checks
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, isr_test_ctx.adc_raw_low);
+    esp_rom_printf("callback runs %d times when $ disabled\n", isr_test_ctx.cb_exe_times_low);
+    TEST_ASSERT_GREATER_OR_EQUAL(1, isr_test_ctx.cb_exe_times_low);
+
+    //ADC IO tile high
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1);
+    isr_test_ctx.level = 1;
+    //Reset counter value to zero
+    TEST_ESP_OK(gptimer_set_raw_count(timer, 0));
+    printf("start timer\r\n");
+    TEST_ESP_OK(gptimer_start(timer));
+    s_test_cache_disable_period_us(&isr_test_ctx, 100 * 1000);
+    TEST_ESP_OK(gptimer_stop(timer));
+    //Checks
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL, isr_test_ctx.adc_raw_high);
+    esp_rom_printf("callback runs %d times when $ disabled\n", isr_test_ctx.cb_exe_times_high);
+    TEST_ASSERT_GREATER_OR_EQUAL(1, isr_test_ctx.cb_exe_times_high);
+
+    //Tear Down
+    TEST_ESP_OK(gptimer_disable(timer));
+    TEST_ESP_OK(gptimer_del_timer(timer));
+    TEST_ESP_OK(adc_oneshot_del_unit(oneshot_handle));
+}
+#endif  //#if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM && CONFIG_GPTIMER_ISR_IRAM_SAFE
+
+
+#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE
+#include "esp_adc/adc_continuous.h"
+/*---------------------------------------------------------------
+        ADC continuous work with cache safe ISR
+---------------------------------------------------------------*/
+#if (SOC_ADC_DIGI_RESULT_BYTES == 2)
+#define ADC_TEST_OUTPUT_TYPE    ADC_DIGI_OUTPUT_FORMAT_TYPE1
+#else
+#define ADC_TEST_OUTPUT_TYPE    ADC_DIGI_OUTPUT_FORMAT_TYPE2
+#endif
+
+#define ADC_TEST_FREQ_HZ        (50 * 1000)
+#define ADC_TEST_PKG_SIZE       100
+static bool IRAM_ATTR NOINLINE_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
+{
+    test_adc_iram_ctx_t *test_ctx = (test_adc_iram_ctx_t *)user_data;
+
+    if (test_ctx->cache_disable_flag) {
+        int raw = 0;
+
+        for (int i = 0; i < edata->size; i += SOC_ADC_DIGI_RESULT_BYTES) {
+            adc_digi_output_data_t *p = (void*)&(edata->conv_frame_buffer[i]);
+#if (SOC_ADC_DIGI_RESULT_BYTES == 2)
+            raw += p->type1.data;
+#else
+            raw += p->type2.data;
+#endif
+        }
+        if (test_ctx->level) {
+            test_ctx->adc_raw_high = raw / (edata->size / SOC_ADC_DIGI_RESULT_BYTES);
+            test_ctx->cb_exe_times_high++;
+        } else {
+            test_ctx->adc_raw_low = raw / (edata->size / SOC_ADC_DIGI_RESULT_BYTES);
+            test_ctx->cb_exe_times_low++;
+        }
+    }
+
+
+    return false;
+}
+
+TEST_CASE("ADC continuous work with ISR and Flash", "[adc_oneshot]")
+{
+    adc_continuous_handle_t handle = NULL;
+    adc_continuous_handle_cfg_t adc_config = {
+        .max_store_buf_size = 1024,
+        .conv_frame_size = ADC_TEST_PKG_SIZE,
+    };
+    TEST_ESP_OK(adc_continuous_new_handle(&adc_config, &handle));
+
+    adc_continuous_config_t dig_cfg = {
+        .sample_freq_hz = ADC_TEST_FREQ_HZ,
+        .conv_mode = ADC_CONV_SINGLE_UNIT_1,
+        .format = ADC_TEST_OUTPUT_TYPE,
+    };
+    adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
+    adc_pattern[0].atten = ADC_ATTEN_DB_0;
+    adc_pattern[0].channel = ADC1_TEST_CHAN0;
+    adc_pattern[0].unit = ADC_UNIT_1;
+    adc_pattern[0].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
+    dig_cfg.adc_pattern = adc_pattern;
+    dig_cfg.pattern_num = 1;
+    TEST_ESP_OK(adc_continuous_config(handle, &dig_cfg));
+
+    static DRAM_ATTR test_adc_iram_ctx_t isr_test_ctx = {};
+    isr_test_ctx.adc_handle = &handle;
+    adc_continuous_evt_cbs_t cbs = {
+        .on_conv_done = s_conv_done_cb,
+    };
+    TEST_ESP_OK(adc_continuous_register_event_callbacks(handle, &cbs, &isr_test_ctx));
+
+#if CONFIG_IDF_TARGET_ESP32
+    //This may need to be bigger, when the sampling freq is low
+    uint32_t overhead_us = 150;
+#else
+    uint32_t overhead_us = 0;
+#endif
+    uint32_t wait_time_us = (1000 * 1000 / ADC_TEST_FREQ_HZ * ADC_TEST_PKG_SIZE / SOC_ADC_DIGI_RESULT_BYTES) + overhead_us;
+    printf("period is %d us\n", wait_time_us);
+
+    //ADC IO tile low
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 0);
+    isr_test_ctx.level = 0;
+    TEST_ESP_OK(adc_continuous_start(handle));
+    s_test_cache_disable_period_us(&isr_test_ctx, wait_time_us);
+    TEST_ESP_OK(adc_continuous_stop(handle));
+    //Checks
+    TEST_ASSERT_INT_WITHIN(ADC_TEST_LOW_THRESH, ADC_TEST_LOW_VAL, isr_test_ctx.adc_raw_low);
+    esp_rom_printf("callback runs %d times when $ disabled\n", isr_test_ctx.cb_exe_times_low);
+    TEST_ASSERT_GREATER_OR_EQUAL(1, isr_test_ctx.cb_exe_times_low);
+
+    vTaskDelay(10);
+
+    printf("to set high\n");
+    //ADC IO tile high
+    test_adc_set_io_level(ADC_UNIT_1, ADC1_TEST_CHAN0, 1);
+    isr_test_ctx.level = 1;
+    TEST_ESP_OK(adc_continuous_start(handle));
+    s_test_cache_disable_period_us(&isr_test_ctx, wait_time_us);
+    TEST_ESP_OK(adc_continuous_stop(handle));
+    //Checks
+    // TEST_ASSERT_INT_WITHIN(ADC_TEST_HIGH_THRESH, ADC_TEST_HIGH_VAL_DMA, isr_test_ctx.adc_raw_high);
+    esp_rom_printf("callback runs %d times when $ disabled\n", isr_test_ctx.cb_exe_times_high);
+    TEST_ASSERT_GREATER_OR_EQUAL(1, isr_test_ctx.cb_exe_times_high);
+
+    TEST_ESP_OK(adc_continuous_deinit(handle));
+
+}
+#endif  //#if CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE
+
+static void IRAM_ATTR NOINLINE_ATTR s_test_cache_disable_period_us(test_adc_iram_ctx_t *ctx, uint32_t period_us)
+{
+    spi_flash_disable_interrupts_caches_and_other_cpu();
+    ctx->cache_disable_flag = 1;
+
+    esp_rom_delay_us(period_us);
+
+    ctx->cache_disable_flag = 0;
+    spi_flash_enable_interrupts_caches_and_other_cpu();
+}

+ 298 - 0
components/esp_adc/test_apps/adc/main/test_adc_performance.c

@@ -0,0 +1,298 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "unity.h"
+#include "test_utils.h"
+#include "esp_log.h"
+#include "esp_err.h"
+#include "soc/adc_periph.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_adc/adc_oneshot.h"
+#include "test_common_adc.h"
+
+#if CONFIG_IDF_TARGET_ESP32 ||  SOC_ADC_CALIBRATION_V1_SUPPORTED
+
+__attribute__((unused)) static const char *TAG = "TEST_ADC";
+
+/*---------------------------------------------------------------
+        ADC Oneshot Average / STD_Deviation Test
+---------------------------------------------------------------*/
+#define TEST_COUNT               (1<<SOC_ADC_RTC_MAX_BITWIDTH)
+#define MAX_ARRAY_SIZE           (1<<SOC_ADC_RTC_MAX_BITWIDTH)
+
+static int s_adc_count[MAX_ARRAY_SIZE]={};
+static int s_adc_offset = -1;
+
+static int s_insert_point(uint32_t value)
+{
+    const bool fixed_size = true;
+
+    if (s_adc_offset < 0) {
+        if (fixed_size) {
+            TEST_ASSERT_GREATER_OR_EQUAL(4096, MAX_ARRAY_SIZE);
+            s_adc_offset = 0;   //Fixed to 0 because the array can hold all the data in 12 bits
+        } else {
+            s_adc_offset = MAX((int)value - MAX_ARRAY_SIZE/2, 0);
+        }
+    }
+
+    if (!fixed_size && (value < s_adc_offset || value >= s_adc_offset + MAX_ARRAY_SIZE)) {
+        TEST_ASSERT_GREATER_OR_EQUAL(s_adc_offset, value);
+        TEST_ASSERT_LESS_THAN(s_adc_offset + MAX_ARRAY_SIZE, value);
+    }
+
+    s_adc_count[value - s_adc_offset] ++;
+    return value - s_adc_offset;
+}
+
+static void s_reset_array(void)
+{
+    memset(s_adc_count, 0, sizeof(s_adc_count));
+    s_adc_offset = -1;
+}
+
+static uint32_t s_get_average(void)
+{
+    uint32_t sum = 0;
+    int count = 0;
+    for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
+        sum += s_adc_count[i] * (s_adc_offset+i);
+        count += s_adc_count[i];
+    }
+    return sum/count;
+}
+
+static void s_print_summary(bool figure)
+{
+    const int MAX_WIDTH=20;
+    int max_count = 0;
+    int start = -1;
+    int end = -1;
+    uint32_t sum = 0;
+    int count = 0;
+    for (int i = 0; i < MAX_ARRAY_SIZE; i++) {
+        if (s_adc_count[i] > max_count) {
+            max_count = s_adc_count[i];
+        }
+        if (s_adc_count[i] > 0 && start < 0) {
+            start = i;
+        }
+        if (s_adc_count[i] > 0) {
+            end = i;
+        }
+        count += s_adc_count[i];
+        sum += s_adc_count[i] * (s_adc_offset+i);
+    }
+
+    if (figure) {
+        for (int i = start; i <= end; i++) {
+            printf("%4d ", i+s_adc_offset);
+            int count = s_adc_count[i] * MAX_WIDTH / max_count;
+            for (int j = 0; j < count; j++) {
+                putchar('|');
+            }
+            printf("    %d\n", s_adc_count[i]);
+        }
+    }
+    float average = (float)sum/count;
+
+    float variation_square = 0;
+    for (int i = start; i <= end; i ++) {
+        if (s_adc_count[i] == 0) {
+            continue;
+        }
+        float delta = i + s_adc_offset - average;
+        variation_square += (delta * delta) * s_adc_count[i];
+    }
+
+    printf("%d points.\n", count);
+    printf("average: %.1f\n", (float)sum/count);
+    printf("std: %.2f\n", sqrt(variation_square/count));
+}
+
+#if CONFIG_IDF_TARGET_ESP32
+#define TEST_STD_ADC1_CHANNEL0    ADC_CHANNEL_6
+#else
+#define TEST_STD_ADC1_CHANNEL0    ADC_CHANNEL_2
+#endif
+
+TEST_CASE("ADC1 oneshot raw average / std_deviation", "[adc_oneshot][ignore][manual]")
+{
+    adc_atten_t atten[SOC_ADC_ATTEN_NUM] = {ADC_ATTEN_DB_0, ADC_ATTEN_DB_2_5, ADC_ATTEN_DB_6, ADC_ATTEN_DB_11};
+    adc_channel_t channel = TEST_STD_ADC1_CHANNEL0;
+    int raw = 0;
+    bool print_figure = false;
+
+    //-------------ADC1 Init---------------//
+    adc_oneshot_unit_handle_t adc1_handle;
+    adc_oneshot_unit_init_cfg_t init_config1 = {
+        .unit_id = ADC_UNIT_1,
+        .ulp_mode = false,
+    };
+    TEST_ESP_OK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
+
+    //-------------ADC Channel Config---------------//
+    adc_oneshot_chan_cfg_t config = {
+        .bitwidth = SOC_ADC_RTC_MAX_BITWIDTH,
+    };
+
+    //-------------ADC Calibration Init---------------//
+    bool do_calibration = false;
+    adc_cali_handle_t cali_handle[SOC_ADC_ATTEN_NUM] = {};
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+        do_calibration = test_adc_calibration_init(ADC_UNIT_1, i, ADC_BITWIDTH_DEFAULT, &cali_handle[i]);
+    }
+    if (!do_calibration) {
+        ESP_LOGW(TAG, "calibration fail, jump calibration\n");
+    }
+
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+
+        //-------------ADC1 Channel Config---------------//
+        config.atten = atten[i];
+        TEST_ESP_OK(adc_oneshot_config_channel(adc1_handle, channel, &config));
+        ESP_LOGI("TEST_ADC", "Test with atten: %d", atten[i]);
+
+        while (1) {
+
+            s_reset_array();
+
+            for (int i = 0; i < TEST_COUNT; i++) {
+                TEST_ESP_OK(adc_oneshot_read(adc1_handle, channel, &raw));
+                s_insert_point(raw);
+            }
+            s_print_summary(print_figure);
+            break;
+        }
+
+        if (do_calibration) {
+            uint32_t raw = s_get_average();
+            int voltage_mv = 0;
+            TEST_ESP_OK(adc_cali_raw_to_voltage(cali_handle[i], raw, &voltage_mv));
+            printf("Voltage = %d mV\n", voltage_mv);
+        }
+    }
+
+    TEST_ESP_OK(adc_oneshot_del_unit(adc1_handle));
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+        if (cali_handle[i]) {
+            test_adc_calibration_deinit(cali_handle[i]);
+        }
+    }
+}
+
+
+/*---------------------------------------------------------------
+        ADC Calibration Speed
+---------------------------------------------------------------*/
+#ifdef CONFIG_IDF_TARGET_ESP32
+#define CPU_FREQ_MHZ                    CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
+#elif CONFIG_IDF_TARGET_ESP32S2
+#define CPU_FREQ_MHZ                    CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
+#elif CONFIG_IDF_TARGET_ESP32S3
+#define CPU_FREQ_MHZ                    CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
+#elif CONFIG_IDF_TARGET_ESP32C3
+#define CPU_FREQ_MHZ                    CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
+#endif
+
+#define RECORD_TIME_PREPARE() uint32_t __t1, __t2
+#define RECORD_TIME_START()             do {__t1 = esp_cpu_get_ccount();}while(0)
+#define RECORD_TIME_END(p_time)         do{__t2 = esp_cpu_get_ccount(); *p_time = (__t2-__t1);}while(0)
+#define GET_US_BY_CCOUNT(t)             ((double)t/CPU_FREQ_MHZ)
+
+
+//ADC Channels
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC1_CALI_SPEED_TEST_CHAN0            ADC_CHANNEL_6
+#define ADC2_CALI_SPEED_TEST_CHAN0            ADC_CHANNEL_0
+#else
+#define ADC1_CALI_SPEED_TEST_CHAN0            ADC_CHANNEL_2
+#define ADC2_CALI_SPEED_TEST_CHAN0            ADC_CHANNEL_0
+#endif
+
+#define TIMES_PER_ATTEN                 10
+
+
+static IRAM_ATTR NOINLINE_ATTR uint32_t get_cali_time_in_ccount(adc_cali_handle_t cali_handle, int adc_raw)
+{
+    uint32_t time;
+    int voltage = 0;
+    RECORD_TIME_PREPARE();
+    RECORD_TIME_START();
+    adc_cali_raw_to_voltage(cali_handle, adc_raw, &voltage);
+    RECORD_TIME_END(&time);
+
+    return time;
+}
+
+static void s_adc_cali_speed(adc_unit_t unit_id, adc_channel_t channel)
+{
+    //-------------ADC Calibration Init---------------//
+    bool do_calibration = false;
+    adc_cali_handle_t cali_handle[SOC_ADC_ATTEN_NUM] = {};
+    for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+        do_calibration = test_adc_calibration_init(unit_id, i, SOC_ADC_RTC_MAX_BITWIDTH, &cali_handle[i]);
+    }
+
+    if (!do_calibration) {
+        ESP_LOGW(TAG, "no efuse burnt, jump test");
+    } else {
+
+        ESP_LOGI(TAG, "CPU FREQ is %dMHz", CPU_FREQ_MHZ);
+        adc_atten_t atten[SOC_ADC_ATTEN_NUM] = {ADC_ATTEN_DB_0, ADC_ATTEN_DB_2_5, ADC_ATTEN_DB_6, ADC_ATTEN_DB_11};
+        uint32_t adc_time_record[4][TIMES_PER_ATTEN] = {};
+        int adc_raw = 0;
+
+        //-------------ADC Init---------------//
+        adc_oneshot_unit_handle_t adc_handle;
+        adc_oneshot_unit_init_cfg_t init_config = {
+            .unit_id = unit_id,
+            .ulp_mode = false,
+        };
+        TEST_ESP_OK(adc_oneshot_new_unit(&init_config, &adc_handle));
+
+        //-------------ADC Channel Config---------------//
+        adc_oneshot_chan_cfg_t config = {
+            .bitwidth = SOC_ADC_RTC_MAX_BITWIDTH,
+        };
+
+        //atten0 ~ atten3
+        for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+
+            //-------------ADC Channel Config---------------//
+            config.atten = atten[i];
+            TEST_ESP_OK(adc_oneshot_config_channel(adc_handle, channel, &config));
+            ESP_LOGI("TEST_ADC", "Test with atten: %d", atten[i]);
+
+            for (int j = 0; j < TIMES_PER_ATTEN; j++) {
+                TEST_ESP_OK(adc_oneshot_read(adc_handle, channel, &adc_raw));
+                adc_time_record[i][j] = get_cali_time_in_ccount(cali_handle[i], adc_raw);
+                IDF_LOG_PERFORMANCE("ADC1 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc_time_record[i][j]));
+            }
+        }
+
+        TEST_ESP_OK(adc_oneshot_del_unit(adc_handle));
+        for (int i = 0; i < SOC_ADC_ATTEN_NUM; i++) {
+            if (cali_handle[i]) {
+                test_adc_calibration_deinit(cali_handle[i]);
+            }
+        }
+    }
+}
+
+TEST_CASE("ADC1 Calibration Speed", "[adc][ignore][manual]")
+{
+    s_adc_cali_speed(ADC_UNIT_1, ADC1_CALI_SPEED_TEST_CHAN0);
+}
+
+TEST_CASE("ADC2 Calibration Speed", "[adc][ignore][manual]")
+{
+    s_adc_cali_speed(ADC_UNIT_2, ADC2_CALI_SPEED_TEST_CHAN0);
+}
+#endif  //#if CONFIG_IDF_TARGET_ESP32 ||  SOC_ADC_CALIBRATION_V1_SUPPORTED

+ 40 - 0
components/esp_adc/test_apps/adc/main/test_app_main.c

@@ -0,0 +1,40 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+#define TEST_MEMORY_LEAK_THRESHOLD (-600)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    unity_run_menu();
+}

+ 94 - 0
components/esp_adc/test_apps/adc/main/test_common_adc.c

@@ -0,0 +1,94 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "unity.h"
+#include "esp_log.h"
+#include "driver/gpio.h"
+#include "driver/rtc_io.h"
+#include "soc/adc_periph.h"
+#include "test_common_adc.h"
+
+__attribute__((unused)) static const char *TAG = "TEST_ADC";
+
+/*---------------------------------------------------------------
+        ADC Calibration
+---------------------------------------------------------------*/
+bool test_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_bitwidth_t bitwidth, adc_cali_handle_t *out_handle)
+{
+    esp_err_t ret = ESP_FAIL;
+    adc_cali_handle_t handle = NULL;
+    bool calibrated = false;
+
+#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
+    ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
+    adc_cali_curve_fitting_config_t cali_config = {
+        .unit_id = unit,
+        .atten = atten,
+        .bitwidth = bitwidth,
+    };
+    ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
+
+#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
+    ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
+    adc_cali_line_fitting_config_t cali_config = {
+        .unit_id = unit,
+        .atten = atten,
+        .bitwidth = bitwidth,
+    };
+    ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
+#endif
+
+    if (ret == ESP_OK) {
+        calibrated = true;
+    } else if (ret == ESP_ERR_NOT_SUPPORTED) {
+        ESP_LOGW(TAG, "calibration fail due to lack of eFuse bits");
+    } else {
+        TEST_ASSERT(false);
+    }
+
+    *out_handle = handle;
+
+    return calibrated;
+}
+
+void test_adc_calibration_deinit(adc_cali_handle_t handle)
+{
+#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
+    ESP_LOGI(TAG, "deregister %s calibration scheme", "Curve Fitting");
+    TEST_ESP_OK(adc_cali_delete_scheme_curve_fitting(handle));
+
+#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
+    ESP_LOGI(TAG, "deregister %s calibration scheme", "Line Fitting");
+    TEST_ESP_OK(adc_cali_delete_scheme_line_fitting(handle));
+#endif
+}
+
+
+/*---------------------------------------------------------------
+        ADC GPIO
+---------------------------------------------------------------*/
+#define ADC_GET_IO_NUM(unit, channel) (adc_channel_io_map[unit][channel])
+
+void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level)
+{
+    TEST_ASSERT(channel < SOC_ADC_CHANNEL_NUM(unit) && "invalid channel");
+
+#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
+    uint32_t io_num = ADC_GET_IO_NUM(unit, channel);
+    TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY: GPIO_PULLDOWN_ONLY)));
+#else
+    gpio_num_t io_num = ADC_GET_IO_NUM(unit, channel);
+    if (level) {
+        TEST_ESP_OK(rtc_gpio_pullup_en(io_num));
+        TEST_ESP_OK(rtc_gpio_pulldown_dis(io_num));
+    } else {
+        TEST_ESP_OK(rtc_gpio_pullup_dis(io_num));
+        TEST_ESP_OK(rtc_gpio_pulldown_en(io_num));
+    }
+    TEST_ESP_OK(gpio_set_pull_mode(io_num, (level ? GPIO_PULLUP_ONLY: GPIO_PULLDOWN_ONLY)));
+#endif
+}

+ 107 - 0
components/esp_adc/test_apps/adc/main/test_common_adc.h

@@ -0,0 +1,107 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "sdkconfig.h"
+#include "esp_log.h"
+#include "soc/soc_caps.h"
+#include "esp_private/adc_private.h"
+#include "esp_adc/adc_cali.h"
+#include "esp_adc/adc_cali_scheme.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MAX
+#define MAX(a, b)         (((a) > (b)) ? (a) : (b))
+#endif
+
+/*---------------------------------------------------------------
+        ADC Calibration
+---------------------------------------------------------------*/
+/**
+ * @brief Initialise ADC Calibration
+ *
+ * @param[out] out_handle    ADC calibration handle
+ *
+ * @return
+ *        - True  Calibration success
+ *        - False Calibration fail
+ */
+bool test_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_bitwidth_t bitwidth, adc_cali_handle_t *out_handle);
+
+/**
+ * @brief De-initialise ADC Calibration
+ *
+ * @param[in] handle    ADC calibration handle
+ */
+void test_adc_calibration_deinit(adc_cali_handle_t handle);
+
+
+/*---------------------------------------------------------------
+        ADC GPIO
+---------------------------------------------------------------*/
+/**
+ * We use weak pulldown, `ADC_TEST_LOW_THRESH` may vary.
+ * If connect to GND, `ADC_TEST_LOW_THRESH` can be smaller
+ */
+#if CONFIG_IDF_TARGET_ESP32
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      10
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_VAL_DMA    4095
+#define ADC_TEST_HIGH_THRESH     10
+
+#elif CONFIG_IDF_TARGET_ESP32S2
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      35
+
+#define ADC_TEST_HIGH_VAL        8191
+#define ADC_TEST_HIGH_VAL_DMA    4095
+#define ADC_TEST_HIGH_THRESH     10
+
+#elif CONFIG_IDF_TARGET_ESP32C3
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      60
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_VAL_DMA    4095
+#define ADC_TEST_HIGH_THRESH     10
+
+#elif CONFIG_IDF_TARGET_ESP32S3
+#define ADC_TEST_LOW_VAL         0
+#define ADC_TEST_LOW_THRESH      15
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_VAL_DMA    4095
+#define ADC_TEST_HIGH_THRESH     0
+
+#elif CONFIG_IDF_TARGET_ESP32C2
+#define ADC_TEST_LOW_VAL         2147
+#define ADC_TEST_LOW_THRESH      50
+
+#define ADC_TEST_HIGH_VAL        4095
+#define ADC_TEST_HIGH_THRESH     0
+#endif
+
+/**
+ * @brief Set ADC IO level
+ *
+ * @param[in] unit      ADC unit
+ * @param[in] channel   ADC channel
+ * @param[in] level     IO level. True: high; False: low
+ */
+void test_adc_set_io_level(adc_unit_t unit, adc_channel_t channel, bool level);
+
+#ifdef __cplusplus
+}
+#endif

+ 21 - 0
components/esp_adc/test_apps/adc/pytest_adc.py

@@ -0,0 +1,21 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32
+@pytest.mark.esp32s2
+@pytest.mark.esp32c3
+@pytest.mark.esp32s3
+@pytest.mark.esp32c2
+@pytest.mark.generic
+@pytest.mark.parametrize('config', [
+    'iram_safe',
+    'release',
+], indirect=True)
+def test_adc(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output(timeout=120)

+ 6 - 0
components/esp_adc/test_apps/adc/sdkconfig.ci.iram_safe

@@ -0,0 +1,6 @@
+CONFIG_COMPILER_DUMP_RTL_FILES=y
+CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM=y
+CONFIG_GPTIMER_ISR_IRAM_SAFE=y
+CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE=y
+# silent the error check, as the error string are stored in rodata, causing RTL check failure
+CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y

+ 3 - 0
components/esp_adc/test_apps/adc/sdkconfig.ci.release

@@ -0,0 +1,3 @@
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

+ 2 - 0
components/esp_adc/test_apps/adc/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n

+ 0 - 12
components/esp_adc_cal/CMakeLists.txt

@@ -1,12 +0,0 @@
-idf_build_get_property(target IDF_TARGET)
-
-set(srcs "esp_adc_cal_common.c")
-set(src_target "${target}/esp_adc_cal.c")
-if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${src_target}")
-    list(APPEND srcs ${src_target})
-endif()
-
-idf_component_register(SRCS ${srcs}
-                       INCLUDE_DIRS include
-                       REQUIRES driver
-                       PRIV_REQUIRES efuse)

+ 0 - 31
components/esp_adc_cal/Kconfig

@@ -1,31 +0,0 @@
-menu "ADC-Calibration"
-
-    config ADC_CAL_EFUSE_TP_ENABLE
-        depends on IDF_TARGET_ESP32
-        bool "Use Two Point Values"
-        default "y"
-        help
-            Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.
-            This option will allow the ADC calibration component to characterize the
-            ADC-Voltage curve using Two Point values if they are available.
-
-    config ADC_CAL_EFUSE_VREF_ENABLE
-        depends on IDF_TARGET_ESP32
-        bool "Use eFuse Vref"
-        default "y"
-        help
-            Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow
-            the ADC calibration component to characterize the ADC-Voltage curve using
-            eFuse Vref if it is available.
-
-    config ADC_CAL_LUT_ENABLE
-        depends on IDF_TARGET_ESP32
-        bool "Use Lookup Tables"
-        default "y"
-        help
-            This option will allow the ADC calibration component to use Lookup Tables
-            to correct for non-linear behavior in 11db attenuation. Other attenuations
-            do not exhibit non-linear behavior hence will not be affected by this option.
-
-
-endmenu  # ADC-Calibration

+ 1 - 1
components/esp_phy/CMakeLists.txt

@@ -31,7 +31,7 @@ endif()
 # [refactor-todo]: requires "driver" component for periph_ctrl header file
 idf_component_register(SRCS "${srcs}"
                     INCLUDE_DIRS "include" "${idf_target}/include"
-                    PRIV_REQUIRES nvs_flash driver efuse esp_timer
+                    PRIV_REQUIRES nvs_flash driver efuse esp_timer esp_adc
                     LDFRAGMENTS "${ldfragments}"
                     EMBED_FILES  ${embed_files}
                     )

+ 2 - 1
components/esp_phy/src/phy_override.c

@@ -5,8 +5,9 @@
  */
 
 #include <stdbool.h>
+#include "esp_attr.h"
 #include "esp_private/regi2c_ctrl.h"
-#include "driver/adc.h"
+#include "esp_private/adc_private.h"
 
 /*
  * This file is used to override the hooks provided by the PHY lib for some system features.

+ 1 - 1
components/esp_wifi/CMakeLists.txt

@@ -30,7 +30,7 @@ endif()
 idf_component_register(SRCS "${srcs}"
                     INCLUDE_DIRS "include"
                     REQUIRES esp_event esp_phy
-                    PRIV_REQUIRES driver esptool_py esp_netif esp_pm esp_timer nvs_flash
+                    PRIV_REQUIRES driver esptool_py esp_netif esp_pm esp_timer nvs_flash esp_adc
                                   wpa_supplicant hal lwip ${extra_priv_requires}
                     LDFRAGMENTS "${ldfragments}")
 

+ 1 - 0
components/esp_wifi/src/wifi_init.c

@@ -15,6 +15,7 @@
 #include "esp_private/esp_clk.h"
 #include "esp_wpa.h"
 #include "esp_netif.h"
+#include "esp_private/adc_private.h"
 #include "esp_coexist_internal.h"
 #include "esp_phy_init.h"
 #include "phy.h"

+ 5 - 3
components/hal/CMakeLists.txt

@@ -44,7 +44,7 @@ if(NOT BOOTLOADER_BUILD)
         "spi_flash_encrypt_hal_iram.c"
         "sha_hal.c"
         "adc_hal_common.c"
-        "adc_hal.c")
+        "adc_oneshot_hal.c")
 
     if(CONFIG_SOC_SYSTIMER_SUPPORTED AND NOT CONFIG_HAL_SYSTIMER_USE_ROM_IMPL)
         list(APPEND srcs "systimer_hal.c")
@@ -82,6 +82,10 @@ if(NOT BOOTLOADER_BUILD)
         list(APPEND srcs "emac_hal.c")
     endif()
 
+    if(CONFIG_SOC_ADC_DMA_SUPPORTED)
+        list(APPEND srcs "adc_hal.c")
+    endif()
+
     if(CONFIG_SOC_LCDCAM_SUPPORTED)
         list(APPEND srcs "lcd_hal.c")
     endif()
@@ -96,7 +100,6 @@ if(NOT BOOTLOADER_BUILD)
             "sdio_slave_hal.c"
             "touch_sensor_hal.c"
             "aes_hal.c"
-            "esp32/adc_hal.c"
             "esp32/brownout_hal.c"
             "esp32/touch_sensor_hal.c"
             "esp32/gpio_hal_workaround.c")
@@ -143,7 +146,6 @@ if(NOT BOOTLOADER_BUILD)
               "spi_slave_hd_hal.c"
               "xt_wdt_hal.c"
               "aes_hal.c"
-              "esp32c3/adc_hal.c"
               "esp32c3/brownout_hal.c"
               "esp32c3/hmac_hal.c"
               "esp32c3/rtc_cntl_hal.c")

+ 9 - 85
components/hal/adc_hal.c

@@ -25,16 +25,6 @@
 #include "soc/spi_struct.h"
 #endif
 
-#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
-/*---------------------------------------------------------------
-                    Single Read
----------------------------------------------------------------*/
-/**
- * For chips without RTC controller, Digital controller is used to trigger an ADC single read.
- */
-#include "esp_rom_sys.h"
-#endif  //SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
-
 /*---------------------------------------------------------------
             Define all ADC DMA required operations here
 ---------------------------------------------------------------*/
@@ -190,9 +180,12 @@ static void adc_hal_digi_sample_freq_config(adc_hal_dma_ctx_t *hal, uint32_t fre
     adc_ll_digi_clk_sel(0);   //use APB
 #else
     i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_SRC_DEFAULT);    /*!< Clock from PLL_D2_CLK(160M)*/
-    uint32_t bck = I2S_BASE_CLK / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_B_DEFAULT / ADC_LL_CLKM_DIV_A_DEFAULT) / 2 / freq;
-    i2s_ll_set_raw_mclk_div(hal->dev, ADC_LL_CLKM_DIV_NUM_DEFAULT, ADC_LL_CLKM_DIV_A_DEFAULT, ADC_LL_CLKM_DIV_B_DEFAULT);
-    i2s_ll_rx_set_bck_div_num(hal->dev, bck);
+    uint32_t bclk_div = 16;
+    uint32_t bclk = freq * 2;
+    uint32_t mclk = bclk * bclk_div;
+    uint32_t mclk_div = I2S_BASE_CLK / mclk;
+    i2s_ll_rx_set_mclk(hal->dev, I2S_BASE_CLK, mclk, mclk_div);
+    i2s_ll_rx_set_bck_div_num(hal->dev, bclk_div);
 #endif
 }
 
@@ -231,13 +224,8 @@ void adc_hal_digi_controller_config(adc_hal_dma_ctx_t *hal, const adc_hal_digi_c
 
 #endif
 
-    if (cfg->conv_limit_en) {
-        adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
-        adc_ll_digi_convert_limit_enable();
-    } else {
-        adc_ll_digi_convert_limit_disable();
-    }
-
+    adc_ll_digi_convert_limit_enable(ADC_LL_DEFAULT_CONV_LIMIT_EN);
+    adc_ll_digi_set_convert_limit_num(ADC_LL_DEFAULT_CONV_LIMIT_NUM);
     adc_ll_digi_set_convert_mode(get_convert_mode(cfg->conv_mode));
 
     //clock and sample frequency
@@ -277,7 +265,7 @@ void adc_hal_digi_start(adc_hal_dma_ctx_t *hal, uint8_t *data_buf)
 
     //reset the current descriptor address
     hal->cur_desc_ptr = &hal->desc_dummy_head;
-    adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * ADC_HAL_DATA_LEN_PER_CONV, hal->desc_max_num);
+    adc_hal_digi_dma_link_descriptors(hal->rx_desc, data_buf, hal->eof_num * SOC_ADC_DIGI_DATA_BYTES_PER_CONV, hal->desc_max_num);
 
     //start DMA
     adc_dma_ll_rx_start(hal->dev, hal->dma_chan, (lldesc_t *)hal->rx_desc);
@@ -334,67 +322,3 @@ void adc_hal_digi_stop(adc_hal_dma_ctx_t *hal)
     //disconnect DMA and peripheral
     adc_ll_digi_dma_disable();
 }
-
-
-/*---------------------------------------------------------------
-                    Single Read
----------------------------------------------------------------*/
-/**
- * For chips without RTC controller, Digital controller is used to trigger an ADC single read.
- */
-
-//--------------------Single Read-------------------------------//
-static void adc_hal_onetime_start(adc_unit_t adc_n)
-{
-#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
-    (void)adc_n;
-    /**
-     * There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the
-     * ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller
-     * clock cycle.
-     *
-     * This limitation will be removed in hardware future versions.
-     *
-     */
-    uint32_t digi_clk = APB_CLK_FREQ / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1);
-    //Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough.
-    uint32_t delay = (1000 * 1000) / digi_clk + 1;
-    //3 ADC digital controller clock cycle
-    delay = delay * 3;
-    //This coefficient (8) is got from test. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed.
-    if (digi_clk >= APB_CLK_FREQ/8) {
-        delay = 0;
-    }
-
-    adc_oneshot_ll_start(false);
-    esp_rom_delay_us(delay);
-    adc_oneshot_ll_start(true);
-
-    //No need to delay here. Becuase if the start signal is not seen, there won't be a done intr.
-#else
-    adc_oneshot_ll_start(adc_n);
-#endif
-}
-
-esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, int *out_raw)
-{
-    uint32_t event = (adc_n == ADC_UNIT_1) ? ADC_LL_EVENT_ADC1_ONESHOT_DONE : ADC_LL_EVENT_ADC2_ONESHOT_DONE;
-    adc_oneshot_ll_clear_event(event);
-    adc_oneshot_ll_disable_all_unit();
-    adc_oneshot_ll_enable(adc_n);
-    adc_oneshot_ll_set_channel(adc_n, channel);
-
-    adc_hal_onetime_start(adc_n);
-    while (adc_oneshot_ll_get_event(event) != true) {
-        ;
-    }
-    *out_raw = adc_oneshot_ll_get_raw_result(adc_n);
-    if (adc_oneshot_ll_raw_check_valid(adc_n, *out_raw) == false) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    //HW workaround: when enabling periph clock, this should be false
-    adc_oneshot_ll_disable_all_unit();
-
-    return ESP_OK;
-}

Some files were not shown because too many files changed in this diff