Skip to content

Commit 8d92284

Browse files
fuzhiboespressif-bot
authored andcommitted
driver(adc): esp32s2 support API adc2_vref_to_gpio
1 parent 6078fce commit 8d92284

File tree

9 files changed

+184
-82
lines changed

9 files changed

+184
-82
lines changed

components/driver/adc_common.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,36 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
535535
return ESP_OK;
536536
}
537537

538+
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
539+
{
540+
return adc_vref_to_gpio(ADC_UNIT_2, gpio);
541+
}
542+
543+
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
544+
{
545+
#ifdef CONFIG_IDF_TARGET_ESP32
546+
if (adc_unit & ADC_UNIT_1) return ESP_ERR_INVALID_ARG;
547+
#endif
548+
adc2_channel_t ch = ADC2_CHANNEL_MAX;
549+
/* Check if the GPIO supported. */
550+
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
551+
if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
552+
ch = i;
553+
break;
554+
}
555+
}
556+
if (ch == ADC2_CHANNEL_MAX) return ESP_ERR_INVALID_ARG;
557+
558+
ADC_ENTER_CRITICAL();
559+
adc_hal_set_power_manage(ADC_POWER_SW_ON);
560+
if (adc_unit & ADC_UNIT_1) {
561+
adc_hal_vref_output(ADC_NUM_1, ch, true);
562+
} else if (adc_unit & ADC_UNIT_2) {
563+
adc_hal_vref_output(ADC_NUM_2, ch, true);
564+
}
565+
ADC_EXIT_CRITICAL();
566+
567+
//Configure RTC gpio, Only ADC2's channels IO are supported to output reference voltage.
568+
adc_gpio_init(ADC_UNIT_2, ch);
569+
return ESP_OK;
570+
}

components/driver/esp32/adc.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -133,22 +133,6 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
133133
RTC controller setting
134134
---------------------------------------------------------------*/
135135

136-
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
137-
{
138-
ADC_ENTER_CRITICAL();
139-
adc_hal_set_power_manage(ADC_POWER_SW_ON);
140-
ADC_EXIT_CRITICAL();
141-
if (adc_hal_vref_output(gpio) != true) {
142-
return ESP_ERR_INVALID_ARG;
143-
}
144-
//Configure RTC gpio
145-
rtc_gpio_init(gpio);
146-
rtc_gpio_set_direction(gpio, RTC_GPIO_MODE_DISABLED);
147-
rtc_gpio_pullup_dis(gpio);
148-
rtc_gpio_pulldown_dis(gpio);
149-
return ESP_OK;
150-
}
151-
152136
/*---------------------------------------------------------------
153137
HALL SENSOR
154138
---------------------------------------------------------------*/

components/driver/esp32/include/driver/adc.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,6 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
4646
RTC controller setting
4747
---------------------------------------------------------------*/
4848

49-
/**
50-
* @brief Output ADC2 reference voltage to GPIO 25 or 26 or 27
51-
*
52-
* This function utilizes the testing mux exclusive to ADC 2 to route the
53-
* reference voltage one of ADC2's channels. Supported GPIOs are GPIOs
54-
* 25, 26, and 27. This refernce voltage can be manually read from the pin
55-
* and used in the esp_adc_cal component.
56-
*
57-
* @param[in] gpio GPIO number (GPIOs 25, 26 and 27 are supported)
58-
*
59-
* @return
60-
* - ESP_OK: v_ref successfully routed to selected GPIO
61-
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
62-
*/
63-
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio);
64-
6549
/**
6650
* @brief Read Hall Sensor
6751
*

components/driver/include/driver/adc_common.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,40 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
312312
*/
313313
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out);
314314

315+
/**
316+
* @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO.
317+
*
318+
* This function routes the internal reference voltage of ADCn to one of
319+
* ADC2's channels. This reference voltage can then be manually measured
320+
* for calibration purposes.
321+
*
322+
* @note ESP32 only supports output of ADC2's internal reference voltage.
323+
* @param[in] adc_unit ADC unit index
324+
* @param[in] gpio GPIO number (Only ADC2's channels IO are supported)
325+
*
326+
* @return
327+
* - ESP_OK: v_ref successfully routed to selected GPIO
328+
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
329+
*/
330+
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
331+
332+
/**
333+
* @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO.
334+
*
335+
* This function routes the internal reference voltage of ADCn to one of
336+
* ADC2's channels. This reference voltage can then be manually measured
337+
* for calibration purposes.
338+
*
339+
* @deprecated Use ``adc_vref_to_gpio`` instead.
340+
*
341+
* @param[in] gpio GPIO number (ADC2's channels are supported)
342+
*
343+
* @return
344+
* - ESP_OK: v_ref successfully routed to selected GPIO
345+
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
346+
*/
347+
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
348+
315349
#ifdef __cplusplus
316350
}
317351
#endif

components/soc/include/hal/adc_hal.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,20 @@ int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value);
168168
*/
169169
#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en)
170170

171+
/**
172+
* Enable/disable the output of ADCn's internal reference voltage to one of ADC2's channels.
173+
*
174+
* This function routes the internal reference voltage of ADCn to one of
175+
* ADC2's channels. This reference voltage can then be manually measured
176+
* for calibration purposes.
177+
*
178+
* @note ESP32 only supports output of ADC2's internal reference voltage.
179+
* @param[in] adc ADC unit select
180+
* @param[in] channel ADC2 channel number
181+
* @param[in] en Enable/disable the reference voltage output
182+
*/
183+
#define adc_hal_vref_output(adc, channel, en) adc_ll_vref_output(adc, channel, en)
184+
171185
/*---------------------------------------------------------------
172186
Digital controller setting
173187
---------------------------------------------------------------*/

components/soc/src/esp32/include/hal/adc_hal.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,6 @@ void adc_hal_digi_deinit(void);
100100
*/
101101
int adc_hal_hall_convert(void);
102102

103-
/**
104-
* @brief Output ADC2 reference voltage to gpio
105-
*
106-
* This function utilizes the testing mux exclusive to ADC2 to route the
107-
* reference voltage one of ADC2's channels.
108-
*
109-
* @param[in] io GPIO number
110-
* @return
111-
* - true: v_ref successfully routed to selected gpio
112-
* - false: Unsupported gpio
113-
*/
114-
#define adc_hal_vref_output(io) adc_ll_vref_output(io)
115-
116103
#ifdef __cplusplus
117104
}
118105
#endif

components/soc/src/esp32/include/hal/adc_ll.h

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -673,43 +673,43 @@ static inline void adc_ll_set_hall_controller(adc_ll_hall_controller_t hall_ctrl
673673
}
674674

675675
/**
676-
* Output ADC2 reference voltage to gpio 25 or 26 or 27
677-
*
678-
* This function utilizes the testing mux exclusive to ADC 2 to route the
679-
* reference voltage one of ADC2's channels. Supported gpios are gpios
680-
* 25, 26, and 27. This refernce voltage can be manually read from the pin
681-
* and used in the esp_adc_cal component.
682-
*
683-
* @param[in] io GPIO number (gpios 25,26,27 supported)
684-
*
685-
* @return
686-
* - true: v_ref successfully routed to selected gpio
687-
* - false: Unsupported gpio
688-
*/
689-
static inline bool adc_ll_vref_output(int io)
690-
{
691-
int channel;
692-
if (io == 25) {
693-
channel = 8; //Channel 8 bit
694-
} else if (io == 26) {
695-
channel = 9; //Channel 9 bit
696-
} else if (io == 27) {
697-
channel = 7; //Channel 7 bit
676+
* Output ADC internal reference voltage to channels, only available for ADC2 on ESP32.
677+
*
678+
* This function routes the internal reference voltage of ADCn to one of
679+
* ADC2's channels. This reference voltage can then be manually measured
680+
* for calibration purposes.
681+
*
682+
* @param[in] adc ADC unit select
683+
* @param[in] channel ADC2 channel number
684+
* @param[in] en Enable/disable the reference voltage output
685+
*/
686+
static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en)
687+
{
688+
if (adc != ADC_NUM_2) return;
689+
690+
if (en) {
691+
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
692+
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
693+
RTCCNTL.test_mux.dtest_rtc = 1; //Config test mux to route v_ref to ADC2 Channels
694+
//set ent
695+
RTCCNTL.test_mux.ent_rtc = 1;
696+
//set sar2_en_test
697+
SENS.sar_start_force.sar2_en_test = 1;
698+
//set sar2 en force
699+
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
700+
//set en_pad for channels 7,8,9 (bits 0x380)
701+
SENS.sar_meas_start2.sar2_en_pad = 1 << channel;
698702
} else {
699-
return false;
703+
RTCCNTL.test_mux.dtest_rtc = 0; //Config test mux to route v_ref to ADC2 Channels
704+
//set ent
705+
RTCCNTL.test_mux.ent_rtc = 0;
706+
//set sar2_en_test
707+
SENS.sar_start_force.sar2_en_test = 0;
708+
//set sar2 en force
709+
SENS.sar_meas_start2.sar2_en_pad_force = 0; //Pad bitmap controlled by SW
710+
//set en_pad for channels 7,8,9 (bits 0x380)
711+
SENS.sar_meas_start2.sar2_en_pad = 0;
700712
}
701-
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
702-
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
703-
RTCCNTL.test_mux.dtest_rtc = 1; //Config test mux to route v_ref to ADC2 Channels
704-
//set ent
705-
RTCCNTL.test_mux.ent_rtc = 1;
706-
//set sar2_en_test
707-
SENS.sar_start_force.sar2_en_test = 1;
708-
//set sar2 en force
709-
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
710-
//set en_pad for channels 7,8,9 (bits 0x380)
711-
SENS.sar_meas_start2.sar2_en_pad = 1 << channel;
712-
return true;
713713
}
714714

715715
#ifdef __cplusplus

components/soc/src/esp32s2/include/hal/adc_ll.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,19 @@ typedef enum {
110110
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR 0x2
111111
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
112112
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
113+
114+
#define ADC_LL_SARADC_DTEST_RTC_ADDR 0x7
115+
#define ADC_LL_SARADC_DTEST_RTC_ADDR_MSB 1
116+
#define ADC_LL_SARADC_DTEST_RTC_ADDR_LSB 0
117+
118+
#define ADC_LL_SARADC_ENT_TSENS_ADDR 0x7
119+
#define ADC_LL_SARADC_ENT_TSENS_ADDR_MSB 2
120+
#define ADC_LL_SARADC_ENT_TSENS_ADDR_LSB 2
121+
122+
#define ADC_LL_SARADC_ENT_RTC_ADDR 0x7
123+
#define ADC_LL_SARADC_ENT_RTC_ADDR_MSB 3
124+
#define ADC_LL_SARADC_ENT_RTC_ADDR_LSB 3
125+
113126
/* ADC calibration defines end. */
114127

115128
/*---------------------------------------------------------------
@@ -1248,6 +1261,59 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par
12481261
}
12491262
/* Temp code end. */
12501263

1264+
/**
1265+
* Output ADCn inter reference voltage to ADC2 channels.
1266+
*
1267+
* This function routes the internal reference voltage of ADCn to one of
1268+
* ADC2's channels. This reference voltage can then be manually measured
1269+
* for calibration purposes.
1270+
*
1271+
* @param[in] adc ADC unit select
1272+
* @param[in] channel ADC2 channel number
1273+
* @param[in] en Enable/disable the reference voltage output
1274+
*/
1275+
static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en)
1276+
{
1277+
/* Should be called before writing I2C registers. */
1278+
void phy_get_romfunc_addr(void);
1279+
phy_get_romfunc_addr();
1280+
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M);
1281+
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18));
1282+
SET_PERI_REG_MASK(ADC_LL_ANA_CONFIG2_REG, BIT(16));
1283+
1284+
if (en) {
1285+
if (adc == ADC_NUM_1) {
1286+
/* Config test mux to route v_ref to ADC1 Channels */
1287+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_DTEST_RTC_ADDR, 1);
1288+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_TSENS_ADDR, 0);
1289+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_RTC_ADDR, 1);
1290+
} else {
1291+
/* Config test mux to route v_ref to ADC2 Channels */
1292+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_DTEST_RTC_ADDR, 0);
1293+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_TSENS_ADDR, 1);
1294+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_RTC_ADDR, 0);
1295+
}
1296+
//in sleep force to use rtc to control ADC
1297+
SENS.sar_meas2_mux.sar2_rtc_force = 1;
1298+
//set sar2_en_test
1299+
SENS.sar_meas2_ctrl1.sar2_en_test = 1;
1300+
//set sar2 en force
1301+
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
1302+
//set en_pad for ADC2 channels (bits 0x380)
1303+
SENS.sar_meas2_ctrl2.sar2_en_pad = 1 << channel;
1304+
} else {
1305+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_TSENS_ADDR, 0);
1306+
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_RTC_ADDR, 0);
1307+
SENS.sar_meas2_mux.sar2_rtc_force = 0;
1308+
//set sar2_en_test
1309+
SENS.sar_meas2_ctrl1.sar2_en_test = 0;
1310+
//set sar2 en force
1311+
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; //Pad bitmap controlled by SW
1312+
//set en_pad for ADC2 channels (bits 0x380)
1313+
SENS.sar_meas2_ctrl2.sar2_en_pad = 0;
1314+
}
1315+
}
1316+
12511317
#ifdef __cplusplus
12521318
}
12531319
#endif

docs/en/api-reference/peripherals/adc.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Then it is possible to read ADC conversion result with :cpp:func:`adc1_get_raw`
5353

5454
This API provides convenient way to configure ADC1 for reading from :doc:`ULP <../../api-guides/ulp>`. To do so, call function :cpp:func:`adc1_ulp_enable` and then set precision and attenuation as discussed above.
5555

56-
There is another specific function :cpp:func:`adc2_vref_to_gpio` used to route internal reference voltage to a GPIO pin. It comes handy to calibrate ADC reading and this is discussed in section :ref:`adc-api-adc-calibration`.
56+
There is another specific function :cpp:func:`adc_vref_to_gpio` used to route internal reference voltage to a GPIO pin. It comes handy to calibrate ADC reading and this is discussed in section :ref:`adc-api-adc-calibration`.
5757

5858
.. todo::
5959

@@ -228,7 +228,7 @@ Routing ADC reference voltage to GPIO, so it can be manually measured (for **Def
228228

229229
...
230230

231-
esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25);
231+
esp_err_t status = adc_vref_to_gpio(ADC_UNIT_1, GPIO_NUM_25);
232232
if (status == ESP_OK) {
233233
printf("v_ref routed to GPIO\n");
234234
} else {

0 commit comments

Comments
 (0)