diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index 815942f95b..f77c4e336c 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -92,7 +92,7 @@ static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; #if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL -#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +#if CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP static uint32_t cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) { uint32_t sets; /* i/d-cache total set counts */ @@ -153,11 +153,11 @@ static uint32_t cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t c * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); } -#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +#endif // CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP static esp_err_t esp_sleep_tagmem_pd_low_init(void) { -#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +#if CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP if (s_cpu_retention.retent.tagmem.link_addr == NULL) { extern char _stext[], _etext[]; uint32_t code_start = (uint32_t)_stext; @@ -186,11 +186,11 @@ static esp_err_t esp_sleep_tagmem_pd_low_init(void) return ESP_ERR_NO_MEM; } } -#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +#else // CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP s_cpu_retention.retent.tagmem.icache.enable = 0; s_cpu_retention.retent.tagmem.dcache.enable = 0; s_cpu_retention.retent.tagmem.link_addr = NULL; -#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +#endif // CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP return ESP_OK; } diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 3bfb9e3b24..35a1c000be 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -108,21 +108,31 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" depends on SOC_PM_SUPPORT_CPU_PD - select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB + select PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB default y help - If enabled, the CPU will be powered down in light sleep. On esp32c3 soc, enabling this - option will consume 1.68 KB of internal RAM and will reduce sleep current consumption - by about 100 uA. On esp32s3 soc, enabling this option will consume 8.58 KB of internal - RAM and will reduce sleep current consumption by about 650 uA. + If enabled, the CPU will be powered down in light sleep, ESP chips supports saving and restoring CPU's running + context before and after light sleep, the feature provides applications with seamless CPU powerdowned lightsleep + without user awareness. + But this will takes up some internal memory. On esp32c3 soc, enabling this option will consume 1.68 KB of internal + RAM and will reduce sleep current consumption by about 100 uA. On esp32s3 soc, enabling this option will consume + 8.58 KB of internal RAM and will reduce sleep current consumption by about 650 uA. - config PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - bool "Power down I/D-cache tag memory in light sleep" + config PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP + bool "Restore I/D-cache tag memory after power down CPU light sleep" depends on IDF_TARGET_ESP32S3 && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP default y help - If enabled, the I/D-cache tag memory will be retained in light sleep. Depending on the the - cache configuration, if this option is enabled, it will consume up to 9 KB of internal RAM. + Cache tag memory and CPU both belong to the CPU power domain. ESP chips supports saving and restoring Cache tag memory + before and after sleep, this feature supports accesses to the external memory that was cached before sleep still + be cached when the CPU wakes up from a powerdowned CPU lightsleep. This option controls the restore method for Cache + tag memory in lightsleep. + If this option is enabled, the I/D-cache tag memory will be backuped to the internal RAM before sleep and restored + upon wakeup. Depending on the the cache configuration, if this option is enabled, it will consume up to 9 KB + of internal RAM. + If this option is disabled, all cached data won't be kept after sleep, the DCache will be writeback before + sleep and invalid all cached data after sleep, all accesses to external memory(Flash/PSRAM) will be cache + missed after waking up, resulting in performance degradation due to increased memory accesses latency. config PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP bool "Power down Digital Peripheral in light sleep (EXPERIMENTAL)" diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index b1809a422a..6930c61995 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -97,5 +97,5 @@ entries: if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y: if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) - if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: + if PM_SLP_IRAM_OPT = y && PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP = y: rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 2746965238..c594a3d3db 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -446,8 +446,11 @@ esp_err_t esp_pm_configure(const void* vconfig) min_freq_mhz, config->light_sleep_enable ? "ENABLED" : "DISABLED"); - portENTER_CRITICAL(&s_switch_lock); + // CPU & Modem power down initialization, which must be initialized before s_light_sleep_en set true, + // to avoid entering idle and sleep in this function. + esp_pm_sleep_configure(config); + portENTER_CRITICAL(&s_switch_lock); bool res __attribute__((unused)); res = rtc_clk_cpu_freq_mhz_to_config(max_freq_mhz, &s_cpu_freq_by_mode[PM_MODE_CPU_MAX]); assert(res); @@ -460,8 +463,6 @@ esp_err_t esp_pm_configure(const void* vconfig) s_config_changed = true; portEXIT_CRITICAL(&s_switch_lock); - esp_pm_sleep_configure(config); - return ESP_OK; } diff --git a/components/esp_pm/sdkconfig.rename b/components/esp_pm/sdkconfig.rename index c1ce6dbd66..ecaaa20a8d 100644 --- a/components/esp_pm/sdkconfig.rename +++ b/components/esp_pm/sdkconfig.rename @@ -1,3 +1,4 @@ # sdkconfig replacement configurations for deprecated options formatted as # CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP CONFIG_PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP diff --git a/components/hal/esp32s3/rtc_cntl_hal.c b/components/hal/esp32s3/rtc_cntl_hal.c index 27d3c605be..94c74908b7 100644 --- a/components/hal/esp32s3/rtc_cntl_hal.c +++ b/components/hal/esp32s3/rtc_cntl_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -68,6 +68,14 @@ void rtc_cntl_hal_enable_cpu_retention(void *addr) ); rtc_cntl_ll_enable_cpu_retention_clock(); rtc_cntl_ll_enable_cpu_retention(); +#if SOC_PM_SUPPORT_TAGMEM_PD + if (!retent->tagmem.dcache.enable) { + // Here we only need to care for the safety of the PSRAM data in the DCache. + // Since only rodata, bss, heap data may be placed in PSRAM, and these data won't be + // modified in the sleep process code after now, so it is safe to writeback here. + Cache_WriteBack_All(); + } +#endif } } }