Просмотр исходного кода

light sleep: separate sleep retention function

Li Shuai 4 лет назад
Родитель
Сommit
15fc449793

+ 3 - 0
components/esp_hw_support/CMakeLists.txt

@@ -18,6 +18,9 @@ if(NOT BOOTLOADER_BUILD)
                      "sleep_gpio.c"
                      "sleep_mac_bb.c"
                      "regi2c_ctrl.c")
+    if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2)
+        list(APPEND srcs "sleep_retention.c")
+    endif()
     list(APPEND requires esp_ipc)
 else()
     # Requires "_esp_error_check_failed()" function

+ 10 - 0
components/esp_hw_support/component.mk

@@ -6,6 +6,9 @@ ifdef IS_BOOTLOADER_BUILD
 COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \
 						intr_alloc.o \
 						sleep_modes.o \
+						sleep_gpio.o \
+						sleep_mac_bb.o \
+						sleep_retention.o \
 						esp_async_memcpy.o \
 						mac_addr.o \
 						regi2c_ctrl.o \
@@ -16,4 +19,11 @@ COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \
 						port/$(IDF_TARGET)/spiram_psram.o
 endif
 
+ifdef CONFIG_IDF_TARGET_ESP32
+COMPONENT_OBJEXCLUDE += sleep_retention.o
+endif
+ifdef CONFIG_IDF_TARGET_ESP32S2
+COMPONENT_OBJEXCLUDE += sleep_retention.o
+endif
+
 COMPONENT_OBJEXCLUDE += esp_async_memcpy.o

+ 55 - 0
components/esp_hw_support/include/esp_private/sleep_retention.h

@@ -0,0 +1,55 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+#include <stdint.h>
+#include "sdkconfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file sleep_retention.h
+ *
+ * This file contains declarations of memory retention related functions in light sleeo mode.
+ */
+
+#if SOC_PM_SUPPORT_CPU_PD
+
+/**
+ * @brief Whether to allow the cpu power domain to be powered off.
+ *
+ * In light sleep mode, only when the system can provide enough memory
+ * for cpu retention, the cpu power domain can be powered off.
+ */
+bool cpu_domain_pd_allowed(void);
+
+#endif
+
+#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
+
+/**
+ * @brief Enable memory retention of some modules.
+ *
+ * In light sleep mode, before the system goes to sleep, enable the memory
+ * retention of modules such as CPU and I/D-cache tag memory.
+ */
+void sleep_enable_memory_retention(void);
+
+/**
+ * @brief Disable memory retention of some modules.
+ *
+ * In light sleep mode, after the system exits sleep, disable the memory
+ * retention of moudles such as CPU and I/D-cache tag memory.
+ */
+void sleep_disable_memory_retention(void);
+
+#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
+
+#ifdef __cplusplus
+}
+#endif

+ 2 - 0
components/esp_hw_support/include/esp_sleep.h

@@ -41,7 +41,9 @@ typedef enum {
     ESP_PD_DOMAIN_RTC_SLOW_MEM,    //!< RTC slow memory
     ESP_PD_DOMAIN_RTC_FAST_MEM,    //!< RTC fast memory
     ESP_PD_DOMAIN_XTAL,            //!< XTAL oscillator
+#if SOC_PM_SUPPORT_CPU_PD
     ESP_PD_DOMAIN_CPU,             //!< CPU core
+#endif
     ESP_PD_DOMAIN_VDDSDIO,         //!< VDD_SDIO
     ESP_PD_DOMAIN_MAX              //!< Number of domains
 } esp_sleep_pd_domain_t;

+ 36 - 56
components/esp_hw_support/sleep_modes.c

@@ -43,6 +43,7 @@
 #include "esp_rom_uart.h"
 #include "esp_rom_sys.h"
 #include "brownout.h"
+#include "esp_private/sleep_retention.h"
 
 #ifdef CONFIG_IDF_TARGET_ESP32
 #include "esp32/rom/cache.h"
@@ -67,14 +68,12 @@
 #include "esp32c3/rom/cache.h"
 #include "esp32c3/rom/rtc.h"
 #include "soc/extmem_reg.h"
-#include "esp_heap_caps.h"
 #include "esp_private/sleep_mac_bb.h"
 #elif CONFIG_IDF_TARGET_ESP32H2
 #include "esp32h2/clk.h"
 #include "esp32h2/rom/cache.h"
 #include "esp32h2/rom/rtc.h"
 #include "soc/extmem_reg.h"
-#include "esp_heap_caps.h"
 #endif
 
 // If light sleep time is less than that, don't power down flash
@@ -151,13 +150,16 @@ typedef struct {
     uint32_t sleep_time_overhead_out;
     uint32_t rtc_clk_cal_period;
     uint64_t rtc_ticks_at_sleep_start;
-#if SOC_PM_SUPPORT_CPU_PD
-    void     *cpu_pd_mem;
-#endif
 } 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, ESP_PD_OPTION_AUTO },
+    .pd_options = {
+        ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO,
+#if SOC_PM_SUPPORT_CPU_PD
+        ESP_PD_OPTION_AUTO,
+#endif
+        ESP_PD_OPTION_AUTO
+    },
     .ccount_ticks_record = 0,
     .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
     .wakeup_triggers = 0
@@ -278,33 +280,33 @@ static void IRAM_ATTR resume_uarts(void)
     }
 }
 
-inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu);
+inline static void IRAM_ATTR misc_modules_sleep_prepare(void)
+{
+#if CONFIG_MAC_BB_PD
+    mac_bb_power_down_cb_execute();
+#endif
+#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
+    gpio_sleep_mode_config_apply();
+#endif
+#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
+    sleep_enable_memory_retention();
+#endif
+}
 
-#if SOC_PM_SUPPORT_CPU_PD
-esp_err_t esp_sleep_cpu_pd_low_init(bool enable)
+inline static void IRAM_ATTR misc_modules_wake_prepare(void)
 {
-    if (enable) {
-        if (s_config.cpu_pd_mem == NULL) {
-            void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
-                                                SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
-                                                MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT);
-            if (buf) {
-                memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE);
-                s_config.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
-                                      buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
-            } else {
-                return ESP_ERR_NO_MEM;
-            }
-        }
-    } else {
-        if (s_config.cpu_pd_mem) {
-            heap_caps_free(s_config.cpu_pd_mem);
-            s_config.cpu_pd_mem = NULL;
-        }
-    }
-    return ESP_OK;
+#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
+    sleep_disable_memory_retention();
+#endif
+#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
+    gpio_sleep_mode_config_unapply();
+#endif
+#if CONFIG_MAC_BB_PD
+    mac_bb_power_up_cb_execute();
+#endif
 }
-#endif // SOC_PM_SUPPORT_CPU_PD
+
+inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu);
 
 static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
 {
@@ -333,10 +335,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
     rtc_clk_cpu_freq_get_config(&cpu_freq_config);
     rtc_clk_cpu_freq_set_xtal();
 
-#if CONFIG_MAC_BB_PD
-    mac_bb_power_down_cb_execute();
-#endif
-
 #if SOC_PM_SUPPORT_EXT_WAKEUP
     // Configure pins for external wakeup
     if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
@@ -358,11 +356,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
     if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) {
         rtc_hal_ulp_wakeup_enable();
     }
-#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
-    gpio_sleep_mode_config_apply();
-#endif
 #endif
 
+    misc_modules_sleep_prepare();
+
 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
     if (deep_sleep) {
         if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) {
@@ -443,17 +440,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
         s_config.ccount_ticks_record = cpu_ll_get_cycle_count();
     }
 
-#if SOC_PM_SUPPORT_CPU_PD
-    rtc_cntl_hal_disable_cpu_retention();
-#endif
+    misc_modules_wake_prepare();
 
-#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
-    gpio_sleep_mode_config_unapply();
-#endif
-
-#if CONFIG_MAC_BB_PD
-    mac_bb_power_up_cb_execute();
-#endif
     // re-enable UART output
     resume_uarts();
 
@@ -637,10 +625,6 @@ esp_err_t esp_light_sleep_start(void)
 
     periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in);
 
-#if SOC_PM_SUPPORT_CPU_PD
-    rtc_cntl_hal_enable_cpu_retention(s_config.cpu_pd_mem);
-#endif
-
     rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
 
     // Safety net: enable WDT in case exit from light sleep fails
@@ -1176,11 +1160,7 @@ static uint32_t get_power_down_flags(void)
     }
 
 #if SOC_PM_SUPPORT_CPU_PD
-    if (s_config.cpu_pd_mem == NULL) {
-        s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
-    }
-#else
-    if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) {
+    if (!cpu_domain_pd_allowed()) {
         s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
     }
 #endif

+ 81 - 0
components/esp_hw_support/sleep_retention.c

@@ -0,0 +1,81 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <sys/lock.h>
+#include <sys/param.h>
+
+#include "esp_attr.h"
+#include "esp_sleep.h"
+#include "esp_log.h"
+#include "esp_heap_caps.h"
+#include "soc/soc_caps.h"
+#include "hal/rtc_hal.h"
+#include "esp_private/sleep_retention.h"
+#include "sdkconfig.h"
+
+/**
+ * Internal structure which holds all requested light sleep memory retention parameters
+ */
+typedef struct {
+    rtc_cntl_sleep_retent_t retent;
+} sleep_retention_t;
+
+static DRAM_ATTR sleep_retention_t s_retention;
+
+#if SOC_PM_SUPPORT_CPU_PD
+
+#define CPU_PD_MEM_TYPE_CAPS        (MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT)
+
+esp_err_t esp_sleep_cpu_pd_low_init(bool enable)
+{
+    if (enable) {
+        if (s_retention.retent.cpu_pd_mem == NULL) {
+            void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
+                                                SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
+                                                CPU_PD_MEM_TYPE_CAPS);
+            if (buf) {
+                memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE);
+                s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
+                                      buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
+            } else {
+                return ESP_ERR_NO_MEM;
+            }
+        }
+    } else {
+        if (s_retention.retent.cpu_pd_mem) {
+            heap_caps_free(s_retention.retent.cpu_pd_mem);
+            s_retention.retent.cpu_pd_mem = NULL;
+        }
+    }
+    return ESP_OK;
+}
+
+bool cpu_domain_pd_allowed(void)
+{
+    return (s_retention.retent.cpu_pd_mem != NULL);
+}
+
+#endif // SOC_PM_SUPPORT_CPU_PD
+
+#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
+
+void sleep_enable_memory_retention(void)
+{
+#if SOC_PM_SUPPORT_CPU_PD
+    rtc_cntl_hal_enable_cpu_retention(&s_retention.retent);
+#endif
+}
+
+void IRAM_ATTR sleep_disable_memory_retention(void)
+{
+#if SOC_PM_SUPPORT_CPU_PD
+    rtc_cntl_hal_disable_cpu_retention(&s_retention.retent);
+#endif
+}
+
+#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD

+ 3 - 0
components/esp_pm/linker.lf

@@ -21,6 +21,9 @@ entries:
         esp_clk:esp_rtc_get_time_us (noflash)
         if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y:
             sleep_gpio:gpio_sleep_mode_config_apply (noflash)
+        if IDF_TARGET_ESP32 = n && IDF_TARGET_ESP32S2 = n:
+            sleep_retention:sleep_enable_memory_retention (noflash)
+            sleep_retention:cpu_domain_pd_allowed (noflash)
 
 [mapping:esp_system_pm]
 archive: libesp_system.a