Merge branch 'feature/vdd_sdio_pd_configurable' into 'master'

system: add VDD_SDIO power domain configuration for light sleep

Closes IDFGH-2893

See merge request espressif/esp-idf!12481
pull/6828/head
Angus Gratton 2021-03-26 08:23:41 +00:00
commit 1dfa0e0aa1
4 zmienionych plików z 70 dodań i 27 usunięć

Wyświetl plik

@ -89,7 +89,9 @@ menu "ESP System Settings"
default y
help
If enabled, chip will try to power down flash at light sleep, which costs more time when chip wakes up.
Only can be enabled if there is no SPIRAM configured.
Can only be enabled if there is no SPIRAM configured. This option will in fact consider VDD_SDIO auto power
value (ESP_PD_OPTION_AUTO) as OFF. Also, it is possible to force a power domain to stay ON during light
sleep by using esp_sleep_pd_config() function.
config ESP_SYSTEM_PM_POWER_DOWN_CPU
bool "Power down CPU in light sleep"

Wyświetl plik

@ -50,6 +50,7 @@ typedef enum {
ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory
ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator
ESP_PD_DOMAIN_CPU, //!< CPU core
ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO
ESP_PD_DOMAIN_MAX //!< Number of domains
} esp_sleep_pd_domain_t;

Wyświetl plik

@ -151,7 +151,7 @@ typedef struct {
} sleep_config_t;
static sleep_config_t s_config = {
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
.ccount_ticks_record = 0,
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
.wakeup_triggers = 0
@ -724,35 +724,43 @@ esp_err_t esp_light_sleep_start(void)
// If it needs to be powered down, adjust sleep time.
const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + DEEP_SLEEP_WAKEUP_DELAY;
#if CONFIG_ESP_SYSTEM_PD_FLASH
/*
* When SPIRAM is disabled in menuconfig, the minimum sleep time of the
* system needs to meet the sum below:
* 1. Wait time for the flash power-on after waking up;
* 2. The execution time of codes between RTC Timer get start time
* with hardware starts to switch state to sleep;
* 3. The hardware state switching time of the rtc state machine during
* sleep and wake-up. This process requires 6 cycles to complete.
* The specific hardware state switching process and the cycles
* consumed are rtc_cpu_run_stall(1), cut_pll_rtl(2), cut_8m(1),
* min_protect(2);
* 4. All the adjustment time which is s_config.sleep_time_adjustment below.
/**
* If VDD_SDIO power domain is requested to be turned off, bit `RTC_SLEEP_PD_VDDSDIO`
* will be set in `pd_flags`.
*/
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment
+ rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
/*
* When VDD_SDIO power domain has to be turned off, the minimum sleep time of the
* system needs to meet the sum below:
* 1. Wait time for the flash power-on after waking up;
* 2. The execution time of codes between RTC Timer get start time
* with hardware starts to switch state to sleep;
* 3. The hardware state switching time of the rtc state machine during
* sleep and wake-up. This process requires 6 cycles to complete.
* The specific hardware state switching process and the cycles
* consumed are rtc_cpu_run_stall(1), cut_pll_rtl(2), cut_8m(1),
* min_protect(2);
* 4. All the adjustment time which is s_config.sleep_time_adjustment below.
*/
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment
+ rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
if (s_config.sleep_duration > vddsdio_pd_sleep_duration) {
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
if (s_config.sleep_time_overhead_out < flash_enable_time_us) {
s_config.sleep_time_adjustment += flash_enable_time_us;
}
} else {
if (s_config.sleep_time_overhead_out > flash_enable_time_us) {
s_config.sleep_time_adjustment -= flash_enable_time_us;
if (s_config.sleep_duration > vddsdio_pd_sleep_duration) {
if (s_config.sleep_time_overhead_out < flash_enable_time_us) {
s_config.sleep_time_adjustment += flash_enable_time_us;
}
} else {
/**
* Minimum sleep time is not enough, then keep the VDD_SDIO power
* domain on.
*/
pd_flags &= ~RTC_SLEEP_PD_VDDSDIO;
if (s_config.sleep_time_overhead_out > flash_enable_time_us) {
s_config.sleep_time_adjustment -= flash_enable_time_us;
}
}
}
#endif //CONFIG_ESP_SYSTEM_PD_FLASH
periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in);
@ -1330,6 +1338,27 @@ static uint32_t get_power_down_flags(void)
pd_flags |= RTC_SLEEP_PD_XTAL;
#endif
/**
* VDD_SDIO power domain shall be kept on during the light sleep
* when CONFIG_ESP_SYSTEM_PD_FLASH is not set and off when it is set.
* The application can still force the power domain to remain on by calling
* `esp_sleep_pd_config` before getting into light sleep mode.
*
* In deep sleep mode, the power domain will be turned off, regardless the
* value of this field.
*/
if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_AUTO) {
#ifdef CONFIG_ESP_SYSTEM_PD_FLASH
s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_OFF;
#else
s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_ON;
#endif
}
if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] != ESP_PD_OPTION_ON) {
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
}
#if ((defined CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) && (defined CONFIG_ESP32_RTC_EXT_CRYST_ADDIT_CURRENT))
if ((s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) == 0) {
// If enabled EXT1 only and enable the additional current by touch, should be keep RTC_PERIPH power on.

Wyświetl plik

@ -1,6 +1,8 @@
Sleep Modes
===========
{IDF_TARGET_SPI_POWER_DOMAIN:default="VDD_SPI", esp32="VDD_SDIO"}
Overview
--------
@ -132,6 +134,15 @@ This wakeup mode doesn't require RTC peripherals or RTC memories to be powered o
:cpp:func:`esp_sleep_enable_gpio_wakeup` function can be used to enable this wakeup source.
.. warning::
Before entering light sleep mode, check if any GPIO pin to be driven is part of the {IDF_TARGET_SPI_POWER_DOMAIN} power domain. If so, this power domain must be configured to remain ON during sleep.
For example, on ESP32-WROOM-32 board, GPIO16 and GPIO17 are linked to {IDF_TARGET_SPI_POWER_DOMAIN} power domain. If they are configured to remain high during
light sleep, the power domain should be configured to remain powered ON. This can be done with :cpp:func:`esp_sleep_pd_config()`::
esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);
UART wakeup (light sleep only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^