|
| 1 | +From a5c02c9a4a0cb2f8215e7e1ed519402eb4447fc5 Mon Sep 17 00:00:00 2001 |
| 2 | + |
| 3 | +Date: Thu, 19 Sep 2024 18:07:36 +0800 |
| 4 | +Subject: [PATCH] fix(adc): support esp32s3 adc range above 3100mv |
| 5 | + |
| 6 | +--- |
| 7 | + .../efuse/esp32s3/esp_efuse_rtc_calib.c | 45 +++++++++++++++++++ |
| 8 | + .../esp32s3/include/esp_efuse_rtc_calib.h | 10 +++++ |
| 9 | + components/esp_adc/adc_oneshot.c | 33 ++++++++++++++ |
| 10 | + components/esp_hw_support/adc_share_hw_ctrl.c | 11 ++++- |
| 11 | + 4 files changed, 98 insertions(+), 1 deletion(-) |
| 12 | + |
| 13 | +diff --git a/components/efuse/esp32s3/esp_efuse_rtc_calib.c b/components/efuse/esp32s3/esp_efuse_rtc_calib.c |
| 14 | +index 2ede5610ba..752d072ecb 100644 |
| 15 | +--- a/components/efuse/esp32s3/esp_efuse_rtc_calib.c |
| 16 | ++++ b/components/efuse/esp32s3/esp_efuse_rtc_calib.c |
| 17 | +@@ -25,6 +25,47 @@ int esp_efuse_rtc_calib_get_ver(void) |
| 18 | + return cali_version; |
| 19 | + } |
| 20 | + |
| 21 | ++#ifdef CONFIG_ENABLE_ADC_USER_CODE_OFFSET |
| 22 | ++ |
| 23 | ++#define ADC_NUM_MAX (ADC_UNIT_2 + 1) |
| 24 | ++static const char* TAG = "eFuse"; |
| 25 | ++ |
| 26 | ++static uint32_t adc_icode_offset[ADC_NUM_MAX][4] = {0}; |
| 27 | ++static bool adc_icode_offset_flag[ADC_NUM_MAX][4] = {0}; |
| 28 | ++ |
| 29 | ++void esp_efuse_rtc_calib_set_init_code_offset(uint32_t adc_unit, int atten, uint32_t offset) |
| 30 | ++{ |
| 31 | ++ assert(adc_unit < ADC_NUM_MAX); |
| 32 | ++ assert(atten < 4); |
| 33 | ++ if (adc_icode_offset[adc_unit][atten] != offset) { |
| 34 | ++ /* code */ |
| 35 | ++ adc_icode_offset[adc_unit][atten] = offset; |
| 36 | ++ adc_icode_offset_flag[adc_unit][atten] = true; |
| 37 | ++ ESP_LOGV(TAG, "adc %lu atten_i %d, offset = %lu", adc_unit+1, atten, offset); |
| 38 | ++ } else { |
| 39 | ++ ESP_LOGV(TAG, "adc %lu atten_i %d, offset = no change", adc_unit+1, atten); |
| 40 | ++ } |
| 41 | ++} |
| 42 | ++ |
| 43 | ++uint32_t esp_efuse_rtc_calib_get_init_code_offset(uint32_t adc_unit, int atten) |
| 44 | ++{ |
| 45 | ++ assert(adc_unit < ADC_NUM_MAX); |
| 46 | ++ assert(atten < 4); |
| 47 | ++ return adc_icode_offset[adc_unit][atten];; |
| 48 | ++} |
| 49 | ++ |
| 50 | ++bool esp_efuse_rtc_calib_query_init_code_offset_flag(uint32_t adc_unit, int atten) |
| 51 | ++{ |
| 52 | ++ return adc_icode_offset_flag[adc_unit][atten]; |
| 53 | ++} |
| 54 | ++ |
| 55 | ++bool esp_efuse_rtc_calib_clear_init_code_offset_flag(uint32_t adc_unit, int atten) |
| 56 | ++{ |
| 57 | ++ adc_icode_offset_flag[adc_unit][atten] = false; |
| 58 | ++ return adc_icode_offset_flag[adc_unit][atten]; |
| 59 | ++} |
| 60 | ++#endif |
| 61 | ++ |
| 62 | + uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) |
| 63 | + { |
| 64 | + assert((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) && |
| 65 | +@@ -58,7 +99,11 @@ uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int a |
| 66 | + adc_icode[3] = adc_icode_diff[3] + adc_icode[2]; |
| 67 | + } |
| 68 | + |
| 69 | ++#ifdef CONFIG_ENABLE_ADC_USER_CODE_OFFSET |
| 70 | ++ return adc_icode[atten] + adc_icode_offset[adc_unit][atten]; |
| 71 | ++#else |
| 72 | + return adc_icode[atten]; |
| 73 | ++#endif |
| 74 | + } |
| 75 | + |
| 76 | + esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t *out_digi, uint32_t *out_vol_mv) |
| 77 | +diff --git a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h |
| 78 | +index 49712040a0..edbcc6d85f 100644 |
| 79 | +--- a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h |
| 80 | ++++ b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h |
| 81 | +@@ -57,6 +57,16 @@ esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, in |
| 82 | + */ |
| 83 | + esp_err_t esp_efuse_rtc_calib_get_tsens_val(float* tsens_cal); |
| 84 | + |
| 85 | ++ |
| 86 | ++#define CONFIG_ENABLE_ADC_USER_CODE_OFFSET 1 |
| 87 | ++ |
| 88 | ++#ifdef CONFIG_ENABLE_ADC_USER_CODE_OFFSET |
| 89 | ++void esp_efuse_rtc_calib_set_init_code_offset(uint32_t adc_unit, int atten, uint32_t offset); |
| 90 | ++uint32_t esp_efuse_rtc_calib_get_init_code_offset(uint32_t adc_unit, int atten); |
| 91 | ++bool esp_efuse_rtc_calib_query_init_code_offset_flag(uint32_t adc_unit, int atten); |
| 92 | ++bool esp_efuse_rtc_calib_clear_init_code_offset_flag(uint32_t adc_unit, int atten); |
| 93 | ++#endif |
| 94 | ++ |
| 95 | + #ifdef __cplusplus |
| 96 | + } |
| 97 | + #endif |
| 98 | +diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c |
| 99 | +index 0691e22f1a..cccb6ee02e 100644 |
| 100 | +--- a/components/esp_adc/adc_oneshot.c |
| 101 | ++++ b/components/esp_adc/adc_oneshot.c |
| 102 | +@@ -29,6 +29,7 @@ |
| 103 | + #include "hal/adc_oneshot_hal.h" |
| 104 | + #include "hal/adc_ll.h" |
| 105 | + #include "soc/adc_periph.h" |
| 106 | ++#include "esp_efuse_rtc_calib.h" |
| 107 | + |
| 108 | + #if CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM |
| 109 | + #define ADC_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) |
| 110 | +@@ -166,6 +167,8 @@ esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, adc_chann |
| 111 | + return ESP_OK; |
| 112 | + } |
| 113 | + |
| 114 | ++extern void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten); |
| 115 | ++ |
| 116 | + esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, int *out_raw) |
| 117 | + { |
| 118 | + ESP_RETURN_ON_FALSE(handle && out_raw, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); |
| 119 | +@@ -180,6 +183,8 @@ esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, |
| 120 | + #if SOC_ADC_CALIBRATION_V1_SUPPORTED |
| 121 | + adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan); |
| 122 | + adc_hal_calibration_init(handle->unit_id); |
| 123 | ++ // Get the offset first, then set the offset. |
| 124 | ++ adc_calc_hw_calibration_code(handle->unit_id, atten); |
| 125 | + adc_set_hw_calibration_code(handle->unit_id, atten); |
| 126 | + #endif // SOC_ADC_CALIBRATION_V1_SUPPORTED |
| 127 | + bool valid = false; |
| 128 | +@@ -251,10 +256,38 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle) |
| 129 | + esp_err_t adc_oneshot_get_calibrated_result(adc_oneshot_unit_handle_t handle, adc_cali_handle_t cali_handle, adc_channel_t chan, int *cali_result) |
| 130 | + { |
| 131 | + int raw = 0; |
| 132 | ++ int voltage_b = 0; |
| 133 | + ESP_RETURN_ON_ERROR(adc_oneshot_read(handle, chan, &raw), TAG, "adc oneshot read fail"); |
| 134 | + ESP_LOGD(TAG, "raw: 0d%d", raw); |
| 135 | + ESP_RETURN_ON_ERROR(adc_cali_raw_to_voltage(cali_handle, raw, cali_result), TAG, "adc calibration fail"); |
| 136 | + |
| 137 | ++#if (CONFIG_IDF_TARGET_ESP32S3 & CONFIG_ENABLE_ADC_USER_CODE_OFFSET) |
| 138 | ++ typedef const float ADC_CAL_TYPE; |
| 139 | ++ adc_atten_t atten = adc_ll_get_atten(handle->unit_id, chan); |
| 140 | ++ if(atten == ADC_ATTEN_DB_12) { |
| 141 | ++ if(*cali_result > 2900) { |
| 142 | ++ ESP_LOGD(TAG, "first is %u", *cali_result); |
| 143 | ++ esp_efuse_rtc_calib_set_init_code_offset(handle->unit_id, atten, 1200); |
| 144 | ++ ESP_RETURN_ON_ERROR(adc_oneshot_read(handle, chan, &raw), TAG, "adc oneshot read fail"); |
| 145 | ++ esp_efuse_rtc_calib_set_init_code_offset(handle->unit_id, atten, 0); |
| 146 | ++ ESP_RETURN_ON_ERROR(adc_cali_raw_to_voltage(cali_handle, raw, &voltage_b), TAG, "adc calibration fail"); |
| 147 | ++ voltage_b += 1000; |
| 148 | ++ |
| 149 | ++ if (voltage_b > 2700) { |
| 150 | ++ ESP_LOGD(TAG, "before is %u", voltage_b); |
| 151 | ++ ADC_CAL_TYPE a = -0.0000016625088686597596; |
| 152 | ++ ADC_CAL_TYPE b = 0.0012152697844402401; |
| 153 | ++ ADC_CAL_TYPE c = 7.660092154791914; |
| 154 | ++ ADC_CAL_TYPE e = a * voltage_b * voltage_b + b * voltage_b + c; |
| 155 | ++ voltage_b = voltage_b * (1 + e / 100); |
| 156 | ++ ESP_LOGD(TAG, "after is %u", voltage_b); |
| 157 | ++ } |
| 158 | ++ |
| 159 | ++ *cali_result = voltage_b; |
| 160 | ++ } |
| 161 | ++ } |
| 162 | ++#endif |
| 163 | ++ |
| 164 | + return ESP_OK; |
| 165 | + } |
| 166 | + |
| 167 | +diff --git a/components/esp_hw_support/adc_share_hw_ctrl.c b/components/esp_hw_support/adc_share_hw_ctrl.c |
| 168 | +index 32f3c67b79..1e2431bacd 100644 |
| 169 | +--- a/components/esp_hw_support/adc_share_hw_ctrl.c |
| 170 | ++++ b/components/esp_hw_support/adc_share_hw_ctrl.c |
| 171 | +@@ -60,11 +60,16 @@ static uint32_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {}; |
| 172 | + |
| 173 | + void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten) |
| 174 | + { |
| 175 | ++#ifdef CONFIG_ENABLE_ADC_USER_CODE_OFFSET |
| 176 | ++ if (!esp_efuse_rtc_calib_query_init_code_offset_flag(adc_n, atten)) { |
| 177 | ++#endif |
| 178 | + if (s_adc_cali_param[adc_n][atten]) { |
| 179 | + ESP_EARLY_LOGV(TAG, "Use calibrated val ADC%d atten=%d: %04" PRIX32, adc_n + 1, atten, s_adc_cali_param[adc_n][atten]); |
| 180 | + return ; |
| 181 | + } |
| 182 | +- |
| 183 | ++#ifdef CONFIG_ENABLE_ADC_USER_CODE_OFFSET |
| 184 | ++ } |
| 185 | ++#endif |
| 186 | + // check if we can fetch the values from eFuse. |
| 187 | + int version = esp_efuse_rtc_calib_get_ver(); |
| 188 | + |
| 189 | +@@ -92,6 +97,10 @@ void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten) |
| 190 | + } |
| 191 | + #endif //SOC_ADC_SELF_HW_CALI_SUPPORTED |
| 192 | + |
| 193 | ++#ifdef CONFIG_ENABLE_ADC_USER_CODE_OFFSET |
| 194 | ++ esp_efuse_rtc_calib_clear_init_code_offset_flag(adc_n, atten); |
| 195 | ++#endif |
| 196 | ++ |
| 197 | + s_adc_cali_param[adc_n][atten] = init_code; |
| 198 | + ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04" PRIX32, version, adc_n + 1, atten, init_code); |
| 199 | + } |
| 200 | +-- |
| 201 | +2.34.1 |
| 202 | + |
0 commit comments