From 04d6b115ae8242dd4c3a1b3c1a12aa03b0570ffc Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Tue, 8 Dec 2020 15:51:27 +0800 Subject: [PATCH] adc: fixed efuse called in critical section issue --- components/driver/adc_common.c | 39 ++++-- components/driver/esp32s2/adc.c | 65 +++++++++ components/driver/esp32s2/adc2_init_cal.c | 6 +- components/hal/esp32c3/adc_hal.c | 53 +++----- components/hal/esp32c3/include/hal/adc_hal.h | 7 +- components/hal/esp32s2/adc_hal.c | 135 +++++++------------ components/hal/esp32s2/include/hal/adc_hal.h | 7 +- components/hal/esp32s3/include/hal/adc_hal.h | 7 +- components/hal/esp32s3/include/hal/adc_ll.h | 2 - 9 files changed, 172 insertions(+), 149 deletions(-) diff --git a/components/driver/adc_common.c b/components/driver/adc_common.c index d3263a20b2..0f5809961d 100644 --- a/components/driver/adc_common.c +++ b/components/driver/adc_common.c @@ -121,6 +121,16 @@ static esp_pm_lock_handle_t s_adc2_arbiter_lock; ADC Common ---------------------------------------------------------------*/ +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 +static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan) +{ + adc_atten_t atten = adc_hal_get_atten(adc_n, chan); + + extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool no_cal); + return adc_get_calibration_offset(adc_n, chan, atten, false); +} +#endif + void adc_power_acquire(void) { bool powered_on = false; @@ -269,13 +279,6 @@ esp_err_t adc_rtc_reset(void) ADC_EXIT_CRITICAL(); return ESP_OK; } - -static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel) -{ - adc_atten_t atten = adc_hal_get_atten(adc_n, channel); - uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false); - adc_hal_set_calibration_param(adc_n, cal_val); -} #endif /*------------------------------------------------------------------------------------- @@ -369,20 +372,25 @@ int adc1_get_raw(adc1_channel_t channel) adc1_rtc_mode_acquire(); adc_power_acquire(); +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 + // Get calibration value before going into critical section + uint32_t cal_val = get_calibration_offset(ADC_NUM_1, channel); +#endif + ADC_ENTER_CRITICAL(); #ifdef CONFIG_IDF_TARGET_ESP32 adc_hal_hall_disable(); //Disable other peripherals. adc_hal_amp_disable(); //Currently the LNA is not open, close it by default. #endif -#if !CONFIG_IDF_TARGET_ESP32 - adc_set_init_code(ADC_NUM_1, channel); // calibration for adc +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 + adc_hal_set_calibration_param(ADC_NUM_1, cal_val); #endif adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); //Set controller adc_hal_convert(ADC_NUM_1, channel, &adc_value); //Start conversion, For ADC1, the data always valid. - ADC_EXIT_CRITICAL(); #if !CONFIG_IDF_TARGET_ESP32 adc_hal_rtc_reset(); //Reset FSM of rtc controller #endif + ADC_EXIT_CRITICAL(); adc_power_release(); adc1_lock_release(); @@ -520,6 +528,11 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * adc_power_acquire(); //in critical section with whole rtc module +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 + // Get calibration value before going into critical section + uint32_t cal_val = get_calibration_offset(ADC_NUM_2, channel); +#endif + ADC2_ENTER_CRITICAL(); //avoid collision with other tasks if ( ADC2_WIFI_LOCK_TRY_ACQUIRE() == -1 ) { //try the lock, return if failed (wifi using). @@ -532,7 +545,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * #endif adc2_config_width(width_bit); // in critical section with whole rtc module. because the PWDET use the same registers, place it here. #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 - adc_set_init_code(ADC_NUM_2, channel); // calibration for adc + adc_hal_set_calibration_param(ADC_NUM_2, cal_val); #endif adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);// set controller @@ -557,12 +570,12 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * #endif //CONFIG_PM_ENABLE #endif //CONFIG_IDF_TARGET_ESP32 - ADC2_WIFI_LOCK_RELEASE(); - ADC2_EXIT_CRITICAL(); #if !CONFIG_IDF_TARGET_ESP32 adc_rtc_reset(); #endif + ADC2_WIFI_LOCK_RELEASE(); + ADC2_EXIT_CRITICAL(); if (adc_value < 0) { ESP_LOGD( ADC_TAG, "ADC2 ARB: Return data is invalid." ); diff --git a/components/driver/esp32s2/adc.c b/components/driver/esp32s2/adc.c index 5c2e22b7c3..2422989fb7 100644 --- a/components/driver/esp32s2/adc.c +++ b/components/driver/esp32s2/adc.c @@ -29,6 +29,7 @@ #include "driver/rtc_cntl.h" #include "driver/gpio.h" #include "driver/adc.h" +#include "esp32s2/esp_efuse_rtc_table.h" #include "hal/adc_types.h" #include "hal/adc_hal.h" @@ -61,6 +62,8 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi static esp_pm_lock_handle_t s_adc_digi_arbiter_lock = NULL; #endif //CONFIG_PM_ENABLE +esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten); + /*--------------------------------------------------------------- Digital controller setting ---------------------------------------------------------------*/ @@ -106,6 +109,17 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config) } #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_NUM_1, config->adc1_pattern[i].channel, 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_NUM_2, config->adc2_pattern[i].channel, config->adc2_pattern[i].atten); + } + } + ADC_ENTER_CRITICAL(); adc_hal_digi_controller_config(config); ADC_EXIT_CRITICAL(); @@ -413,3 +427,54 @@ esp_err_t adc_digi_isr_deregister(void) /*--------------------------------------------------------------- RTC controller setting ---------------------------------------------------------------*/ + +/*--------------------------------------------------------------- + Calibration +---------------------------------------------------------------*/ + +static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} }; + +//NOTE: according to calibration version, different types of lock may be taken during the process: +// 1. Semaphore when reading efuse +// 2. Spinlock when actually doing ADC calibration +//This function shoudn't be called inside critical section or ISR +uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool no_cal) +{ +#ifdef CONFIG_IDF_ENV_FPGA + return 0; +#endif + + 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]; + } + + if (no_cal) { + return 0; //indicating failure + } + + uint32_t dout = 0; + // check if we can fetch the values from eFuse. + int version = esp_efuse_rtc_table_read_calib_version(); + if (version == 2) { + int tag = esp_efuse_rtc_table_get_tag(version, adc_n + 1, atten, RTCCALIB_V2_PARAM_VINIT); + dout = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false); + } else { + const bool internal_gnd = true; + ADC_ENTER_CRITICAL(); + dout = 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, dout); + s_adc_cali_param[adc_n][atten] = (uint16_t)dout; + return dout; +} + +esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) +{ + 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); + ADC_EXIT_CRITICAL(); + return ESP_OK; +} diff --git a/components/driver/esp32s2/adc2_init_cal.c b/components/driver/esp32s2/adc2_init_cal.c index ee2653b959..1968cfd49e 100644 --- a/components/driver/esp32s2/adc2_init_cal.c +++ b/components/driver/esp32s2/adc2_init_cal.c @@ -25,7 +25,11 @@ Don't put any other code into this file. */ */ static __attribute__((constructor)) void adc2_init_code_calibration(void) { - adc_hal_set_calibration_param(ADC_NUM_2, adc_hal_calibration(ADC_NUM_2, 0, ADC_ATTEN_DB_11, true, false)); + const adc_ll_num_t adc_n = ADC_NUM_2; + const adc_atten_t atten = ADC_ATTEN_DB_11; + const adc_channel_t channel = 0; + extern esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten); + adc_cal_offset(adc_n, channel, atten); } /** Don't call `adc2_cal_include` in user code. */ diff --git a/components/hal/esp32c3/adc_hal.c b/components/hal/esp32c3/adc_hal.c index 3bfffeeebd..bf48c033bd 100644 --- a/components/hal/esp32c3/adc_hal.c +++ b/components/hal/esp32c3/adc_hal.c @@ -40,12 +40,6 @@ void adc_hal_digi_deinit(void) adc_hal_deinit(); } -static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ - uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false); - adc_hal_set_calibration_param(adc_n, cal_val); -} - void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) { /* If enable digtal controller, adc xpd should always on. */ @@ -58,7 +52,6 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); for (int i = 0; i < cfg->adc1_pattern_len; i++) { adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); - adc_set_init_code(ADC_NUM_1, cfg->adc1_pattern[i].channel, cfg->adc1_pattern[i].atten); } } } @@ -68,7 +61,6 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); for (int i = 0; i < cfg->adc2_pattern_len; i++) { adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); - adc_set_init_code(ADC_NUM_2, cfg->adc2_pattern[i].channel, cfg->adc2_pattern[i].atten); } } } @@ -162,44 +154,27 @@ void adc_hal_arbiter_config(adc_arbiter_t *config) /*--------------------------------------------------------------- ADC calibration setting ---------------------------------------------------------------*/ - -#define ADC_HAL_CAL_OFFSET_RANGE (4096) #define ADC_HAL_CAL_TIMES (10) +#define ADC_HAL_CAL_OFFSET_RANGE (4096) -static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} }; - -static uint32_t adc_hal_read_self_cal(adc_ll_num_t adc_n, int channel) +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_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal) +uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { - if (!force_cal) { - if (s_adc_cali_param[adc_n][atten]) { - return (uint32_t)s_adc_cali_param[adc_n][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; - uint32_t dout = 0; - 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_hal_arbiter_config(adc_arbiter_t *config) 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); @@ -209,25 +184,31 @@ uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atte 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); - dout = adc_hal_read_self_cal(adc_n, channel); + uint32_t self_cal = read_cal_channel(adc_n, channel); while (code_h - code_l > 1) { - if (dout == 0) { + 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); - dout = adc_hal_read_self_cal(adc_n, channel); + 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); - dout = adc_hal_read_self_cal(adc_n, channel); + self_cal = read_cal_channel(adc_n, channel); } } code_list[rpt] = chk_code; @@ -244,12 +225,10 @@ uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atte } } chk_code = code_h + code_l; - dout = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4) + 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_set_calibration_param(adc_n, dout); adc_ll_calibration_finish(adc_n); - s_adc_cali_param[adc_n][atten] = (uint16_t)dout; - return dout; + return ret; } diff --git a/components/hal/esp32c3/include/hal/adc_hal.h b/components/hal/esp32c3/include/hal/adc_hal.h index 5010400b57..962528b4ab 100644 --- a/components/hal/esp32c3/include/hal/adc_hal.h +++ b/components/hal/esp32c3/include/hal/adc_hal.h @@ -232,21 +232,20 @@ void adc_hal_arbiter_config(adc_arbiter_t *config); ---------------------------------------------------------------*/ /** - * Calibrate the ADC according to the parameters. + * 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. - * @param force_cal true: Do not use the results that have already been verified, and perform the verification again. It will take a long time. - * false: Use the result of the last calibration. * * @return * - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set. */ -uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal); +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. diff --git a/components/hal/esp32s2/adc_hal.c b/components/hal/esp32s2/adc_hal.c index 588d01bd7d..5797b677d7 100644 --- a/components/hal/esp32s2/adc_hal.c +++ b/components/hal/esp32s2/adc_hal.c @@ -19,7 +19,6 @@ #include "hal/adc_types.h" #include "hal/adc_hal_conf.h" #include "esp_log.h" -#include "esp32s2/esp_efuse_rtc_table.h" /*--------------------------------------------------------------- Digital controller setting @@ -44,12 +43,6 @@ void adc_hal_digi_deinit(void) adc_hal_deinit(); } -static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) -{ - uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false); - adc_hal_set_calibration_param(adc_n, cal_val); -} - void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) { /* If enable digtal controller, adc xpd should always on. */ @@ -62,7 +55,6 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len); for (int i = 0; i < cfg->adc1_pattern_len; i++) { adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]); - adc_set_init_code(ADC_NUM_1, cfg->adc1_pattern[i].channel, cfg->adc1_pattern[i].atten); } } } @@ -72,7 +64,6 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg) adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len); for (int i = 0; i < cfg->adc2_pattern_len; i++) { adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]); - adc_set_init_code(ADC_NUM_2, cfg->adc2_pattern[i].channel, cfg->adc2_pattern[i].atten); } } } @@ -166,106 +157,82 @@ void adc_hal_arbiter_config(adc_arbiter_t *config) /*--------------------------------------------------------------- ADC calibration setting ---------------------------------------------------------------*/ - -#define ADC_HAL_CAL_OFFSET_RANGE (4096) #define ADC_HAL_CAL_TIMES (10) +#define ADC_HAL_CAL_OFFSET_RANGE (4096) -static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} }; - -static uint32_t adc_hal_read_self_cal(adc_ll_num_t adc_n, int channel) +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_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal) +uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { -#ifdef CONFIG_IDF_ENV_FPGA - return 0; -#endif - - if (!force_cal) { - if (s_adc_cali_param[adc_n][atten]) { - return (uint32_t)s_adc_cali_param[adc_n][atten]; - } - } - 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_hal_arbiter_config(adc_arbiter_t *config) + adc_ll_calibration_prepare(adc_n, channel, internal_gnd); - - uint32_t dout = 0; - // check if we can fetch the values from eFuse. - int version = esp_efuse_rtc_table_read_calib_version(); - if (version == 2) { - int tag = esp_efuse_rtc_table_get_tag(version, adc_n + 1, atten, RTCCALIB_V2_PARAM_VINIT); - dout = esp_efuse_rtc_table_get_parsed_efuse_value(tag, false); + /* 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 { - 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; + adc_ll_rtc_enable_channel(adc_n, channel); + adc_ll_set_atten(adc_n, channel, atten); + } - /* 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; + 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); - dout = adc_hal_read_self_cal(adc_n, channel); - while (code_h - code_l > 1) { - if (dout == 0) { - code_h = chk_code; - } else { - code_l = chk_code; - } - chk_code = (code_h + code_l) / 2; + 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); - dout = adc_hal_read_self_cal(adc_n, channel); - if ((code_h - code_l == 1)) { - chk_code += 1; - adc_ll_set_calibration_param(adc_n, chk_code); - dout = adc_hal_read_self_cal(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]; + self_cal = read_cal_channel(adc_n, channel); } } - chk_code = code_h + code_l; - dout = ((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; + code_list[rpt] = chk_code; + code_sum += chk_code; } - adc_ll_set_calibration_param(adc_n, dout); - adc_ll_calibration_finish(adc_n); - s_adc_cali_param[adc_n][atten] = (uint16_t)dout; + 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; - return dout; + adc_ll_calibration_finish(adc_n); + return ret; } diff --git a/components/hal/esp32s2/include/hal/adc_hal.h b/components/hal/esp32s2/include/hal/adc_hal.h index c8fe441235..d72f94cce7 100644 --- a/components/hal/esp32s2/include/hal/adc_hal.h +++ b/components/hal/esp32s2/include/hal/adc_hal.h @@ -219,21 +219,20 @@ void adc_hal_arbiter_config(adc_arbiter_t *config); ---------------------------------------------------------------*/ /** - * Calibrate the ADC according to the parameters. + * 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. - * @param force_cal true: Do not use the results that have already been verified, and perform the verification again. It will take a long time(~40us). - * false: Use the result of the last calibration. Return immediately. * * @return * - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set. */ -uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal); +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. diff --git a/components/hal/esp32s3/include/hal/adc_hal.h b/components/hal/esp32s3/include/hal/adc_hal.h index 53e32ebdff..1eaf7e72b8 100644 --- a/components/hal/esp32s3/include/hal/adc_hal.h +++ b/components/hal/esp32s3/include/hal/adc_hal.h @@ -232,21 +232,20 @@ void adc_hal_arbiter_config(adc_arbiter_t *config); ---------------------------------------------------------------*/ /** - * Calibrate the ADC according to the parameters. + * 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. - * @param force_cal true: Do not use the results that have already been verified, and perform the verification again. It will take a long time. - * false: Use the result of the last calibration. * * @return * - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set. */ -uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal); +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. diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 08816ab92a..8a79ea6f0e 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -1053,8 +1053,6 @@ static inline void adc_ll_disable_sleep_controller(void) #define SAR2_DREF_ADDR_MSB 0x6 #define SAR2_DREF_ADDR_LSB 0x4 -#define ADC_HAL_CAL_OFFSET_RANGE (4096) -#define ADC_HAL_CAL_TIMES (10) /** * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration.