adc: support adc self-calibration on esp32s3

pull/7680/head
Armando 2021-09-15 12:18:38 +08:00
rodzic 6704f4c92f
commit ddd0235783
5 zmienionych plików z 55 dodań i 15 usunięć

Wyświetl plik

@ -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; uint32_t init_code = 0;
if (version == 1) { if (version == 1) {
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten); init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
s_adc_cali_param[adc_n][atten] = init_code;
} else { } 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]; return s_adc_cali_param[adc_n][atten];
} }
#elif CONFIG_IDF_TARGET_ESP32S2 #elif CONFIG_IDF_TARGET_ESP32S2

Wyświetl plik

@ -18,6 +18,14 @@
#define I2C_SAR_ADC 0X69 #define I2C_SAR_ADC 0X69
#define I2C_SAR_ADC_HOSTID 0 #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 0x1
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0 #define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0

Wyświetl plik

@ -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) 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 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). */ /* Enable/disable internal connect GND (for calibration). */
if (internal_gnd) { 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_TIMES (10)
#define ADC_HAL_CAL_OFFSET_RANGE (4096) #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) 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) { 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; : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
adc_ll_calibration_finish(adc_n); adc_ll_calibration_finish(adc_n);
return ret; return ret;
} }
#endif //#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED #endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2

Wyświetl plik

@ -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) static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
{ {
//To be added including RTC_CNTR reg and functions /* Should be called before writing I2C registers. */
abort(); 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. * 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 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. * @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. * 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) 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) 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);
}
} }
/** /**

Wyświetl plik

@ -54,9 +54,9 @@ static bool adc_calibration_init(void)
ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME); ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME);
if (ret == ESP_ERR_NOT_SUPPORTED) { 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) { } 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) { } else if (ret == ESP_OK) {
cali_enable = true; cali_enable = true;
esp_adc_cal_characterize(ADC_UNIT_1, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars); esp_adc_cal_characterize(ADC_UNIT_1, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);