Kaynağa Gözat

driver(adc): esp32s2 support API adc2_vref_to_gpio

fuzhibo 5 yıl önce
ebeveyn
işleme
885f8ce484

+ 33 - 0
components/driver/adc_common.c

@@ -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;
+}

+ 0 - 16
components/driver/esp32/adc.c

@@ -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
 ---------------------------------------------------------------*/

+ 0 - 16
components/driver/esp32/include/driver/adc.h

@@ -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
  *

+ 34 - 0
components/driver/include/driver/adc_common.h

@@ -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

+ 14 - 0
components/soc/include/hal/adc_hal.h

@@ -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
 ---------------------------------------------------------------*/

+ 0 - 13
components/soc/src/esp32/include/hal/adc_hal.h

@@ -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

+ 35 - 35
components/soc/src/esp32/include/hal/adc_ll.h

@@ -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
- *
- *  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]  io    GPIO number (gpios 25,26,27 supported)
- *
- *  @return
- *                  - true: v_ref successfully routed to selected gpio
- *                  - false: Unsupported gpio
- */
-static inline bool adc_ll_vref_output(int io)
-{
-    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
+ *  Output ADC internal reference voltage to channels, only available for ADC2 on ESP32.
+ *
+ *  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)
+{
+    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

+ 66 - 0
components/soc/src/esp32s2/include/hal/adc_ll.h

@@ -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

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

@@ -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 {