1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
58
59
60
61
62
63
67
68
69
70
71
72
73
74
78
79
80
81
82
83
84
85
86
87
88
89
90
94
95
96
97
98
99
103
104
105
122
123
124
125
128
129
130
131
132
133
136
137
140
141
142
143
144
145
146
150
151
155
156
157
158
159
160
161
166
167
172
173
174
175
176
177
178
179
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
201
202
203
204
205
206
207
216
217
218
219
220
221
222
223
224
236
237
238
/* ... */
/* ... */
#include <esp_types.h>
#include "sdkconfig.h"
#include "sys/lock.h"
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#include "hal/adc_types.h"
#include "hal/adc_hal_common.h"
#include "hal/adc_ll.h"
#include "esp_private/adc_share_hw_ctrl.h"
#include "esp_private/sar_periph_ctrl.h"
#include "esp_private/periph_ctrl.h"
#include "soc/periph_defs.h"13 includes
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp_efuse_rtc_table.h"
#elif SOC_ADC_CALIBRATION_V1_SUPPORTED
#include "esp_efuse_rtc_calib.h"
#endif
static const char *TAG = "adc_share_hw_ctrl";
extern portMUX_TYPE rtc_spinlock;
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
/* ... */
#if CONFIG_IDF_TARGET_ESP32S2
#define esp_efuse_rtc_calib_get_ver() esp_efuse_rtc_table_read_calib_version()
static inline uint32_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
{
int tag = esp_efuse_rtc_table_get_tag(version, adc_unit, atten, RTCCALIB_V2_PARAM_VINIT);
return esp_efuse_rtc_table_get_parsed_efuse_value(tag, false);
}{...}
/* ... */#endif
static uint32_t s_adc_cali_param[SOC_ADC_PERIPH_NUM][SOC_ADC_ATTEN_NUM] = {};
void adc_calc_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
{
if (s_adc_cali_param[adc_n][atten]) {
ESP_EARLY_LOGV(TAG, "Use calibrated val ADC%d atten=%d: %04" PRIX32, adc_n + 1, atten, s_adc_cali_param[adc_n][atten]);
return ;
}{...}
int version = esp_efuse_rtc_calib_get_ver();
uint32_t init_code = 0;
if ((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX)) {
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
}{...}
#if SOC_ADC_SELF_HW_CALI_SUPPORTED
else {
ESP_EARLY_LOGD(TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
sar_periph_ctrl_adc_oneshot_power_acquire();
portENTER_CRITICAL(&rtc_spinlock);
adc_ll_pwdet_set_cct(ADC_LL_PWDET_CCT_DEFAULT);
const bool internal_gnd = true;
init_code = adc_hal_self_calibration(adc_n, atten, internal_gnd);
portEXIT_CRITICAL(&rtc_spinlock);
sar_periph_ctrl_adc_oneshot_power_release();
}{...}
/* ... */#else
else {
ESP_EARLY_LOGD(TAG, "ICode self-calibration isn't supported");
}{...}
/* ... */#endif
s_adc_cali_param[adc_n][atten] = init_code;
ESP_EARLY_LOGV(TAG, "Calib(V%d) ADC%d atten=%d: %04" PRIX32, version, adc_n + 1, atten, init_code);
}{...}
void IRAM_ATTR adc_set_hw_calibration_code(adc_unit_t adc_n, adc_atten_t atten)
{
adc_hal_set_calibration_param(adc_n, s_adc_cali_param[adc_n][atten]);
}{...}
#if SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
static int s_adc_cali_chan_compens[SOC_ADC_MAX_CHANNEL_NUM][SOC_ADC_ATTEN_NUM] = {};
void adc_load_hw_calibration_chan_compens(adc_unit_t adc_n, adc_channel_t chan, adc_atten_t atten)
{
int version = esp_efuse_rtc_calib_get_ver();
if ((version >= ESP_EFUSE_ADC_CALIB_VER_MIN) &&
(version <= ESP_EFUSE_ADC_CALIB_VER_MAX)) {
s_adc_cali_chan_compens[chan][atten] = esp_efuse_rtc_calib_get_chan_compens(version, adc_n, chan, atten);
}{...}
}{...}
int IRAM_ATTR adc_get_hw_calibration_chan_compens(adc_unit_t adc_n, adc_channel_t chan, adc_atten_t atten)
{
return s_adc_cali_chan_compens[chan][atten];
}{...}
/* ... */#endif /* ... */
#endif
/* ... */
static _lock_t adc1_lock;
static _lock_t adc2_lock;
esp_err_t adc_lock_acquire(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_1) {
_lock_acquire(&adc1_lock);
}{...}
if (adc_unit == ADC_UNIT_2) {
_lock_acquire(&adc2_lock);
}{...}
return ESP_OK;
}{ ... }
esp_err_t adc_lock_release(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_2) {
ESP_RETURN_ON_FALSE(((uint32_t *)adc2_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc2 lock release without acquiring");
_lock_release(&adc2_lock);
}{...}
if (adc_unit == ADC_UNIT_1) {
ESP_RETURN_ON_FALSE(((uint32_t *)adc1_lock != NULL), ESP_ERR_INVALID_STATE, TAG, "adc1 lock release without acquiring");
_lock_release(&adc1_lock);
}{...}
return ESP_OK;
}{ ... }
esp_err_t adc_lock_try_acquire(adc_unit_t adc_unit)
{
if (adc_unit == ADC_UNIT_1) {
if (_lock_try_acquire(&adc1_lock) == -1) {
return ESP_ERR_TIMEOUT;
}{...}
}{...}
if (adc_unit == ADC_UNIT_2) {
if (_lock_try_acquire(&adc2_lock) == -1) {
return ESP_ERR_TIMEOUT;
}{...}
}{...}
return ESP_OK;
}{ ... }
esp_err_t adc2_wifi_acquire(void)
{
#if CONFIG_IDF_TARGET_ESP32
adc_lock_acquire(ADC_UNIT_2);
ESP_LOGD(TAG, "Wi-Fi takes adc2 lock.");/* ... */
#endif
return ESP_OK;
}{ ... }
esp_err_t adc2_wifi_release(void)
{
#if CONFIG_IDF_TARGET_ESP32
return adc_lock_release(ADC_UNIT_2);
#endif
return ESP_OK;
}{ ... }
static portMUX_TYPE s_spinlock = portMUX_INITIALIZER_UNLOCKED;
/* ... */
static int s_adc_digi_ctrlr_cnt;
void adc_apb_periph_claim(void)
{
portENTER_CRITICAL(&s_spinlock);
s_adc_digi_ctrlr_cnt++;
if (s_adc_digi_ctrlr_cnt == 1) {
ADC_BUS_CLK_ATOMIC() {
adc_ll_enable_bus_clock(true);
#if SOC_RCC_IS_INDEPENDENT
adc_ll_enable_func_clock(true);
#endif
adc_ll_reset_register();
}{...}
}{...}
portEXIT_CRITICAL(&s_spinlock);
}{ ... }
void adc_apb_periph_free(void)
{
portENTER_CRITICAL(&s_spinlock);
s_adc_digi_ctrlr_cnt--;
if (s_adc_digi_ctrlr_cnt == 0) {
ADC_BUS_CLK_ATOMIC() {
adc_ll_enable_bus_clock(false);
#if SOC_RCC_IS_INDEPENDENT
adc_ll_enable_func_clock(false);
#endif
}{...}
}{...} else if (s_adc_digi_ctrlr_cnt < 0) {
portEXIT_CRITICAL(&s_spinlock);
ESP_LOGE(TAG, "%s called, but `s_adc_digi_ctrlr_cnt == 0`", __func__);
abort();
}{...}
portEXIT_CRITICAL(&s_spinlock);
}{ ... }