diff --git a/components/driver/adc_common.c b/components/driver/adc_common.c index 5c0b6f4d24..8cc8e434df 100644 --- a/components/driver/adc_common.c +++ b/components/driver/adc_common.c @@ -247,11 +247,16 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a uint32_t init_code = 0; if (version == 1) { init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten); - s_adc_cali_param[adc_n][atten] = init_code; } else { - ESP_LOGW(ADC_TAG, "Calibration eFuse is not configured, skip calibration"); + ESP_LOGV(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode"); + adc_power_acquire(); + RTC_ENTER_CRITICAL(); + const bool internal_gnd = true; + init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd); + RTC_EXIT_CRITICAL(); + adc_power_release(); } - + s_adc_cali_param[adc_n][atten] = init_code; return s_adc_cali_param[adc_n][atten]; } #elif CONFIG_IDF_TARGET_ESP32S2 diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h index bb39d2c813..4224e92dcf 100644 --- a/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h @@ -18,6 +18,14 @@ #define I2C_SAR_ADC 0X69 #define I2C_SAR_ADC_HOSTID 0 +#define ADC_SAR1_ENCAL_GND_ADDR 0x7 +#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5 +#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5 + +#define ADC_SAR2_ENCAL_GND_ADDR 0x7 +#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7 +#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7 + #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0 diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 2f1b4c8c01..bf38b76edb 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -71,10 +71,14 @@ void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) } } -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { +#if CONFIG_IDF_TARGET_ESP32S2 adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller +#else + adc_hal_set_controller(adc_n, ADC_LL_CTRL_ARB); //Set controller +#endif /* Enable/disable internal connect GND (for calibration). */ if (internal_gnd) { @@ -134,7 +138,6 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel) #define ADC_HAL_CAL_TIMES (10) #define ADC_HAL_CAL_OFFSET_RANGE (4096) -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { if (adc_n == ADC_NUM_2) { @@ -190,9 +193,9 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1; adc_ll_calibration_finish(adc_n); + return ret; } -#endif //#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 #endif //SOC_ADC_CALIBRATION_V1_SUPPORTED #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 0be475931b..778e9d8d78 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -129,8 +129,12 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa */ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) { - //To be added including RTC_CNTR reg and functions - abort(); + /* Should be called before writing I2C registers. */ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M); + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); + + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle); } /** @@ -720,16 +724,32 @@ static inline void adc_ll_calibration_init(adc_ll_num_t adc_n) /** * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration. * - * @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 channel Not used * @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. */ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd) { - abort(); + /* Should be called before writing I2C registers. */ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M); + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); + + /* Enable/disable internal connect GND (for calibration). */ + if (adc_n == ADC_NUM_1) { + 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 { //adc_n == ADC_NUM_2 + if (internal_gnd) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + } + } } /** @@ -739,7 +759,11 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t */ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) { - abort(); + if (adc_n == ADC_NUM_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + } else { //adc_n == ADC_NUM_2 + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + } } /** diff --git a/examples/peripherals/adc/single_read/single_read/main/single_read.c b/examples/peripherals/adc/single_read/single_read/main/single_read.c index 7f8e97abf5..2a567d0682 100644 --- a/examples/peripherals/adc/single_read/single_read/main/single_read.c +++ b/examples/peripherals/adc/single_read/single_read/main/single_read.c @@ -54,9 +54,9 @@ static bool adc_calibration_init(void) ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME); if (ret == ESP_ERR_NOT_SUPPORTED) { - ESP_LOGW(TAG, "Calibration scheme not supported, skip calibration"); + ESP_LOGW(TAG, "Calibration scheme not supported, skip software calibration"); } else if (ret == ESP_ERR_INVALID_VERSION) { - ESP_LOGW(TAG, "eFuse not burnt, skip calibration"); + 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_EXAMPLE_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);