diff --git a/components/driver/test/test_adc.c b/components/driver/test/test_adc.c index 17b5a2684b..460a2cb28c 100644 --- a/components/driver/test/test_adc.c +++ b/components/driver/test/test_adc.c @@ -9,19 +9,13 @@ #include #include "esp_log.h" #include "test_utils.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -// TODO: Support ADC IDF-3908 #include "esp_adc_cal.h" -#include "driver/adc.h" +#include "driver/adc_common.h" -static const char *TAG = "ADC"; +__attribute__((unused)) static const char *TAG = "ADC"; - -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3) //TODO: IDF-3160 -//API only supported for C3 now. - -#include "esp_adc_cal.h" -#include "esp_log.h" +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2) +//TODO: IDF-3160 #define TEST_COUNT 4096 #define MAX_ARRAY_SIZE 4096 @@ -282,12 +276,10 @@ TEST_CASE("test_adc_single", "[adc][ignore][manual]") } } -#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) - - - +#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) //TODO IDF-3908 /******************************************************************************** * ADC Speed Related Tests @@ -400,4 +392,222 @@ TEST_CASE("test_adc_single_cali_time", "[adc][ignore][manual]") } } -#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) + +/******************************************************************************** + * ADC Single with Light Sleep + ********************************************************************************/ +#include +#include "esp_sleep.h" +#include "regi2c_ctrl.h" + +//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 diff --git a/components/esp_hw_support/port/esp32/CMakeLists.txt b/components/esp_hw_support/port/esp32/CMakeLists.txt index 6c1db686e2..f06277097c 100644 --- a/components/esp_hw_support/port/esp32/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32/CMakeLists.txt @@ -1,5 +1,5 @@ target_include_directories(${COMPONENT_LIB} PUBLIC .) -target_include_directories(${COMPONENT_LIB} PRIVATE private_include) +target_include_directories(${COMPONENT_LIB} PUBLIC private_include) set(srcs "rtc_clk.c" diff --git a/components/esp_hw_support/port/esp32c2/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32c2/private_include/regi2c_saradc.h index dd23556527..255ed52e33 100644 --- a/components/esp_hw_support/port/esp32c2/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32c2/private_include/regi2c_saradc.h @@ -77,3 +77,10 @@ #define I2C_SARADC_TSENS_DAC 0x6 #define I2C_SARADC_TSENS_DAC_MSB 3 #define I2C_SARADC_TSENS_DAC_LSB 0 + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#define REGI2C_ANA_CALI_PD_WORKAROUND 1 +#define REGI2C_ANA_CALI_BYTE_NUM 8 diff --git a/components/esp_hw_support/port/esp32c2/regi2c_ctrl.h b/components/esp_hw_support/port/esp32c2/regi2c_ctrl.h index 423c2b0bbb..f665d3f664 100644 --- a/components/esp_hw_support/port/esp32c2/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32c2/regi2c_ctrl.h @@ -83,6 +83,16 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, #define REGI2C_READ(block, reg_add) \ regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add) + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#if REGI2C_ANA_CALI_PD_WORKAROUND +void regi2c_analog_cali_reg_read(void); +void regi2c_analog_cali_reg_write(void); +#endif //#if ADC_CALI_PD_WORKAROUND + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h index 1c35fd61ef..255ed52e33 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -77,3 +77,10 @@ #define I2C_SARADC_TSENS_DAC 0x6 #define I2C_SARADC_TSENS_DAC_MSB 3 #define I2C_SARADC_TSENS_DAC_LSB 0 + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#define REGI2C_ANA_CALI_PD_WORKAROUND 1 +#define REGI2C_ANA_CALI_BYTE_NUM 8 diff --git a/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h b/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h index 27e969eda8..7e5060288c 100644 --- a/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h @@ -82,6 +82,16 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, #define REGI2C_READ(block, reg_add) \ regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add) + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#if REGI2C_ANA_CALI_PD_WORKAROUND +void regi2c_analog_cali_reg_read(void); +void regi2c_analog_cali_reg_write(void); +#endif //#if ADC_CALI_PD_WORKAROUND + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h index 388f9c6221..2c3738a221 100644 --- a/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -73,3 +73,10 @@ #define I2C_SARADC_TSENS_DAC 0x6 #define I2C_SARADC_TSENS_DAC_MSB 3 #define I2C_SARADC_TSENS_DAC_LSB 0 + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#define REGI2C_ANA_CALI_PD_WORKAROUND 1 +#define REGI2C_ANA_CALI_BYTE_NUM 8 diff --git a/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h b/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h index 741c0b1020..5058cbb57e 100644 --- a/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h @@ -77,6 +77,16 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, #define REGI2C_READ(block, reg_add) \ regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add) + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#if REGI2C_ANA_CALI_PD_WORKAROUND +void regi2c_analog_cali_reg_read(void); +void regi2c_analog_cali_reg_write(void); +#endif //#if ADC_CALI_PD_WORKAROUND + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32s2/rtc_init.c b/components/esp_hw_support/port/esp32s2/rtc_init.c index ae1c2949d6..946eed5ae6 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_init.c @@ -235,50 +235,50 @@ static void set_ocode_by_efuse(int calib_version) */ static void calibrate_ocode(void) { - // /* - // Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL). - // Method: - // 1. read current cpu config, save in old_config; - // 2. switch cpu to xtal because PLL will be closed when o-code calibration; - // 3. begin o-code calibration; - // 4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout; - // 5. set cpu to old-config. - // */ - // rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get(); - // rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL; - // rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256; - // rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX; - // if (slow_clk_freq == (rtc_slow_freq_x32k)) { - // cal_clk = RTC_CAL_32K_XTAL; - // } else if (slow_clk_freq == rtc_slow_freq_8MD256) { - // cal_clk = RTC_CAL_8MD256; - // } + /* + Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL). + Method: + 1. read current cpu config, save in old_config; + 2. switch cpu to xtal because PLL will be closed when o-code calibration; + 3. begin o-code calibration; + 4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout; + 5. set cpu to old-config. + */ + rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get(); + rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL; + rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256; + rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX; + if (slow_clk_freq == (rtc_slow_freq_x32k)) { + cal_clk = RTC_CAL_32K_XTAL; + } else if (slow_clk_freq == rtc_slow_freq_8MD256) { + cal_clk = RTC_CAL_8MD256; + } - // uint64_t max_delay_time_us = 10000; - // uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100); - // uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period); - // uint64_t cycle0 = rtc_time_get(); - // uint64_t timeout_cycle = cycle0 + max_delay_cycle; - // uint64_t cycle1 = 0; + uint64_t max_delay_time_us = 10000; + uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100); + uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period); + uint64_t cycle0 = rtc_time_get(); + uint64_t timeout_cycle = cycle0 + max_delay_cycle; + uint64_t cycle1 = 0; - // rtc_cpu_freq_config_t old_config; - // rtc_clk_cpu_freq_get_config(&old_config); - // rtc_clk_cpu_freq_set_xtal(); + rtc_cpu_freq_config_t old_config; + rtc_clk_cpu_freq_get_config(&old_config); + rtc_clk_cpu_freq_set_xtal(); - // REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0); - // REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1); - // bool odone_flag = 0; - // bool bg_odone_flag = 0; - // while(1) { - // odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG); - // bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG); - // cycle1 = rtc_time_get(); - // if (odone_flag && bg_odone_flag) - // break; - // if (cycle1 >= timeout_cycle) { - // SOC_LOGW(TAG, "o_code calibration fail"); - // break; - // } - // } - // rtc_clk_cpu_freq_set_config(&old_config); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1); + bool odone_flag = 0; + bool bg_odone_flag = 0; + while(1) { + odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG); + bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG); + cycle1 = rtc_time_get(); + if (odone_flag && bg_odone_flag) + break; + if (cycle1 >= timeout_cycle) { + SOC_LOGW(TAG, "o_code calibration fail"); + break; + } + } + rtc_clk_cpu_freq_set_config(&old_config); } 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 388f9c6221..2c3738a221 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -73,3 +73,10 @@ #define I2C_SARADC_TSENS_DAC 0x6 #define I2C_SARADC_TSENS_DAC_MSB 3 #define I2C_SARADC_TSENS_DAC_LSB 0 + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#define REGI2C_ANA_CALI_PD_WORKAROUND 1 +#define REGI2C_ANA_CALI_BYTE_NUM 8 diff --git a/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h b/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h index e338035fc9..385444d5fe 100644 --- a/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -81,6 +81,15 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add) +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#if REGI2C_ANA_CALI_PD_WORKAROUND +void regi2c_analog_cali_reg_read(void); +void regi2c_analog_cali_reg_write(void); +#endif //#if ADC_CALI_PD_WORKAROUND + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/regi2c_ctrl.c b/components/esp_hw_support/regi2c_ctrl.c index 4ffe67175f..265534d54c 100644 --- a/components/esp_hw_support/regi2c_ctrl.c +++ b/components/esp_hw_support/regi2c_ctrl.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "regi2c_ctrl.h" +#include "esp_attr.h" #include #include #include @@ -40,3 +41,27 @@ void IRAM_ATTR regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_ i2c_write_reg_mask_raw(block, host_id, reg_add, msb, lsb, data); portEXIT_CRITICAL_ISR(&mux); } + +/** + * Restore regi2c analog calibration related configuration registers. + * This is a workaround, and is fixed on later chips + */ +#if REGI2C_ANA_CALI_PD_WORKAROUND + +static DRAM_ATTR uint8_t reg_val[REGI2C_ANA_CALI_BYTE_NUM]; + +void IRAM_ATTR regi2c_analog_cali_reg_read(void) +{ + for (int i = 0; i < REGI2C_ANA_CALI_PD_WORKAROUND; i++) { + reg_val[i] = regi2c_ctrl_read_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i); + } +} + +void IRAM_ATTR regi2c_analog_cali_reg_write(void) +{ + for (int i = 0; i < REGI2C_ANA_CALI_PD_WORKAROUND; i++) { + regi2c_ctrl_write_reg(I2C_SAR_ADC, I2C_SAR_ADC_HOSTID, i, reg_val[i]); + } +} + +#endif //#if ADC_CALI_PD_WORKAROUND diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index cbf786062d..d85cc487db 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -27,6 +27,7 @@ #include "soc/rtc.h" #include "soc/soc_caps.h" +#include "regi2c_ctrl.h" //For `REGI2C_ANA_CALI_PD_WORKAROUND`, temp #include "hal/wdt_hal.h" #include "hal/rtc_hal.h" @@ -319,6 +320,9 @@ static void IRAM_ATTR resume_uarts(void) } } +/** + * These save-restore workaround should be moved to lower layer + */ inline static void IRAM_ATTR misc_modules_sleep_prepare(void) { #if CONFIG_MAC_BB_PD @@ -330,8 +334,14 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void) #if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD sleep_enable_memory_retention(); #endif +#if REGI2C_ANA_CALI_PD_WORKAROUND + regi2c_analog_cali_reg_read(); +#endif } +/** + * These save-restore workaround should be moved to lower layer + */ inline static void IRAM_ATTR misc_modules_wake_prepare(void) { #if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD @@ -343,6 +353,9 @@ inline static void IRAM_ATTR misc_modules_wake_prepare(void) #if CONFIG_MAC_BB_PD mac_bb_power_up_cb_execute(); #endif +#if REGI2C_ANA_CALI_PD_WORKAROUND + regi2c_analog_cali_reg_write(); +#endif } inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu); diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index 14e04b99d7..0994202714 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -566,8 +566,8 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel) return (uint32_t)adc_ll_rtc_get_convert_value(adc_n); } -#elif SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED //For those RTC controller not supported chips, they use digital controller to do the single read. e.g.: esp32c3 +#elif SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { adc_ll_onetime_sample_enable(ADC_NUM_1, false);