driver(adc): esp32s2 support API adc2_vref_to_gpio

This commit is contained in:
fuzhibo 2020-06-03 17:38:10 +08:00
parent 934fe37c48
commit 885f8ce484
9 changed files with 180 additions and 78 deletions

View file

@ -535,3 +535,36 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
return ESP_OK;
}
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
{
return adc_vref_to_gpio(ADC_UNIT_2, gpio);
}
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
{
#ifdef CONFIG_IDF_TARGET_ESP32
if (adc_unit & ADC_UNIT_1) return ESP_ERR_INVALID_ARG;
#endif
adc2_channel_t ch = ADC2_CHANNEL_MAX;
/* Check if the GPIO supported. */
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
ch = i;
break;
}
}
if (ch == ADC2_CHANNEL_MAX) return ESP_ERR_INVALID_ARG;
ADC_ENTER_CRITICAL();
adc_hal_set_power_manage(ADC_POWER_SW_ON);
if (adc_unit & ADC_UNIT_1) {
adc_hal_vref_output(ADC_NUM_1, ch, true);
} else if (adc_unit & ADC_UNIT_2) {
adc_hal_vref_output(ADC_NUM_2, ch, true);
}
ADC_EXIT_CRITICAL();
//Configure RTC gpio, Only ADC2's channels IO are supported to output reference voltage.
adc_gpio_init(ADC_UNIT_2, ch);
return ESP_OK;
}

View file

@ -133,22 +133,6 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
RTC controller setting
---------------------------------------------------------------*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
{
ADC_ENTER_CRITICAL();
adc_hal_set_power_manage(ADC_POWER_SW_ON);
ADC_EXIT_CRITICAL();
if (adc_hal_vref_output(gpio) != true) {
return ESP_ERR_INVALID_ARG;
}
//Configure RTC gpio
rtc_gpio_init(gpio);
rtc_gpio_set_direction(gpio, RTC_GPIO_MODE_DISABLED);
rtc_gpio_pullup_dis(gpio);
rtc_gpio_pulldown_dis(gpio);
return ESP_OK;
}
/*---------------------------------------------------------------
HALL SENSOR
---------------------------------------------------------------*/

View file

@ -46,22 +46,6 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
RTC controller setting
---------------------------------------------------------------*/
/**
* @brief Output ADC2 reference voltage to GPIO 25 or 26 or 27
*
* This function utilizes the testing mux exclusive to ADC 2 to route the
* reference voltage one of ADC2's channels. Supported GPIOs are GPIOs
* 25, 26, and 27. This refernce voltage can be manually read from the pin
* and used in the esp_adc_cal component.
*
* @param[in] gpio GPIO number (GPIOs 25, 26 and 27 are supported)
*
* @return
* - ESP_OK: v_ref successfully routed to selected GPIO
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio);
/**
* @brief Read Hall Sensor
*

View file

@ -312,6 +312,40 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
*/
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out);
/**
* @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO.
*
* This function routes the internal reference voltage of ADCn to one of
* ADC2's channels. This reference voltage can then be manually measured
* for calibration purposes.
*
* @note ESP32 only supports output of ADC2's internal reference voltage.
* @param[in] adc_unit ADC unit index
* @param[in] gpio GPIO number (Only ADC2's channels IO are supported)
*
* @return
* - ESP_OK: v_ref successfully routed to selected GPIO
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
*/
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
/**
* @brief Output ADC2 reference voltage to ``adc2_channe_t``'s IO.
*
* This function routes the internal reference voltage of ADCn to one of
* ADC2's channels. This reference voltage can then be manually measured
* for calibration purposes.
*
* @deprecated Use ``adc_vref_to_gpio`` instead.
*
* @param[in] gpio GPIO number (ADC2's channels are supported)
*
* @return
* - ESP_OK: v_ref successfully routed to selected GPIO
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
#ifdef __cplusplus
}
#endif

View file

@ -168,6 +168,20 @@ int adc_hal_convert(adc_ll_num_t adc_n, int channel, int *value);
*/
#define adc_hal_rtc_output_invert(adc_n, inv_en) adc_ll_rtc_output_invert(adc_n, inv_en)
/**
* Enable/disable the output of ADCn's internal reference voltage to one of ADC2's channels.
*
* This function routes the internal reference voltage of ADCn to one of
* ADC2's channels. This reference voltage can then be manually measured
* for calibration purposes.
*
* @note ESP32 only supports output of ADC2's internal reference voltage.
* @param[in] adc ADC unit select
* @param[in] channel ADC2 channel number
* @param[in] en Enable/disable the reference voltage output
*/
#define adc_hal_vref_output(adc, channel, en) adc_ll_vref_output(adc, channel, en)
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/

View file

@ -100,19 +100,6 @@ void adc_hal_digi_deinit(void);
*/
int adc_hal_hall_convert(void);
/**
* @brief Output ADC2 reference voltage to gpio
*
* This function utilizes the testing mux exclusive to ADC2 to route the
* reference voltage one of ADC2's channels.
*
* @param[in] io GPIO number
* @return
* - true: v_ref successfully routed to selected gpio
* - false: Unsupported gpio
*/
#define adc_hal_vref_output(io) adc_ll_vref_output(io)
#ifdef __cplusplus
}
#endif

View file

@ -673,43 +673,43 @@ static inline void adc_ll_set_hall_controller(adc_ll_hall_controller_t hall_ctrl
}
/**
* Output ADC2 reference voltage to gpio 25 or 26 or 27
* Output ADC internal reference voltage to channels, only available for ADC2 on ESP32.
*
* This function utilizes the testing mux exclusive to ADC 2 to route the
* reference voltage one of ADC2's channels. Supported gpios are gpios
* 25, 26, and 27. This refernce voltage can be manually read from the pin
* and used in the esp_adc_cal component.
* This function routes the internal reference voltage of ADCn to one of
* ADC2's channels. This reference voltage can then be manually measured
* for calibration purposes.
*
* @param[in] io GPIO number (gpios 25,26,27 supported)
*
* @return
* - true: v_ref successfully routed to selected gpio
* - false: Unsupported gpio
* @param[in] adc ADC unit select
* @param[in] channel ADC2 channel number
* @param[in] en Enable/disable the reference voltage output
*/
static inline bool adc_ll_vref_output(int io)
static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en)
{
int channel;
if (io == 25) {
channel = 8; //Channel 8 bit
} else if (io == 26) {
channel = 9; //Channel 9 bit
} else if (io == 27) {
channel = 7; //Channel 7 bit
if (adc != ADC_NUM_2) return;
if (en) {
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
RTCCNTL.test_mux.dtest_rtc = 1; //Config test mux to route v_ref to ADC2 Channels
//set ent
RTCCNTL.test_mux.ent_rtc = 1;
//set sar2_en_test
SENS.sar_start_force.sar2_en_test = 1;
//set sar2 en force
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
//set en_pad for channels 7,8,9 (bits 0x380)
SENS.sar_meas_start2.sar2_en_pad = 1 << channel;
} else {
return false;
RTCCNTL.test_mux.dtest_rtc = 0; //Config test mux to route v_ref to ADC2 Channels
//set ent
RTCCNTL.test_mux.ent_rtc = 0;
//set sar2_en_test
SENS.sar_start_force.sar2_en_test = 0;
//set sar2 en force
SENS.sar_meas_start2.sar2_en_pad_force = 0; //Pad bitmap controlled by SW
//set en_pad for channels 7,8,9 (bits 0x380)
SENS.sar_meas_start2.sar2_en_pad = 0;
}
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
RTCCNTL.test_mux.dtest_rtc = 1; //Config test mux to route v_ref to ADC2 Channels
//set ent
RTCCNTL.test_mux.ent_rtc = 1;
//set sar2_en_test
SENS.sar_start_force.sar2_en_test = 1;
//set sar2 en force
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
//set en_pad for channels 7,8,9 (bits 0x380)
SENS.sar_meas_start2.sar2_en_pad = 1 << channel;
return true;
}
#ifdef __cplusplus

View file

@ -110,6 +110,19 @@ typedef enum {
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR 0x2
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
#define ADC_LL_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
#define ADC_LL_SARADC_DTEST_RTC_ADDR 0x7
#define ADC_LL_SARADC_DTEST_RTC_ADDR_MSB 1
#define ADC_LL_SARADC_DTEST_RTC_ADDR_LSB 0
#define ADC_LL_SARADC_ENT_TSENS_ADDR 0x7
#define ADC_LL_SARADC_ENT_TSENS_ADDR_MSB 2
#define ADC_LL_SARADC_ENT_TSENS_ADDR_LSB 2
#define ADC_LL_SARADC_ENT_RTC_ADDR 0x7
#define ADC_LL_SARADC_ENT_RTC_ADDR_MSB 3
#define ADC_LL_SARADC_ENT_RTC_ADDR_LSB 3
/* ADC calibration defines end. */
/*---------------------------------------------------------------
@ -1248,6 +1261,59 @@ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t par
}
/* Temp code end. */
/**
* Output ADCn inter reference voltage to ADC2 channels.
*
* This function routes the internal reference voltage of ADCn to one of
* ADC2's channels. This reference voltage can then be manually measured
* for calibration purposes.
*
* @param[in] adc ADC unit select
* @param[in] channel ADC2 channel number
* @param[in] en Enable/disable the reference voltage output
*/
static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, bool en)
{
/* Should be called before writing I2C registers. */
void phy_get_romfunc_addr(void);
phy_get_romfunc_addr();
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M);
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18));
SET_PERI_REG_MASK(ADC_LL_ANA_CONFIG2_REG, BIT(16));
if (en) {
if (adc == ADC_NUM_1) {
/* Config test mux to route v_ref to ADC1 Channels */
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_DTEST_RTC_ADDR, 1);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_TSENS_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_RTC_ADDR, 1);
} else {
/* Config test mux to route v_ref to ADC2 Channels */
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_DTEST_RTC_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_TSENS_ADDR, 1);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_RTC_ADDR, 0);
}
//in sleep force to use rtc to control ADC
SENS.sar_meas2_mux.sar2_rtc_force = 1;
//set sar2_en_test
SENS.sar_meas2_ctrl1.sar2_en_test = 1;
//set sar2 en force
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
//set en_pad for ADC2 channels (bits 0x380)
SENS.sar_meas2_ctrl2.sar2_en_pad = 1 << channel;
} else {
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_TSENS_ADDR, 0);
I2C_WRITEREG_MASK_RTC(ADC_LL_I2C_ADC, ADC_LL_SARADC_ENT_RTC_ADDR, 0);
SENS.sar_meas2_mux.sar2_rtc_force = 0;
//set sar2_en_test
SENS.sar_meas2_ctrl1.sar2_en_test = 0;
//set sar2 en force
SENS.sar_meas2_ctrl2.sar2_en_pad_force = 0; //Pad bitmap controlled by SW
//set en_pad for ADC2 channels (bits 0x380)
SENS.sar_meas2_ctrl2.sar2_en_pad = 0;
}
}
#ifdef __cplusplus
}
#endif

View file

@ -53,7 +53,7 @@ Then it is possible to read ADC conversion result with :cpp:func:`adc1_get_raw`
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.
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`.
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`.
.. todo::
@ -228,7 +228,7 @@ Routing ADC reference voltage to GPIO, so it can be manually measured (for **Def
...
esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25);
esp_err_t status = adc_vref_to_gpio(ADC_UNIT_1, GPIO_NUM_25);
if (status == ESP_OK) {
printf("v_ref routed to GPIO\n");
} else {