]> granicus.if.org Git - esp-idf/commitdiff
reset_reason: fix setting wake stub entry point to 0x80000000
authorIvan Grokhotkov <ivan@espressif.com>
Mon, 27 Aug 2018 00:12:28 +0000 (08:12 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Mon, 27 Aug 2018 11:01:03 +0000 (19:01 +0800)
esp_reset_reason_init would check for reset reason hint, and
unconditionally set RTC_RESET_CAUSE_REG (which is also
RTC_ENTRY_ADDR_REG) to hint value 0, i.e. 0x80000000. However the ROM
code treats this value as valid deep sleep wake stub entry point, and
tries to jump to it.

Clear RTC_RESET_CAUSE_REG only if it contained a valid reset reason
hint, and simply set the register value to 0 when doing so. Also add
a check to esp_get_deep_sleep_wake_stub function that deep sleep wake
stub entry address must be in IRAM.

Reported in https://esp32.com/viewtopic.php?f=13&t=6919.

components/esp32/reset_reason.c
components/esp32/sleep_modes.c
components/esp32/test/test_sleep.c

index 191271df0f29f8286245143edcca873ca1c7f05e..b43bc8bc70ac6c66584d4f079d3105f1e74877a3 100644 (file)
@@ -17,6 +17,8 @@
 #include "rom/rtc.h"
 #include "soc/rtc_cntl_reg.h"
 
+static void esp_reset_reason_clear_hint();
+
 static esp_reset_reason_t s_reset_reason;
 
 static esp_reset_reason_t get_reset_reason(RESET_REASON rtc_reset_reason, esp_reset_reason_t reset_reason_hint)
@@ -69,9 +71,12 @@ static esp_reset_reason_t get_reset_reason(RESET_REASON rtc_reset_reason, esp_re
 
 static void __attribute__((constructor)) esp_reset_reason_init(void)
 {
+    esp_reset_reason_t hint = esp_reset_reason_get_hint();
     s_reset_reason = get_reset_reason(rtc_get_reset_reason(PRO_CPU_NUM),
-                                      esp_reset_reason_get_hint());
-    esp_reset_reason_set_hint(ESP_RST_UNKNOWN);
+                                      hint);
+    if (hint != ESP_RST_UNKNOWN) {
+        esp_reset_reason_clear_hint();
+    }
 }
 
 esp_reset_reason_t esp_reset_reason(void)
@@ -114,3 +119,8 @@ esp_reset_reason_t IRAM_ATTR esp_reset_reason_get_hint(void)
     }
     return (esp_reset_reason_t) low;
 }
+static void esp_reset_reason_clear_hint()
+{
+    REG_WRITE(RTC_RESET_CAUSE_REG, 0);
+}
+
index 2fda37a5ddb3ba32680e604a1ea260309cca45e8..ac9ea70dca64b211804ee145fe82ae6b05ed0b7f 100644 (file)
@@ -103,11 +103,14 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
     REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc);
     _lock_release(&lock_rtc_memory_crc);
 
-    if(stored_crc == calc_crc) {
-        return (esp_deep_sleep_wake_stub_fn_t)REG_READ(RTC_ENTRY_ADDR_REG);
-    } else {
+    if(stored_crc != calc_crc) {
+        return NULL;
+    }
+    esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
+    if (!esp_ptr_executable(stub_ptr)) {
         return NULL;
     }
+    return stub_ptr;
 }
 
 void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
index 2212de3c49308c9f6f43db90118cf3f54ab1f5a3..7eb5042269b08650740e1f190e0dea9c0fdd3551 100644 (file)
@@ -202,6 +202,74 @@ TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep][re
 }
 #endif
 
+static void do_deep_sleep()
+{
+    esp_sleep_enable_timer_wakeup(100000);
+    esp_deep_sleep_start();
+}
+
+static void check_sleep_reset_and_sleep()
+{
+    TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
+    esp_sleep_enable_timer_wakeup(100000);
+    esp_deep_sleep_start();
+}
+
+static void check_sleep_reset()
+{
+    TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
+}
+
+TEST_CASE_MULTIPLE_STAGES("enter deep sleep more than once", "[deepsleep][reset=DEEPSLEEP_RESET,DEEPSLEEP_RESET,DEEPSLEEP_RESET]",
+        do_deep_sleep,
+        check_sleep_reset_and_sleep,
+        check_sleep_reset_and_sleep,
+        check_sleep_reset);
+
+static void do_abort()
+{
+    abort();
+}
+
+static void check_abort_reset_and_sleep()
+{
+    TEST_ASSERT_EQUAL(ESP_RST_PANIC, esp_reset_reason());
+    esp_sleep_enable_timer_wakeup(100000);
+    esp_deep_sleep_start();
+}
+
+TEST_CASE_MULTIPLE_STAGES("enter deep sleep after abort", "[deepsleep][reset=abort,SW_CPU_RESET,DEEPSLEEP_RESET]",
+        do_abort,
+        check_abort_reset_and_sleep,
+        check_sleep_reset);
+
+static RTC_DATA_ATTR uint32_t s_wake_stub_var;
+
+static RTC_IRAM_ATTR void wake_stub()
+{
+    esp_default_wake_deep_sleep();
+    s_wake_stub_var = (uint32_t) &wake_stub;
+}
+
+static void prepare_wake_stub()
+{
+    esp_set_deep_sleep_wake_stub(&wake_stub);
+    esp_sleep_enable_timer_wakeup(100000);
+    esp_deep_sleep_start();
+}
+
+static void check_wake_stub()
+{
+    TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
+    TEST_ASSERT_EQUAL_HEX32((uint32_t) &wake_stub, s_wake_stub_var);
+    /* ROM code clears wake stub entry address */
+    TEST_ASSERT_NULL(esp_get_deep_sleep_wake_stub());
+}
+
+TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEEP_RESET]",
+        prepare_wake_stub,
+        check_wake_stub);
+
 
 TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]")
 {