Skip to content

Commit 85679be

Browse files
committed
Merge branch 'feat/add_adc_range_extend_on_idf531' into 'master'
feat: support adc range extend on idf v5.3.1 See merge request ae_group/esp-iot-solution!1092
2 parents 97b8b7b + 0a7638c commit 85679be

File tree

4 files changed

+245
-6
lines changed

4 files changed

+245
-6
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
From a5c02c9a4a0cb2f8215e7e1ed519402eb4447fc5 Mon Sep 17 00:00:00 2001
2+
From: yanke <[email protected]>
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+

docs/en/others/adc_range.rst

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,32 @@ Overall, during each ADC measurement, there will be 1-2 times ADC reading. For m
2020
Patch Use Guide
2121
-------------------
2222

23-
At present, the patch file is developed based on ESP-IDF ``v4.4.8``:
23+
How to Apply a Patch Based on ESP-IDF ``v4.4.8``
24+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2425

2526
1. Please make sure ESP-IDF has been ``checked out`` to the ``v4.4.8``
2627
2. Please download file :download:`esp32s3_adc_range_to_3100.patch <../../_static/esp32s3_adc_range_to_3100.patch>` to anywhere you want
2728
3. Using command ``git am --signoff < esp32s3_adc_range_to_3100.patch`` to apply the patch to ESP-IDF
2829

30+
How to Apply a Patch Based on ESP-IDF ``v5.3.1``
31+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
33+
1. Please make sure ESP-IDF has been ``checked out`` to the ``v5.3.1``
34+
2. Please download file :download:`esp32s3_adc_range_to_3100_v531.patch <../../_static/esp32s3_adc_range_to_3100_v531.patch>` to anywhere you want
35+
3. Using command ``git am --signoff < esp32s3_adc_range_to_3100_v531.patch`` to apply the patch to ESP-IDF
36+
2937
API Guide
3038
-------------
3139

32-
1. To get the range expansion result, users must directly use ``esp_adc_cal_get_voltage`` to get the voltage of ``ADC1`` or ``ADC2``.
33-
2. Other APIs of ESP-IDF ADC are not affected, and the read results are consistent with the default results
40+
The method to obtain the voltage value after ADC range extension varies for different versions of ESP-IDF:
41+
42+
- ESP-IDF ``v4.4.8``
43+
44+
1. To get the range expansion result, users must directly use ``esp_adc_cal_get_voltage`` to get the voltage of ``ADC1`` or ``ADC2``.
45+
2. Other APIs of ESP-IDF ``v4.4.8`` ADC are not affected, and the read results are consistent with the default results
46+
47+
48+
- ESP-IDF ``v5.3.1``
49+
50+
1. To get the range expansion result, users must directly use ``adc_oneshot_get_calibrated_result`` to get the voltage of ``ADC1`` or ``ADC2``.
51+
2. Other APIs of ESP-IDF ``v5.3.1`` ADC are not affected, and the read results are consistent with the default results

docs/zh_CN/others/adc_range.rst

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,33 @@ ESP32-S3 可通过配置寄存器调整 ADC 的偏置电压,再结合高电压
2020
Patch 使用方法
2121
-------------------
2222

23-
当前 Patch 基于 ESP-IDF ``v4.4.8`` 开发:
23+
基于 ESP-IDF ``v4.4.8`` 的 Patch 使用方法
24+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2425

2526
1. 确认 ESP-IDF 已经 ``checkout`` 到 ``v4.4.8``
2627
2. 下载 :download:`esp32s3_adc_range_to_3100.patch <../../_static/esp32s3_adc_range_to_3100.patch>` 文件
2728
3. 使用指令 ``git am --signoff < esp32s3_adc_range_to_3100.patch`` 将 Patch 应用到 IDF 中
2829
4. 请注意, 该方案仅对 ``esp_adc_cal_get_voltage`` 接口有效,用户可直接调用该接口获取扩展后的读数
2930

31+
基于 ESP-IDF ``v5.3.1`` 的 Patch 使用方法
32+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33+
34+
1. 确认 ESP-IDF 已经 ``checkout`` 到 ``v5.3.1``
35+
2. 下载 :download:`esp32s3_adc_range_to_3100_v531.patch <../../_static/esp32s3_adc_range_to_3100_v531.patch>` 文件
36+
3. 使用指令 ``git am --signoff < esp32s3_adc_range_to_3100_v531.patch`` 将 Patch 应用到 IDF 中
37+
4. 请注意, 该方案仅对 ``adc_oneshot_get_calibrated_result`` 接口有效,用户可直接调用该接口获取扩展后的读数
38+
3039
API 使用说明
3140
--------------
3241

33-
1. 如果想要读取量程扩展后的电压值,用户必须使用 ``esp_adc_cal_get_voltage`` 直接获取 ``ADC1`` 或 ``ADC2`` 的通道电压。
34-
2. ESP-IDF ADC 其它 API 不受影响,读取的结果和默认结果一致
42+
对于不同版本的 ESP-IDF,获取 ADC 量程扩展后的电压值方法有所不同:
43+
44+
- ESP-IDF ``v4.4.8``
45+
46+
1. 如果想要读取量程扩展后的电压值,用户必须使用 ``esp_adc_cal_get_voltage`` 直接获取 ``ADC1`` 或 ``ADC2`` 的通道电压
47+
2. ESP-IDF ``v4.4.8`` ADC 其它 API 不受影响,读取的结果和默认结果一致
48+
49+
- ESP-IDF ``v5.3.1``
50+
51+
1. 如果想要读取量程扩展后的电压值,用户必须使用 ``adc_oneshot_get_calibrated_result`` 直接获取 ``ADC1`` 或 ``ADC2`` 的通道电压
52+
2. ESP-IDF ``v5.3.1`` ADC 其它 API 不受影响,读取的结果和默认结果一致

tools/ci/astyle-rules.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ not_formatted_permanent:
3737
- "components/gui/lvgl_gui/"
3838
- "components/usb/usb_stream/test_apps/main/wave_1ch_16bits.c"
3939
- "components/utilities/xz/"
40+
- "docs/_static/esp32s3_adc_range_to_3100_v531.patch"
4041
- "docs/_static/esp32s3_adc_range_to_3100.patch"
4142
- "docs/doxygen-known-warnings.txt"
4243
- "docs/sphinx-known-warnings.txt"

0 commit comments

Comments
 (0)