Ver Fonte

Merge branch 'bugfix/fix_psram_access_faild_after_pd_cpu_wakeup' into 'master'

fix(esp_pm): fix psram access failed after pd_cpu wakeup if uart driver driven console is used

Closes WIFIBUG-238

See merge request espressif/esp-idf!27020
Wu Zheng Hui há 2 anos atrás
pai
commit
bb95f9bcc6

+ 5 - 5
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;
 }
 

+ 20 - 10
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.
-
-    config PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
-        bool "Power down I/D-cache tag memory in light sleep"
+            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_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)"

+ 1 - 1
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)

+ 4 - 3
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;
 }
 

+ 1 - 0
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

+ 9 - 1
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
         }
     }
 }