mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-11 02:07:46 +00:00
adc_i2s: solve the i2s_adc issue when using wifi
This commit is contained in:
@@ -75,6 +75,14 @@ In ADC2, there're two locks used for different cases:
|
||||
|
||||
adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.
|
||||
*/
|
||||
// This gets incremented when adc_power_acquire() is called, and decremented when
|
||||
// adc_power_release() is called. ADC is powered down when the value reaches zero.
|
||||
// Should be modified within critical section (ADC_ENTER/EXIT_CRITICAL).
|
||||
static int s_adc_power_on_cnt;
|
||||
|
||||
static void adc_power_on_internal(void);
|
||||
static void adc_power_off_internal(void);
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
//prevent ADC2 being used by wifi and other tasks at the same time.
|
||||
static _lock_t adc2_wifi_lock;
|
||||
@@ -113,36 +121,60 @@ static esp_pm_lock_handle_t s_adc2_arbiter_lock;
|
||||
ADC Common
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
void adc_power_always_on(void)
|
||||
void adc_power_acquire(void)
|
||||
{
|
||||
bool powered_on = false;
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_set_power_manage(ADC_POWER_SW_ON);
|
||||
s_adc_power_on_cnt++;
|
||||
if (s_adc_power_on_cnt == 1) {
|
||||
adc_power_on_internal();
|
||||
powered_on = true;
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
if (powered_on) {
|
||||
ESP_LOGV(ADC_TAG, "%s: ADC powered on", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_power_on(void)
|
||||
void adc_power_release(void)
|
||||
{
|
||||
bool powered_off = false;
|
||||
ADC_ENTER_CRITICAL();
|
||||
s_adc_power_on_cnt--;
|
||||
/* Sanity check */
|
||||
if (s_adc_power_on_cnt < 0) {
|
||||
ADC_EXIT_CRITICAL();
|
||||
ESP_LOGE(ADC_TAG, "%s called, but s_adc_power_on_cnt == 0", __func__);
|
||||
abort();
|
||||
} else if (s_adc_power_on_cnt == 0) {
|
||||
adc_power_off_internal();
|
||||
powered_off = true;
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
if (powered_off) {
|
||||
ESP_LOGV(ADC_TAG, "%s: ADC powered off", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void adc_power_on_internal(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
/* The power FSM controlled mode saves more power, while the ADC noise may get increased. */
|
||||
#ifndef CONFIG_ADC_FORCE_XPD_FSM
|
||||
/* Set the power always on to increase precision. */
|
||||
adc_hal_set_power_manage(ADC_POWER_SW_ON);
|
||||
#else
|
||||
/* Use the FSM to turn off the power while not used to save power. */
|
||||
if (adc_hal_get_power_manage() != ADC_POWER_BY_FSM) {
|
||||
adc_hal_set_power_manage(ADC_POWER_SW_ON);
|
||||
}
|
||||
#endif
|
||||
ADC_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void adc_power_off(void)
|
||||
void adc_power_on(void) __attribute__((alias("adc_power_on_internal")));
|
||||
|
||||
static void adc_power_off_internal(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_set_power_manage(ADC_POWER_SW_OFF);
|
||||
ADC_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void adc_power_off(void) __attribute__((alias("adc_power_off_internal")));
|
||||
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
@@ -335,7 +367,7 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
int adc_value;
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
adc1_rtc_mode_acquire();
|
||||
adc_power_on();
|
||||
adc_power_acquire();
|
||||
|
||||
ADC_ENTER_CRITICAL();
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
@@ -352,6 +384,7 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
adc_hal_rtc_reset(); //Reset FSM of rtc controller
|
||||
#endif
|
||||
|
||||
adc_power_release();
|
||||
adc1_lock_release();
|
||||
return adc_value;
|
||||
}
|
||||
@@ -364,7 +397,7 @@ int adc1_get_voltage(adc1_channel_t channel) //Deprecated. Use adc1_get_raw()
|
||||
#if SOC_ULP_SUPPORTED
|
||||
void adc1_ulp_enable(void)
|
||||
{
|
||||
adc_power_on();
|
||||
adc_power_acquire();
|
||||
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_ULP);
|
||||
@@ -485,12 +518,13 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
adc_power_on(); //in critical section with whole rtc module
|
||||
adc_power_acquire(); //in critical section with whole rtc module
|
||||
|
||||
ADC2_ENTER_CRITICAL(); //avoid collision with other tasks
|
||||
|
||||
if ( ADC2_WIFI_LOCK_TRY_ACQUIRE() == -1 ) { //try the lock, return if failed (wifi using).
|
||||
ADC2_EXIT_CRITICAL();
|
||||
adc_power_release();
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
#ifdef CONFIG_ADC_DISABLE_DAC
|
||||
@@ -532,8 +566,12 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
|
||||
if (adc_value < 0) {
|
||||
ESP_LOGD( ADC_TAG, "ADC2 ARB: Return data is invalid." );
|
||||
adc_power_release();
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
//in critical section with whole rtc module
|
||||
adc_power_release();
|
||||
*raw_out = adc_value;
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -546,7 +584,9 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
adc_power_acquire();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_power_release();
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
@@ -559,6 +599,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
}
|
||||
}
|
||||
if (ch == ADC2_CHANNEL_MAX) {
|
||||
adc_power_release();
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user