Skip to content

Commit

Permalink
Merge branch 'refactor/improve_adc_power_maintanance_v4.4' into 'rele…
Browse files Browse the repository at this point in the history
…ase/v4.4'

adc: improve power logic (v4.4)

See merge request espressif/esp-idf!23275
  • Loading branch information
suda-morris committed Jun 20, 2023
2 parents ea9d916 + 2a0a4fa commit 564e20d
Show file tree
Hide file tree
Showing 35 changed files with 1,272 additions and 137 deletions.
19 changes: 10 additions & 9 deletions components/driver/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "soc/i2s_periph.h"
#include "esp_private/i2s_platform.h"
#endif
#include "esp_private/sar_periph_ctrl.h"

static const char *ADC_TAG = "ADC";

Expand Down Expand Up @@ -365,7 +366,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();
sar_periph_ctrl_adc_continuous_power_acquire();
//reset flags
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
s_adc_digi_ctx->driver_start_flag = 1;
Expand Down Expand Up @@ -454,7 +455,7 @@ esp_err_t adc_digi_stop(void)
if (s_adc_digi_ctx->use_adc2) {
SAR_ADC2_LOCK_RELEASE();
}
adc_power_release();
sar_periph_ctrl_adc_continuous_power_release();
}
#if CONFIG_IDF_TARGET_ESP32S2
else {
Expand Down Expand Up @@ -662,7 +663,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
}
}

adc_power_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();
if (adc_unit & ADC_UNIT_1) {
ADC_ENTER_CRITICAL();
adc_hal_vref_output(ADC_NUM_1, channel, true);
Expand Down Expand Up @@ -707,7 +708,7 @@ int adc1_get_raw(adc1_channel_t channel)
int raw_out = 0;

periph_module_enable(PERIPH_SARADC_MODULE);
adc_power_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();

SAR_ADC1_LOCK_ACQUIRE();
adc_ll_digi_clk_sel(0);
Expand All @@ -723,7 +724,7 @@ int adc1_get_raw(adc1_channel_t channel)

SAR_ADC1_LOCK_RELEASE();

adc_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
periph_module_disable(PERIPH_SARADC_MODULE);

return raw_out;
Expand Down Expand Up @@ -758,7 +759,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_periph_ctrl_adc_oneshot_power_acquire();

SAR_ADC2_LOCK_ACQUIRE();
adc_ll_digi_clk_sel(0);
Expand All @@ -777,7 +778,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *

SAR_ADC2_LOCK_RELEASE();

adc_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
periph_module_disable(PERIPH_SARADC_MODULE);

return ret;
Expand Down Expand Up @@ -879,12 +880,12 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a

} else {
ESP_LOGD(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode");
adc_power_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();
ADC_ENTER_CRITICAL();
const bool internal_gnd = true;
init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
ADC_EXIT_CRITICAL();
adc_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
}

s_adc_cali_param[adc_n][atten] = init_code;
Expand Down
67 changes: 16 additions & 51 deletions components/driver/adc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "hal/adc_hal_conf.h"
#include "esp_private/sar_periph_ctrl.h"

#if SOC_DAC_SUPPORTED
#include "driver/dac.h"
Expand Down Expand Up @@ -132,64 +133,28 @@ static esp_pm_lock_handle_t s_adc2_arbiter_lock;
ADC Common
---------------------------------------------------------------*/
// ADC Power

// 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)
{
/* Set the power always on to increase precision. */
adc_hal_set_power_manage(ADC_POWER_SW_ON);
}

void adc_power_acquire(void)
{
ADC_POWER_ENTER();
s_adc_power_on_cnt++;
if (s_adc_power_on_cnt == 1) {
adc_power_on_internal();
}
ADC_POWER_EXIT();
sar_periph_ctrl_adc_oneshot_power_acquire();
sar_periph_ctrl_adc_continuous_power_acquire();
}

void adc_power_on(void)
{
ADC_POWER_ENTER();
adc_power_on_internal();
ADC_POWER_EXIT();
}

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
sar_periph_ctrl_adc_oneshot_power_acquire();
sar_periph_ctrl_adc_continuous_power_acquire();
}

void adc_power_release(void)
{
ADC_POWER_ENTER();
s_adc_power_on_cnt--;
/* Sanity check */
if (s_adc_power_on_cnt < 0) {
ADC_POWER_EXIT();
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();
}
ADC_POWER_EXIT();
sar_periph_ctrl_adc_continuous_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
}

void adc_power_off(void)
{
ADC_POWER_ENTER();
adc_power_off_internal();
ADC_POWER_EXIT();
sar_periph_ctrl_adc_continuous_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
}

esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
Expand Down Expand Up @@ -389,7 +354,7 @@ esp_err_t adc1_dma_mode_acquire(void)
SARADC1_ACQUIRE();
ESP_LOGD( ADC_TAG, "dma mode takes adc1 lock." );

adc_power_acquire();
sar_periph_ctrl_adc_continuous_power_acquire();

SARADC1_ENTER();
/* switch SARADC into DIG channel */
Expand All @@ -404,7 +369,7 @@ esp_err_t adc1_rtc_mode_acquire(void)
/* Use locks to avoid digtal and RTC controller conflicts.
for adc1, block until acquire the lock. */
SARADC1_ACQUIRE();
adc_power_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();

SARADC1_ENTER();
/* switch SARADC into RTC channel. */
Expand All @@ -419,7 +384,7 @@ esp_err_t adc1_lock_release(void)
ADC_CHECK((uint32_t *)adc1_dma_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
/* Use locks to avoid digtal and RTC controller conflicts. for adc1, block until acquire the lock. */

adc_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
SARADC1_RELEASE();
return ESP_OK;
}
Expand Down Expand Up @@ -460,7 +425,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_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();

SARADC1_ENTER();
adc_ll_set_controller(ADC_NUM_1, ADC_LL_CTRL_ULP);
Expand Down Expand Up @@ -583,7 +548,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
//try the lock, return if failed (wifi using).
return ESP_ERR_TIMEOUT;
}
adc_power_acquire(); //in critical section with whole rtc module
sar_periph_ctrl_adc_oneshot_power_acquire(); //in critical section with whole rtc module

//avoid collision with other tasks
adc2_init(); // in critical section with whole rtc module. because the PWDET use the same registers, place it here.
Expand Down Expand Up @@ -628,7 +593,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
#endif //CONFIG_IDF_TARGET_ESP32
SARADC2_EXIT();

adc_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
SARADC2_RELEASE();

*raw_out = adc_value;
Expand Down Expand Up @@ -659,7 +624,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
return ESP_ERR_INVALID_ARG;
}

adc_power_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();
if (adc_unit & ADC_UNIT_1) {
VREF_ENTER(1);
adc_hal_vref_output(ADC_NUM_1, ch, true);
Expand Down
5 changes: 3 additions & 2 deletions components/driver/esp32/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "driver/rtc_cntl.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_private/sar_periph_ctrl.h"

#ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds
Expand All @@ -47,7 +48,7 @@ static int hall_sensor_get_value(void) //hall sensor without LNA
{
int hall_value;

adc_power_acquire();
sar_periph_ctrl_adc_oneshot_power_acquire();

ADC_ENTER_CRITICAL();
/* disable other peripherals. */
Expand All @@ -59,7 +60,7 @@ static int hall_sensor_get_value(void) //hall sensor without LNA
adc_ll_hall_disable();
ADC_EXIT_CRITICAL();

adc_power_release();
sar_periph_ctrl_adc_oneshot_power_release();
return hall_value;
}

Expand Down
3 changes: 2 additions & 1 deletion components/driver/i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "esp_efuse.h"
#include "esp_rom_gpio.h"
#include "esp_private/i2s_platform.h"
#include "esp_private/sar_periph_ctrl.h"

#include "sdkconfig.h"

Expand Down Expand Up @@ -1995,7 +1996,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
#if SOC_I2S_SUPPORTS_ADC
/* If using built-in ADC, we need to enable ADC power manerge*/
if (pre_alloc_i2s_obj->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) {
adc_power_acquire();
sar_periph_ctrl_adc_continuous_power_acquire();
}
#endif
/* Enable module clock */
Expand Down
3 changes: 2 additions & 1 deletion components/esp_hw_support/component.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \
port/$(IDF_TARGET)/cache_sram_mmu.o \
port/$(IDF_TARGET)/esp_himem.o \
port/$(IDF_TARGET)/spiram.o \
port/$(IDF_TARGET)/spiram_psram.o
port/$(IDF_TARGET)/spiram_psram.o \
port/$(IDF_TARGET)/sar_periph_ctrl.o
endif

ifdef CONFIG_IDF_TARGET_ESP32
Expand Down
77 changes: 77 additions & 0 deletions components/esp_hw_support/include/esp_private/sar_periph_ctrl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* SAR related peripherals are interdependent. This file
* provides a united control to these registers, as multiple
* components require these controls.
*
* See target/sar_periph_ctrl.c to know involved peripherals
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

/**
* Initialise SAR related peripheral register settings
* Should only be used when running into app stage
*/
void sar_periph_ctrl_init(void);


/*------------------------------------------------------------------------------
* ADC Power
*----------------------------------------------------------------------------*/
/**
* @brief Acquire the ADC oneshot mode power
*/
void sar_periph_ctrl_adc_oneshot_power_acquire(void);

/**
* @brief Release the ADC oneshot mode power
*/
void sar_periph_ctrl_adc_oneshot_power_release(void);

/**
* @brief Acquire the ADC continuous mode power
*/
void sar_periph_ctrl_adc_continuous_power_acquire(void);

/**
* @brief Release the ADC ADC continuous mode power
*/
void sar_periph_ctrl_adc_continuous_power_release(void);


/*------------------------------------------------------------------------------
* PWDET Power
*----------------------------------------------------------------------------*/
/**
* @brief Acquire the PWDET Power
*/
void sar_periph_ctrl_pwdet_power_acquire(void);

/**
* @brief Release the PWDET Power
*/
void sar_periph_ctrl_pwdet_power_release(void);

/**
* @brief Enable SAR power when system wakes up
*/
void sar_periph_ctrl_power_enable(void);

/**
* @brief Disable SAR power when system goes to sleep
*/
void sar_periph_ctrl_power_disable(void);

#ifdef __cplusplus
}
#endif
3 changes: 2 additions & 1 deletion components/esp_hw_support/port/esp32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ if(NOT BOOTLOADER_BUILD)
"dport_access.c"
"esp_himem.c"
"spiram.c"
"spiram_psram.c")
"spiram_psram.c"
"sar_periph_ctrl.c")
endif()

add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
Expand Down
8 changes: 8 additions & 0 deletions components/esp_hw_support/port/esp32/rtc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include "soc/efuse_periph.h"
#include "hal/efuse_ll.h"
#include "soc/gpio_periph.h"
#ifndef BOOTLOADER_BUILD
#include "esp_private/sar_periph_ctrl.h"
#endif


void rtc_init(rtc_config_t cfg)
Expand Down Expand Up @@ -95,6 +98,11 @@ void rtc_init(rtc_config_t cfg)

REG_WRITE(RTC_CNTL_INT_ENA_REG, 0);
REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX);

#ifndef BOOTLOADER_BUILD
//initialise SAR related peripheral register settings
sar_periph_ctrl_init();
#endif
}

rtc_vddsdio_config_t rtc_vddsdio_get_config(void)
Expand Down
Loading

0 comments on commit 564e20d

Please sign in to comment.