From b0684e8b3c36d59f984729313530ec24a69a521e Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Wed, 24 Feb 2021 10:53:24 +0800 Subject: [PATCH 1/2] esp_system: add VDD_SDIO power domain configuration for light sleep VDD_SDIO power domain can now be configured for light sleep by the application. It is now possible to keep the power domain ON during light sleep, keeping the GPIOs connected to it powered. The power domain will, by default be: - Kept ON if CONFIG_ESP_SYSTEM_PD_FLASH is not set - Turned OFF if not set The application can still force it to be ON by calling `esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);` --- components/esp_system/include/esp_sleep.h | 1 + components/esp_system/sleep_modes.c | 81 +++++++++++++++-------- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/components/esp_system/include/esp_sleep.h b/components/esp_system/include/esp_sleep.h index f7f5c2323e..d84933cde5 100644 --- a/components/esp_system/include/esp_sleep.h +++ b/components/esp_system/include/esp_sleep.h @@ -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; diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 7ce4e6c3e4..97e41475e6 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -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 @@ -715,35 +715,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) != 0) { + /* + * 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); @@ -1316,6 +1324,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. From ae3b4819da67b2b9499955430d7aaad2a25d3682 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 4 Mar 2021 17:44:14 +0800 Subject: [PATCH 2/2] esp_system: add VDD_SDIO power domain configuration to documentation Add a warning in `sleep_modes` doc page to explain how to keep VDD_SDIO power domain ON. --- components/esp_system/Kconfig | 4 +++- components/esp_system/sleep_modes.c | 2 +- docs/en/api-reference/system/sleep_modes.rst | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 16171815e8..e82335d2d3 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -88,7 +88,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" diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 97e41475e6..a1786682fe 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -719,7 +719,7 @@ esp_err_t esp_light_sleep_start(void) * If VDD_SDIO power domain is requested to be turned off, bit `RTC_SLEEP_PD_VDDSDIO` * will be set in `pd_flags`. */ - if ((pd_flags & RTC_SLEEP_PD_VDDSDIO) != 0) { + 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: diff --git a/docs/en/api-reference/system/sleep_modes.rst b/docs/en/api-reference/system/sleep_modes.rst index b6db0636ac..15bd3d6854 100644 --- a/docs/en/api-reference/system/sleep_modes.rst +++ b/docs/en/api-reference/system/sleep_modes.rst @@ -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) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^