Bläddra i källkod

Merge branch 'feature/sync_adc_changes_from_c3_to_master_last' into 'master'

adc: sync adc changes from c3 to master (last time)

Closes IDF-2694

See merge request espressif/esp-idf!12134
Michael (XIAO Xufeng) 5 år sedan
förälder
incheckning
c99e891201

+ 8 - 0
components/driver/adc_common.c

@@ -308,6 +308,10 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
     adc_hal_set_atten(ADC_NUM_1, channel, atten);
     ADC_EXIT_CRITICAL();
 
+#if SOC_ADC_HW_CALIBRATION_V1
+    adc_hal_calibration_init(ADC_NUM_1);
+#endif
+
     return ESP_OK;
 }
 
@@ -472,6 +476,10 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
     ADC2_WIFI_LOCK_RELEASE();
     ADC2_EXIT_CRITICAL();
 
+#if SOC_ADC_HW_CALIBRATION_V1
+    adc_hal_calibration_init(ADC_NUM_2);
+#endif
+
     return ESP_OK;
 }
 

+ 38 - 19
components/driver/esp32c3/adc.c

@@ -201,6 +201,9 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
     periph_module_enable(PERIPH_SARADC_MODULE);
     periph_module_enable(PERIPH_GDMA_MODULE);
 
+    adc_hal_calibration_init(ADC_NUM_1);
+    adc_hal_calibration_init(ADC_NUM_2);
+
     return ret;
 
 cleanup:
@@ -268,8 +271,6 @@ esp_err_t adc_digi_start(void)
     ADC_DIGI_LOCK_ACQUIRE();
 
     adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
-    adc_hal_init();
-
     if (s_adc_digi_ctx->use_adc1) {
         uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten);
         adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
@@ -279,6 +280,8 @@ esp_err_t adc_digi_start(void)
         adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
     }
 
+    adc_hal_init();
+
     adc_hal_arbiter_config(&config);
     adc_hal_digi_init(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
     adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
@@ -418,6 +421,8 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
     s_atten1_single[channel] = atten;
     ret = adc_digi_gpio_init(ADC_NUM_1, BIT(channel));
 
+    adc_hal_calibration_init(ADC_NUM_1);
+
     return ret;
 }
 
@@ -441,18 +446,19 @@ int adc1_get_raw(adc1_channel_t channel)
     adc_hal_digi_controller_config(&dig_cfg);
 
     adc_hal_intr_clear(ADC_EVENT_ADC1_DONE);
+
+    adc_hal_adc1_onetime_sample_enable(true);
     adc_hal_onetime_channel(ADC_NUM_1, channel);
     adc_hal_set_onetime_atten(atten);
 
     //Trigger single read.
-    adc_hal_adc1_onetime_sample_enable(true);
     adc_hal_onetime_start(&dig_cfg);
-
     while (!adc_hal_intr_get_raw(ADC_EVENT_ADC1_DONE));
+    adc_hal_single_read(ADC_NUM_1, &raw_out);
+
     adc_hal_intr_clear(ADC_EVENT_ADC1_DONE);
     adc_hal_adc1_onetime_sample_enable(false);
 
-    adc_hal_single_read(ADC_NUM_1, &raw_out);
     adc_hal_digi_deinit();
     periph_module_disable(PERIPH_SARADC_MODULE);
 
@@ -470,6 +476,8 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
     s_atten2_single[channel] = atten;
     ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
 
+    adc_hal_calibration_init(ADC_NUM_2);
+
     return ret;
 }
 
@@ -498,28 +506,26 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
     adc_hal_digi_controller_config(&dig_cfg);
 
     adc_hal_intr_clear(ADC_EVENT_ADC2_DONE);
+
+    adc_hal_adc2_onetime_sample_enable(true);
     adc_hal_onetime_channel(ADC_NUM_2, channel);
     adc_hal_set_onetime_atten(atten);
 
     //Trigger single read.
-    adc_hal_adc2_onetime_sample_enable(true);
     adc_hal_onetime_start(&dig_cfg);
-
     while (!adc_hal_intr_get_raw(ADC_EVENT_ADC2_DONE));
+    ret = adc_hal_single_read(ADC_NUM_2, raw_out);
+
     adc_hal_intr_clear(ADC_EVENT_ADC2_DONE);
     adc_hal_adc2_onetime_sample_enable(false);
 
-    ret = adc_hal_single_read(ADC_NUM_2, raw_out);
-    if (ret != ESP_OK) {
-        return ret;
-    }
     adc_hal_digi_deinit();
     periph_module_disable(PERIPH_SARADC_MODULE);
 
     ADC_DIGI_LOCK_RELEASE();
     SAC_ADC2_LOCK_RELEASE();
 
-    return ESP_OK;
+    return ret;
 }
 
 
@@ -794,7 +800,7 @@ esp_err_t adc_digi_isr_deregister(void)
                     RTC controller setting
 ---------------------------------------------------------------*/
 
-static uint16_t s_adc_cali_param[ADC_ATTEN_MAX] = {};
+static uint16_t s_adc_cali_param[ADC_UNIT_MAX][ADC_ATTEN_MAX] = {};
 
 //NOTE: according to calibration version, different types of lock may be taken during the process:
 //  1. Semaphore when reading efuse
@@ -803,8 +809,8 @@ static uint16_t s_adc_cali_param[ADC_ATTEN_MAX] = {};
 static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
 {
     const bool no_cal = false;
-    if (s_adc_cali_param[atten]) {
-        return (uint32_t)s_adc_cali_param[atten];
+    if (s_adc_cali_param[adc_n][atten]) {
+        return (uint32_t)s_adc_cali_param[adc_n][atten];
     }
 
     if (no_cal) {
@@ -813,17 +819,30 @@ static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t cha
 
     // check if we can fetch the values from eFuse.
     int version = esp_efuse_rtc_calib_get_ver();
-    assert(version == 1);
-    uint32_t init_code = esp_efuse_rtc_calib_get_init_code(version, atten);
 
-    ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
-    s_adc_cali_param[atten] = init_code;
+    uint32_t init_code = 0;
+    if (version == 1) {
+        //for calibration v1, both ADC units use the same init code (calibrated by ADC1)
+        init_code = esp_efuse_rtc_calib_get_init_code(version, atten);
+        ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code);
+        s_adc_cali_param[0][atten] = init_code;
+        s_adc_cali_param[1][atten] = init_code;
+    } else {
+        const bool internal_gnd = true;
+        ADC_ENTER_CRITICAL();
+        init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
+        ADC_EXIT_CRITICAL();
+        ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
+        s_adc_cali_param[adc_n][atten] = init_code;
+    }
+
     return init_code;
 }
 
 // Internal function to calibrate PWDET for WiFi
 esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
 {
+    adc_hal_calibration_init(adc_n);
     uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten);
     ADC_ENTER_CRITICAL();
     adc_hal_set_calibration_param(adc_n, cal_val);

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

@@ -74,6 +74,10 @@ esp_err_t adc_digi_init(void)
     adc_hal_init();
     adc_hal_arbiter_config(&config);
     ADC_EXIT_CRITICAL();
+
+    adc_hal_calibration_init(ADC_NUM_1);
+    adc_hal_calibration_init(ADC_NUM_2);
+
     return ESP_OK;
 }
 
@@ -472,6 +476,7 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a
 
 esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
 {
+    adc_hal_calibration_init(adc_n);
     uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten, false);
     ADC_ENTER_CRITICAL();
     adc_hal_set_calibration_param(adc_n, cal_val);

+ 9 - 2
components/driver/include/driver/adc2_wifi_private.h

@@ -43,14 +43,21 @@ esp_err_t adc2_wifi_acquire(void);
  */
 esp_err_t adc2_wifi_release(void);
 
-#if CONFIG_IDF_TARGET_ESP32S2
+#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
 /**
  * @brief This API help ADC2 calibration constructor be linked.
  *
  * @note  This is a private function, Don't call `adc2_cal_include` in user code.
  */
 void adc2_cal_include(void);
-#endif //CONFIG_IDF_TARGET_ESP32S2
+#else
+/**
+ * @brief There's no calibration involved on this chip.
+ *
+ * @note  This is a private function, Don't call `adc2_cal_include` in user code.
+ */
+#define adc2_cal_include()
+#endif //CONFIG_IDF_TARGET_*
 
 #ifdef __cplusplus
 }

+ 22 - 8
components/driver/test/test_adc_dma.c

@@ -175,9 +175,13 @@ TEST_CASE("test_adc_dma", "[adc][ignore][manual]")
         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);
-        TEST_ASSERT(cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP);
+        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();
@@ -201,9 +205,11 @@ TEST_CASE("test_adc_dma", "[adc][ignore][manual]")
 
         print_summary(print_figure);
 
-        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 (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());
@@ -240,9 +246,13 @@ TEST_CASE("test_adc_single", "[adc][ignore][manual]")
 
         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);
-        TEST_ASSERT(cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP);
+        if (cal_ret == ESP_ADC_CAL_VAL_EFUSE_TP) {
+            do_calibration = true;
+        }
 
 
         const int test_count = TEST_COUNT;
@@ -258,9 +268,13 @@ TEST_CASE("test_adc_single", "[adc][ignore][manual]")
             print_summary(print_figure);
             break;
         }
-        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 (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;

+ 4 - 0
components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h

@@ -50,6 +50,10 @@
 #define I2C_ULP_BG_O_DONE_FLAG_MSB 3
 #define I2C_ULP_BG_O_DONE_FLAG_LSB 3
 
+#define I2C_ULP_OCODE 4
+#define I2C_ULP_OCODE_MSB 7
+#define I2C_ULP_OCODE_LSB 0
+
 #define I2C_ULP_IR_FORCE_CODE 5
 #define I2C_ULP_IR_FORCE_CODE_MSB 6
 #define I2C_ULP_IR_FORCE_CODE_LSB 6

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

@@ -247,9 +247,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
             return result;
         }
     }
-#if CONFIG_IDF_TARGET_ESP32S2
     adc2_cal_include(); //This enables the ADC2 calibration constructor at start up.
-#endif
     esp_wifi_config_info();
     return result;
 }

+ 161 - 10
components/hal/adc_hal.c

@@ -12,8 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "soc/soc_caps.h"
 #include "hal/adc_hal.h"
 #include "hal/adc_hal_conf.h"
+#include "sdkconfig.h"
+#include <sys/param.h>
 
 
 #if CONFIG_IDF_TARGET_ESP32C3
@@ -50,6 +53,159 @@ int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value)
 }
 #endif
 
+/*---------------------------------------------------------------
+                    ADC calibration setting
+---------------------------------------------------------------*/
+#if SOC_ADC_HW_CALIBRATION_V1
+// ESP32-S2 and C3 support HW offset calibration.
+
+void adc_hal_calibration_init(adc_ll_num_t adc_n)
+{
+    adc_ll_calibration_init(adc_n);
+}
+
+static uint32_t s_previous_init_code[SOC_ADC_PERIPH_NUM] = {-1, -1};
+
+void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param)
+{
+    if (param != s_previous_init_code[adc_n]) {
+        adc_ll_set_calibration_param(adc_n, param);
+        s_previous_init_code[adc_n] = param;
+    }
+}
+
+#if CONFIG_IDF_TARGET_ESP32S2
+static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
+{
+    adc_hal_set_controller(adc_n, ADC_CTRL_RTC);    //Set controller
+
+    /* Enable/disable internal connect GND (for calibration). */
+    if (internal_gnd) {
+        adc_ll_rtc_disable_channel(adc_n);
+        adc_ll_set_atten(adc_n, 0, atten);  // Note: when disable all channel, HW auto select channel0 atten param.
+    } else {
+        adc_ll_rtc_enable_channel(adc_n, channel);
+        adc_ll_set_atten(adc_n, channel, atten);
+    }
+}
+
+static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
+{
+    adc_ll_rtc_start_convert(adc_n, channel);
+    while (adc_ll_rtc_convert_is_done(adc_n) != true);
+    return (uint32_t)adc_ll_rtc_get_convert_value(adc_n);
+}
+
+#elif CONFIG_IDF_TARGET_ESP32C3
+static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
+{
+    adc_hal_set_controller(adc_n, ADC_CTRL_DIG);    //Set controller
+
+    adc_digi_config_t dig_cfg = {
+        .conv_limit_en = 0,
+        .conv_limit_num = 250,
+        .sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
+    };
+    adc_hal_digi_controller_config(&dig_cfg);
+
+    /* Enable/disable internal connect GND (for calibration). */
+    if (internal_gnd) {
+        const int esp32c3_invalid_chan = (adc_n == ADC_NUM_1)? 0xF: 0x1;
+        adc_ll_onetime_set_channel(adc_n, esp32c3_invalid_chan);
+    } else {
+        adc_ll_onetime_set_channel(adc_n, channel);
+    }
+    adc_ll_onetime_set_atten(atten);
+    adc_hal_adc1_onetime_sample_enable((adc_n == ADC_NUM_1));
+    adc_hal_adc2_onetime_sample_enable((adc_n == ADC_NUM_2));
+}
+
+static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
+{
+    adc_ll_intr_clear(ADC_LL_INTR_ADC1_DONE | ADC_LL_INTR_ADC2_DONE);
+    adc_ll_onetime_start(false);
+    esp_rom_delay_us(5);
+    adc_ll_onetime_start(true);
+
+    while(!adc_ll_intr_get_raw(ADC_LL_INTR_ADC1_DONE | ADC_LL_INTR_ADC2_DONE));
+
+    uint32_t read_val = -1;
+    if (adc_n == ADC_NUM_1) {
+        read_val = adc_ll_adc1_read();
+    } else if (adc_n == ADC_NUM_2) {
+        read_val = adc_ll_adc2_read();
+        if (adc_ll_analysis_raw_data(adc_n, read_val)) {
+            return -1;
+        }
+    }
+    return read_val;
+}
+#endif //CONFIG_IDF_TARGET_*
+
+#define ADC_HAL_CAL_TIMES        (10)
+#define ADC_HAL_CAL_OFFSET_RANGE (4096)
+
+uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
+{
+    adc_hal_set_power_manage(ADC_POWER_SW_ON);
+
+    if (adc_n == ADC_NUM_2) {
+        adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
+        adc_hal_arbiter_config(&config);
+    }
+
+    cal_setup(adc_n, channel, atten, internal_gnd);
+
+    adc_ll_calibration_prepare(adc_n, channel, internal_gnd);
+
+    uint32_t code_list[ADC_HAL_CAL_TIMES] = {0};
+    uint32_t code_sum = 0;
+    uint32_t code_h = 0;
+    uint32_t code_l = 0;
+    uint32_t chk_code = 0;
+
+    for (uint8_t rpt = 0 ; rpt < ADC_HAL_CAL_TIMES ; rpt ++) {
+        code_h = ADC_HAL_CAL_OFFSET_RANGE;
+        code_l = 0;
+        chk_code = (code_h + code_l) / 2;
+        adc_ll_set_calibration_param(adc_n, chk_code);
+        uint32_t self_cal = read_cal_channel(adc_n, channel);
+        while (code_h - code_l > 1) {
+            if (self_cal == 0) {
+                code_h = chk_code;
+            } else {
+                code_l = chk_code;
+            }
+            chk_code = (code_h + code_l) / 2;
+            adc_ll_set_calibration_param(adc_n, chk_code);
+            self_cal = read_cal_channel(adc_n, channel);
+            if ((code_h - code_l == 1)) {
+                chk_code += 1;
+                adc_ll_set_calibration_param(adc_n, chk_code);
+                self_cal = read_cal_channel(adc_n, channel);
+            }
+        }
+        code_list[rpt] = chk_code;
+        code_sum += chk_code;
+    }
+
+    code_l = code_list[0];
+    code_h = code_list[0];
+    for (uint8_t i = 0 ; i < ADC_HAL_CAL_TIMES ; i++) {
+        code_l = MIN(code_l, code_list[i]);
+        code_h = MAX(code_h, code_list[i]);
+    }
+
+    chk_code = code_h + code_l;
+    uint32_t ret = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4)
+           ? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2)
+           : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
+
+    adc_ll_calibration_finish(adc_n);
+    return ret;
+}
+#endif //SOC_ADC_HW_CALIBRATION_V1
+
 #if CONFIG_IDF_TARGET_ESP32C3
 //This feature is currently supported on ESP32C3, will be supported on other chips soon
 /*---------------------------------------------------------------
@@ -130,6 +286,9 @@ void adc_hal_digi_init(adc_dma_hal_context_t *adc_dma_ctx, adc_dma_hal_config_t
     gdma_ll_enable_clock(adc_dma_ctx->dev, true);
     gdma_ll_clear_interrupt_status(adc_dma_ctx->dev, dma_config->dma_chan, UINT32_MAX);
     gdma_ll_rx_connect_to_periph(adc_dma_ctx->dev, dma_config->dma_chan, SOC_GDMA_TRIG_PERIPH_ADC0);
+
+    adc_ll_adc1_onetime_sample_enable(false);
+    adc_ll_adc2_onetime_sample_enable(false);
 }
 
 /*---------------------------------------------------------------
@@ -163,20 +322,12 @@ void adc_hal_onetime_start(adc_digi_config_t *adc_digi_config)
 
 void adc_hal_adc1_onetime_sample_enable(bool enable)
 {
-    if (enable) {
-        adc_ll_adc1_onetime_sample_ena();
-    } else {
-        adc_ll_adc1_onetime_sample_dis();
-    }
+    adc_ll_adc1_onetime_sample_enable(enable);
 }
 
 void adc_hal_adc2_onetime_sample_enable(bool enable)
 {
-    if (enable) {
-        adc_ll_adc2_onetime_sample_ena();
-    } else {
-        adc_ll_adc2_onetime_sample_dis();
-    }
+    adc_ll_adc2_onetime_sample_enable(enable);
 }
 
 void adc_hal_onetime_channel(adc_ll_num_t unit, adc_channel_t channel)

+ 1 - 2
components/hal/esp32/include/hal/adc_ll.h

@@ -299,9 +299,8 @@ static inline void adc_ll_rtc_enable_channel(adc_ll_num_t adc_n, int channel)
  * @note Only one channel can be selected in once measurement.
  *
  * @param adc_n ADC unit.
- * @param channel ADC channel number for each ADCn.
  */
-static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n, int channel)
+static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n)
 {
     if (adc_n == ADC_NUM_1) {
         SENS.sar_meas_start1.sar1_en_pad = 0; //only one channel is selected.

+ 0 - 14
components/hal/esp32c3/include/hal/adc_hal.h

@@ -206,20 +206,6 @@ void adc_hal_digi_monitor_enable(adc_digi_monitor_idx_t mon_idx, bool enable);
  */
 void adc_hal_arbiter_config(adc_arbiter_t *config);
 
-/*---------------------------------------------------------------
-                    ADC calibration setting
----------------------------------------------------------------*/
-
-
-/**
- * Set the calibration result (initial data) to ADC.
- *
- * @note  Different ADC units and different attenuation options use different calibration data (initial data).
- *
- * @param adc_n ADC index number.
- */
-#define adc_hal_set_calibration_param(adc_n, param) adc_ll_set_calibration_param(adc_n, param);
-
 #ifdef __cplusplus
 }
 #endif

+ 15 - 19
components/hal/esp32c3/include/hal/adc_ll.h

@@ -738,6 +738,17 @@ static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig,
 }
 
 /* ADC calibration code. */
+/**
+ * @brief Set common calibration configuration. Should be shared with other parts (PWDET).
+ */
+static inline void adc_ll_calibration_init(adc_ll_num_t adc_n)
+{
+    if (adc_n == ADC_NUM_1) {
+        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 1);
+    } else {
+        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 1);
+    }
+}
 
 /**
  * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration.
@@ -751,19 +762,14 @@ static inline void adc_ll_set_arbiter_priority(uint8_t pri_rtc, uint8_t pri_dig,
  */
 static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd)
 {
-    /* Should be called before writing I2C registers. */
-    SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU);
-
     /* Enable/disable internal connect GND (for calibration). */
     if (adc_n == ADC_NUM_1) {
-        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 4);
         if (internal_gnd) {
             REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1);
         } else {
             REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0);
         }
     } else {
-        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 4);
         if (internal_gnd) {
             REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1);
         } else {
@@ -912,14 +918,9 @@ static inline bool adc_ll_intr_get_status(adc_ll_intr_t mask)
 }
 
 //--------------------------------adc1------------------------------//
-static inline void adc_ll_adc1_onetime_sample_ena(void)
-{
-    APB_SARADC.onetime_sample.adc1_onetime_sample = 1;
-}
-
-static inline void adc_ll_adc1_onetime_sample_dis(void)
+static inline void adc_ll_adc1_onetime_sample_enable(bool enable)
 {
-    APB_SARADC.onetime_sample.adc1_onetime_sample = 0;
+    APB_SARADC.onetime_sample.adc1_onetime_sample = enable;
 }
 
 static inline uint32_t adc_ll_adc1_read(void)
@@ -929,14 +930,9 @@ static inline uint32_t adc_ll_adc1_read(void)
 }
 
 //--------------------------------adc2------------------------------//
-static inline void adc_ll_adc2_onetime_sample_ena(void)
-{
-    APB_SARADC.onetime_sample.adc2_onetime_sample = 1;
-}
-
-static inline void adc_ll_adc2_onetime_sample_dis(void)
+static inline void adc_ll_adc2_onetime_sample_enable(bool enable)
 {
-    APB_SARADC.onetime_sample.adc2_onetime_sample = 0;
+    APB_SARADC.onetime_sample.adc2_onetime_sample = enable;
 }
 
 static inline uint32_t adc_ll_adc2_read(void)

+ 0 - 83
components/hal/esp32s2/adc_hal.c

@@ -146,86 +146,3 @@ void adc_hal_arbiter_config(adc_arbiter_t *config)
     adc_ll_set_arbiter_work_mode(config->mode);
     adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri);
 }
-
-/*---------------------------------------------------------------
-                    ADC calibration setting
----------------------------------------------------------------*/
-#define ADC_HAL_CAL_TIMES        (10)
-#define ADC_HAL_CAL_OFFSET_RANGE (4096)
-
-static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
-{
-    adc_ll_rtc_start_convert(adc_n, channel);
-    while (adc_ll_rtc_convert_is_done(adc_n) != true);
-    return (uint32_t)adc_ll_rtc_get_convert_value(adc_n);
-}
-
-uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
-{
-    adc_hal_set_power_manage(ADC_POWER_SW_ON);
-
-    if (adc_n == ADC_NUM_2) {
-        adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
-        adc_hal_arbiter_config(&config);
-    }
-    adc_hal_set_controller(adc_n, ADC_CTRL_RTC);    //Set controller
-
-
-    adc_ll_calibration_prepare(adc_n, channel, internal_gnd);
-    /* Enable/disable internal connect GND (for calibration). */
-    if (internal_gnd) {
-        adc_ll_rtc_disable_channel(adc_n, channel);
-        adc_ll_set_atten(adc_n, 0, atten);  // Note: when disable all channel, HW auto select channel0 atten param.
-    } else {
-        adc_ll_rtc_enable_channel(adc_n, channel);
-        adc_ll_set_atten(adc_n, channel, atten);
-    }
-
-    uint32_t code_list[ADC_HAL_CAL_TIMES] = {0};
-    uint32_t code_sum = 0;
-    uint32_t code_h = 0;
-    uint32_t code_l = 0;
-    uint32_t chk_code = 0;
-
-    for (uint8_t rpt = 0 ; rpt < ADC_HAL_CAL_TIMES ; rpt ++) {
-        code_h = ADC_HAL_CAL_OFFSET_RANGE;
-        code_l = 0;
-        chk_code = (code_h + code_l) / 2;
-        adc_ll_set_calibration_param(adc_n, chk_code);
-        uint32_t self_cal = read_cal_channel(adc_n, channel);
-        while (code_h - code_l > 1) {
-            if (self_cal == 0) {
-                code_h = chk_code;
-            } else {
-                code_l = chk_code;
-            }
-            chk_code = (code_h + code_l) / 2;
-            adc_ll_set_calibration_param(adc_n, chk_code);
-            self_cal = read_cal_channel(adc_n, channel);
-            if ((code_h - code_l == 1)) {
-                chk_code += 1;
-                adc_ll_set_calibration_param(adc_n, chk_code);
-                self_cal = read_cal_channel(adc_n, channel);
-            }
-        }
-        code_list[rpt] = chk_code;
-        code_sum += chk_code;
-    }
-    code_l = code_list[0];
-    code_h = code_list[0];
-    for (uint8_t i = 0 ; i < ADC_HAL_CAL_TIMES ; i++) {
-        if (code_l > code_list[i]) {
-            code_l = code_list[i];
-        }
-        if (code_h < code_list[i]) {
-            code_h = code_list[i];
-        }
-    }
-    chk_code = code_h + code_l;
-    uint32_t ret = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4)
-           ? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2)
-           : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
-
-    adc_ll_calibration_finish(adc_n);
-    return ret;
-}

+ 0 - 29
components/hal/esp32s2/include/hal/adc_hal.h

@@ -214,35 +214,6 @@ void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config)
  */
 void adc_hal_arbiter_config(adc_arbiter_t *config);
 
-/*---------------------------------------------------------------
-                    ADC calibration setting
----------------------------------------------------------------*/
-
-/**
- * Calibrate the ADC using internal connections.
- *
- * @note  Different ADC units and different attenuation options use different calibration data (initial data).
- *
- * @param adc_n ADC index number.
- * @param channel adc channel number.
- * @param atten The attenuation for the channel
- * @param internal_gnd true:  Disconnect from the IO port and use the internal GND as the calibration voltage.
- *                     false: Use IO external voltage as calibration voltage.
- *
- * @return
- *      - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set.
- */
-uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd);
-
-/**
- * Set the calibration result (initial data) to ADC.
- *
- * @note  Different ADC units and different attenuation options use different calibration data (initial data).
- *
- * @param adc_n ADC index number.
- */
-#define adc_hal_set_calibration_param(adc_n, param) adc_ll_set_calibration_param(adc_n, param);
-
 #ifdef __cplusplus
 }
 #endif

+ 13 - 3
components/hal/esp32s2/include/hal/adc_ll.h

@@ -690,7 +690,7 @@ static inline void adc_ll_rtc_enable_channel(adc_ll_num_t adc_n, int channel)
  * @param adc_n ADC unit.
  * @param channel ADC channel number for each ADCn.
  */
-static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n, int channel)
+static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n)
 {
     if (adc_n == ADC_NUM_1) {
         SENS.sar_meas1_ctrl2.sar1_en_pad = 0; //only one channel is selected.
@@ -1123,6 +1123,18 @@ static inline void adc_ll_disable_sleep_controller(void)
 }
 
 /* ADC calibration code. */
+/**
+ * @brief Set common calibration configuration. Should be shared with other parts (PWDET).
+ */
+static inline void adc_ll_calibration_init(adc_ll_num_t adc_n)
+{
+    if (adc_n == ADC_NUM_1) {
+        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 4);
+    } else {
+        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 4);
+    }
+}
+
 /**
  * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration.
  *
@@ -1143,14 +1155,12 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t
 
     /* Enable/disable internal connect GND (for calibration). */
     if (adc_n == ADC_NUM_1) {
-        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 4);
         if (internal_gnd) {
             REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1);
         } else {
             REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0);
         }
     } else {
-        REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 4);
         if (internal_gnd) {
             REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1);
         } else {

+ 1 - 1
components/hal/esp32s3/include/hal/adc_ll.h

@@ -606,7 +606,7 @@ static inline void adc_ll_rtc_enable_channel(adc_ll_num_t adc_n, int channel)
  * @param adc_n ADC unit.
  * @param channel ADC channel number for each ADCn.
  */
-static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n, int channel)
+static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n)
 {
     if (adc_n == ADC_NUM_1) {
         SENS.sar_meas1_ctrl2.sar1_en_pad = 0; //only one channel is selected.

+ 42 - 0
components/hal/include/hal/adc_hal.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "soc/soc_caps.h"
 #include "hal/adc_types.h"
 #include "hal/adc_ll.h"
 
@@ -206,6 +207,47 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
  */
 #define adc_hal_digi_clear_pattern_table(adc_n) adc_ll_digi_clear_pattern_table(adc_n)
 
+/*---------------------------------------------------------------
+                    ADC calibration setting
+---------------------------------------------------------------*/
+#if SOC_ADC_HW_CALIBRATION_V1
+// ESP32-S2 and C3 support HW offset calibration.
+
+/**
+ * @brief Initialize default parameter for the calibration block.
+ *
+ * @param adc_n ADC index numer
+ */
+void adc_hal_calibration_init(adc_ll_num_t adc_n);
+
+/**
+ * Set the calibration result (initial data) to ADC.
+ *
+ * @note  Different ADC units and different attenuation options use different calibration data (initial data).
+ *
+ * @param adc_n ADC index number.
+ * @param param the calibration parameter to configure
+ */
+void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param);
+
+/**
+ * Calibrate the ADC using internal connections.
+ *
+ * @note  Different ADC units and different attenuation options use different calibration data (initial data).
+ *
+ * @param adc_n ADC index number.
+ * @param channel adc channel number.
+ * @param atten The attenuation for the channel
+ * @param internal_gnd true:  Disconnect from the IO port and use the internal GND as the calibration voltage.
+ *                     false: Use IO external voltage as calibration voltage.
+ *
+ * @return
+ *      - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set.
+ */
+uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd);
+
+#endif //SOC_ADC_HW_CALIBRATION_V1
+
 #if CONFIG_IDF_TARGET_ESP32C3
 /*---------------------------------------------------------------
                     DMA setting

+ 1 - 0
components/soc/esp32c3/include/soc/soc_caps.h

@@ -109,6 +109,7 @@
 #define SOC_ADC_MAX_BITWIDTH                    (12)
 #define SOC_ADC_DIGI_FILTER_NUM                 (2)
 #define SOC_ADC_DIGI_MONITOR_NUM                (2)
+#define SOC_ADC_HW_CALIBRATION_V1               (1) /*!< support HW offset calibration */
 #define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM)    1
 //F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
 #define SOC_ADC_SAMPLE_FREQ_THRES_HIGH          83333

+ 2 - 0
components/soc/esp32s2/include/soc/soc_caps.h

@@ -58,6 +58,8 @@
 #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10)
 #define SOC_ADC_MAX_CHANNEL_NUM         (10)
 #define SOC_ADC_MAX_BITWIDTH            (13)
+#define SOC_ADC_HW_CALIBRATION_V1       (1) /*!< support HW offset calibration */
+
 
 /**
  * Check if adc support digital controller (DMA) mode.