Просмотр исходного кода

Merge branch 'bugfix/adc_power_issue' into 'master'

adc: fix adc power issue

Closes IDF-2954, WIFI-3453, WIFI-3462, IDFGH-4439, and IDFGH-4887

See merge request espressif/esp-idf!12757
Michael (XIAO Xufeng) 4 лет назад
Родитель
Сommit
99aaebb5e4

+ 4 - 0
components/driver/adc_common.c

@@ -177,7 +177,11 @@ void adc_power_on(void)
 
 static void adc_power_off_internal(void)
 {
+#if CONFIG_IDF_TARGET_ESP32
     adc_hal_set_power_manage(ADC_POWER_SW_OFF);
+#else
+    adc_hal_set_power_manage(ADC_POWER_BY_FSM);
+#endif
 }
 
 void adc_power_release(void)

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

@@ -135,6 +135,7 @@ esp_err_t adc_digi_init(void)
 
 esp_err_t adc_digi_deinit(void)
 {
+    adc_power_release();
     ADC_ENTER_CRITICAL();
     adc_hal_digi_deinit();
     ADC_EXIT_CRITICAL();
@@ -143,6 +144,8 @@ esp_err_t adc_digi_deinit(void)
 
 esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
 {
+    /* If enable digital controller, adc xpd should always on. */
+    adc_power_acquire();
     ADC_ENTER_CRITICAL();
     adc_hal_digi_controller_config(config);
     ADC_EXIT_CRITICAL();

+ 7 - 5
components/driver/esp32c3/adc.c

@@ -287,6 +287,7 @@ esp_err_t adc_digi_start(void)
         ESP_LOGE(ADC_TAG, "The driver is already started");
         return ESP_ERR_INVALID_STATE;
     }
+    adc_power_acquire();
     //reset flags
     s_adc_digi_ctx->ringbuf_overflow_flag = 0;
     s_adc_digi_ctx->driver_start_flag = 1;
@@ -356,6 +357,7 @@ esp_err_t adc_digi_stop(void)
     if (s_adc_digi_ctx->use_adc2) {
         SAR_ADC2_LOCK_RELEASE();
     }
+    adc_power_release();
 
     return ESP_OK;
 }
@@ -450,7 +452,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
         }
     }
 
-    adc_hal_set_power_manage(ADC_POWER_SW_ON);
+    adc_power_acquire();
     if (adc_unit & ADC_UNIT_1) {
         ADC_ENTER_CRITICAL();
         adc_hal_vref_output(ADC_NUM_1, channel, true);
@@ -495,6 +497,7 @@ int adc1_get_raw(adc1_channel_t channel)
     int raw_out = 0;
 
     periph_module_enable(PERIPH_SARADC_MODULE);
+    adc_power_acquire();
 
     SAR_ADC1_LOCK_ACQUIRE();
 
@@ -503,14 +506,13 @@ int adc1_get_raw(adc1_channel_t channel)
     adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
 
     ADC_REG_LOCK_ENTER();
-    adc_hal_set_power_manage(ADC_POWER_SW_ON);
     adc_hal_set_atten(ADC_NUM_2, channel, atten);
     adc_hal_convert(ADC_NUM_1, channel, &raw_out);
-    adc_hal_set_power_manage(ADC_POWER_BY_FSM);
     ADC_REG_LOCK_EXIT();
 
     SAR_ADC1_LOCK_RELEASE();
 
+    adc_power_release();
     periph_module_disable(PERIPH_SARADC_MODULE);
 
     return raw_out;
@@ -540,6 +542,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
     esp_err_t ret = ESP_OK;
 
     periph_module_enable(PERIPH_SARADC_MODULE);
+    adc_power_acquire();
 
     SAR_ADC2_LOCK_ACQUIRE();
 
@@ -548,14 +551,13 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
     adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
 
     ADC_REG_LOCK_ENTER();
-    adc_hal_set_power_manage(ADC_POWER_SW_ON);
     adc_hal_set_atten(ADC_NUM_2, channel, atten);
     ret = adc_hal_convert(ADC_NUM_2, channel, raw_out);
-    adc_hal_set_power_manage(ADC_POWER_BY_FSM);
     ADC_REG_LOCK_EXIT();
 
     SAR_ADC2_LOCK_RELEASE();
 
+    adc_power_release();
     periph_module_disable(PERIPH_SARADC_MODULE);
 
     return ret;

+ 3 - 0
components/driver/esp32s2/adc.c

@@ -89,6 +89,7 @@ esp_err_t adc_digi_deinit(void)
         s_adc_digi_arbiter_lock = NULL;
     }
 #endif
+    adc_power_release();
     ADC_ENTER_CRITICAL();
     adc_hal_digi_deinit();
     ADC_EXIT_CRITICAL();
@@ -124,6 +125,8 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
         }
     }
 
+    /* If enable digtal controller, adc xpd should always on. */
+    adc_power_acquire();
     ADC_ENTER_CRITICAL();
     adc_hal_digi_controller_config(config);
     ADC_EXIT_CRITICAL();

+ 2 - 4
components/hal/adc_hal.c

@@ -43,10 +43,6 @@ void adc_hal_init(void)
     adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT);
 }
 
-void adc_hal_deinit(void)
-{
-    adc_ll_set_power_manage(ADC_POWER_SW_OFF);
-}
 /*---------------------------------------------------------------
                     ADC calibration setting
 ---------------------------------------------------------------*/
@@ -381,6 +377,8 @@ esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw)
     adc_hal_onetime_start();
     while (!adc_hal_intr_get_raw(event));
     ret = adc_hal_single_read(adc_n, out_raw);
+    //HW workaround: when enabling periph clock, this should be false
+    adc_ll_onetime_sample_enable(adc_n, false);
 
     return ret;
 }

+ 0 - 3
components/hal/esp32/adc_hal.c

@@ -22,13 +22,10 @@ void adc_hal_digi_deinit(void)
 {
     adc_ll_digi_clear_pattern_table(ADC_NUM_1);
     adc_ll_digi_clear_pattern_table(ADC_NUM_2);
-    adc_hal_deinit();
 }
 
 void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
 {
-    /* If enable digital controller, adc xpd should always on. */
-    adc_ll_set_power_manage(ADC_POWER_SW_ON);
     /* Single channel mode or multi channel mode. */
     adc_ll_digi_set_convert_mode(cfg->conv_mode);
     if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {

+ 0 - 3
components/hal/esp32c3/adc_hal.c

@@ -42,7 +42,6 @@ void adc_hal_digi_deinit(void)
     adc_ll_digi_filter_reset(ADC_NUM_2);
     adc_ll_digi_reset();
     adc_ll_digi_controller_clk_disable();
-    adc_hal_deinit();
 }
 
 /**
@@ -62,8 +61,6 @@ void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
     //only one pattern table is supported on C3, but LL still needs one argument.
     const int pattern_both = 0;
 
-    /* If enable digtal controller, adc xpd should always on. */
-    adc_ll_set_power_manage(ADC_POWER_SW_ON);
     if (cfg->adc_pattern_len) {
         adc_ll_digi_clear_pattern_table(pattern_both);
         adc_ll_digi_set_pattern_table_len(pattern_both, cfg->adc_pattern_len);

+ 0 - 3
components/hal/esp32s2/adc_hal.c

@@ -33,13 +33,10 @@ void adc_hal_digi_deinit(void)
     adc_ll_digi_filter_reset(ADC_NUM_2);
     adc_ll_digi_reset();
     adc_ll_digi_controller_clk_disable();
-    adc_hal_deinit();
 }
 
 void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
 {
-    /* If enable digtal controller, adc xpd should always on. */
-    adc_ll_set_power_manage(ADC_POWER_SW_ON);
     /* Single channel mode or multi channel mode. */
     adc_ll_digi_set_convert_mode(cfg->conv_mode);
     if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {

+ 0 - 5
components/hal/include/hal/adc_hal.h

@@ -61,11 +61,6 @@ typedef struct adc_hal_context_t {
  */
 void adc_hal_init(void);
 
-/**
- * ADC module deinitialization.
- */
-void adc_hal_deinit(void);
-
 /**
  * Set ADC module power management.
  *