Forráskód Böngészése

deep sleep: add deep sleep support for esp32s3

Li Shuai 4 éve
szülő
commit
881e1b0fd5

+ 46 - 4
components/esp_hw_support/sleep_modes.c

@@ -188,12 +188,41 @@ static void touch_wakeup_prepare(void);
 static void esp_deep_sleep_wakeup_prepare(void);
 #endif
 
+#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
+static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL;
+
+static void RTC_IRAM_ATTR __attribute__((used, noinline)) esp_wake_stub_start(void)
+{
+    if (wake_stub_fn_handler) {
+        (*wake_stub_fn_handler)();
+    }
+}
+
+/* We must have a default deep sleep wake stub entry function, which must be
+ * located at the start address of the RTC fast memory, and its implementation
+ * must be simple enough to ensure that there is no litteral data before the
+ * wake stub entry, otherwise, the litteral data before the wake stub entry
+ * will not be CRC checked. */
+static void __attribute__((section(".rtc.entry.text"))) esp_wake_stub_entry(void)
+{
+#define _SYM2STR(s) # s
+#define SYM2STR(s)  _SYM2STR(s)
+    // call4 has a larger effective addressing range (-524284 to 524288 bytes),
+    // which is sufficient for instruction addressing in RTC fast memory.
+    __asm__ __volatile__ ("call4 " SYM2STR(esp_wake_stub_start) "\n");
+}
+#endif // SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
+
 /* Wake from deep sleep stub
    See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
 */
 esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
 {
+#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
+    esp_deep_sleep_wake_stub_fn_t stub_ptr = wake_stub_fn_handler;
+#else
     esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
+#endif
     if (!esp_ptr_executable(stub_ptr)) {
         return NULL;
     }
@@ -202,7 +231,11 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
 
 void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
 {
+#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
+    wake_stub_fn_handler = new_stub;
+#else
     REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
+#endif
 }
 
 void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void)
@@ -416,18 +449,27 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
          */
         portENTER_CRITICAL(&spinlock_rtc_deep_sleep);
 
+#if SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
+        extern char _rtc_text_start[];
+#if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM
+        extern char _rtc_noinit_end[];
+        size_t rtc_fast_length = (size_t)_rtc_noinit_end - (size_t)_rtc_text_start;
+#else
+        extern char _rtc_force_fast_end[];
+        size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start;
+#endif
+        esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length);
+        result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
+#else
 #if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
         /* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
-#if CONFIG_IDF_TARGET_ESP32S3//TODO: WIFI-3542
-        result = 0;
-#else
         set_rtc_memory_crc();
         result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
-#endif
 #else
         /* Otherwise, need to call the dedicated soc function for this */
         result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
 #endif
+#endif // SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
 
         portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
     } else {

+ 21 - 25
components/esp_rom/include/esp32s3/rom/rtc.h

@@ -62,6 +62,7 @@ extern "C" {
 #define RTC_BOOT_TIME_LOW_REG   RTC_CNTL_STORE2_REG
 #define RTC_BOOT_TIME_HIGH_REG  RTC_CNTL_STORE3_REG
 #define RTC_XTAL_FREQ_REG       RTC_CNTL_STORE4_REG
+#define RTC_ENTRY_LENGTH_REG    RTC_CNTL_STORE5_REG
 #define RTC_ENTRY_ADDR_REG      RTC_CNTL_STORE6_REG
 #define RTC_RESET_CAUSE_REG     RTC_CNTL_STORE6_REG
 #define RTC_MEMORY_CRC_REG      RTC_CNTL_STORE7_REG
@@ -173,16 +174,31 @@ RESET_REASON rtc_get_reset_reason(int cpu_no);
   */
 WAKEUP_REASON rtc_get_wakeup_cause(void);
 
+typedef void (* esp_rom_wake_func_t)(void);
+
+/**
+  * @brief Read stored RTC wake function address
+  *
+  * Returns pointer to wake address if a value is set in RTC registers, and stored length & CRC all valid.
+  *
+  * @param  None
+  *
+  * @return esp_rom_wake_func_t : Returns pointer to wake address if a value is set in RTC registers
+  */
+esp_rom_wake_func_t esp_rom_get_rtc_wake_addr(void);
+
 /**
-  * @brief Get CRC for Fast RTC Memory.
+  * @brief Store new RTC wake function address
   *
-  * @param  uint32_t start_addr : 0 - 0x7ff for Fast RTC Memory.
+  * Set a new RTC wake address function. If a non-NULL function pointer is set then the function
+  * memory is calculated and stored also.
   *
-  * @param  uint32_t crc_len : 0 - 0x7ff, 0 for 4 byte, 0x7ff for 0x2000 byte.
+  * @param entry_addr Address of function. If NULL, length is ignored and all registers are cleared to 0.
+  * @param length of function in RTC fast memory. cannot be larger than RTC Fast memory size.
   *
-  * @return uint32_t : CRC32 result
+  * @return None
   */
-uint32_t calc_rtc_memory_crc(uint32_t start_addr, uint32_t crc_len);
+void esp_rom_set_rtc_wake_addr(esp_rom_wake_func_t entry_addr, size_t length);
 
 /**
   * @brief Suppress ROM log by setting specific RTC control register.
@@ -202,26 +218,6 @@ static inline void rtc_suppress_rom_log(void)
     REG_SET_BIT(RTC_CNTL_STORE4_REG, RTC_DISABLE_ROM_LOG);
 }
 
-/**
-  * @brief Set CRC of Fast RTC memory 0-0x7ff into RTC STORE7.
-  *
-  * @param  None
-  *
-  * @return None
-  */
-void set_rtc_memory_crc(void);
-
-/**
-  * @brief Fetch entry from RTC memory and RTC STORE reg
-  *
-  * @param uint32_t * entry_addr : the address to save entry
-  *
-  * @param RESET_REASON reset_reason : reset reason this time
-  *
-  * @return None
-  */
-void rtc_boot_control(uint32_t *entry_addr, RESET_REASON reset_reason);
-
 /**
   * @brief Software Reset digital core.
   *

+ 2 - 0
components/esp_system/ld/esp32s3/sections.ld.in

@@ -18,6 +18,8 @@ SECTIONS
   .rtc.text :
   {
     . = ALIGN(4);
+    _rtc_text_start = ABSOLUTE(.);
+    *(.rtc.entry.text)
 
     mapping[rtc_text]
 

+ 3 - 0
components/soc/esp32s3/include/soc/soc_caps.h

@@ -287,6 +287,9 @@
 
 #define SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP    (1)     /*!<Supports waking up from touch pad trigger */
 
+#define SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY   (1)
+
+
 /*-------------------------- Flash Encryption CAPS----------------------------*/
 #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX   (64)