]> granicus.if.org Git - esp-idf/commitdiff
esp32: RWDT is used to reboot system in case of panic handler crash
authorAlexey Gerenkov <alexey@espressif.com>
Wed, 29 Mar 2017 18:09:47 +0000 (21:09 +0300)
committerAlexey Gerenkov <alexey@espressif.com>
Thu, 6 Apr 2017 23:34:29 +0000 (02:34 +0300)
also fixes TG1WDG protection bug in panic handler

components/esp32/cpu_start.c
components/esp32/include/esp_panic.h
components/esp32/include/soc/rtc_cntl_reg.h
components/esp32/panic.c

index 495a178034c5b3f95ba8f90a82c6df64234e919e..9c06a49f265560fcc874f28e14d001441864a765 100644 (file)
@@ -55,6 +55,7 @@
 #include "esp_task_wdt.h"
 #include "esp_phy_init.h"
 #include "esp_coexist.h"
+#include "esp_panic.h"
 #include "esp_core_dump.h"
 #include "trax.h"
 
@@ -92,6 +93,11 @@ static const char* TAG = "cpu_start";
 
 void IRAM_ATTR call_start_cpu0()
 {
+#if CONFIG_FREERTOS_UNICORE
+    RESET_REASON rst_reas[1];
+#else
+    RESET_REASON rst_reas[2];
+#endif
     cpu_configure_region_protection();
 
     //Move exception vectors to IRAM
@@ -99,10 +105,25 @@ void IRAM_ATTR call_start_cpu0()
                   "wsr    %0, vecbase\n" \
                   ::"r"(&_init_start));
 
+    rst_reas[0] = rtc_get_reset_reason(0);
+#if !CONFIG_FREERTOS_UNICORE
+    rst_reas[1] = rtc_get_reset_reason(1);
+#endif
+    // from panic handler we can be reset by RWDT or TG0WDT
+    if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET
+#if !CONFIG_FREERTOS_UNICORE
+        || rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
+#endif
+        ) {
+        // stop wdt in case of any
+        ESP_EARLY_LOGI(TAG, "Stop panic WDT");
+        esp_panic_wdt_stop();
+    }
+
     memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
 
     /* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */
-    if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) {
+    if (rst_reas[0] != DEEPSLEEP_RESET) {
         memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
     }
 
index e9668facc593d81e072e919403e988591f83e8cf..c9ee14099d644693d5d1f185b40ac22bfcecc54a 100644 (file)
@@ -61,6 +61,11 @@ esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags);
 void esp_clear_watchpoint(int no);
 
 
+/**
+ * @brief Stops panic WDT
+ */
+void esp_panic_wdt_stop(void);
+
 #endif
 
 #ifdef __cplusplus
index 40d65f21f69a0891083dd1959e2008b29a13ad3f..ae287fd676b69f6af2708db925a94ad5d91b3217 100644 (file)
 #define RTC_CNTL_WDT_PAUSE_IN_SLP_M  (BIT(7))
 #define RTC_CNTL_WDT_PAUSE_IN_SLP_V  0x1
 #define RTC_CNTL_WDT_PAUSE_IN_SLP_S  7
+/* RTC_CNTL_WDT_STGX : */
+/*description: stage action selection values */
+#define RTC_WDT_STG_SEL_OFF             0
+#define RTC_WDT_STG_SEL_INT             1
+#define RTC_WDT_STG_SEL_RESET_CPU       2
+#define RTC_WDT_STG_SEL_RESET_SYSTEM    3
 
 #define RTC_CNTL_WDTCONFIG1_REG          (DR_REG_RTCCNTL_BASE + 0x90)
 /* RTC_CNTL_WDT_STG0_HOLD : R/W ;bitpos:[31:0] ;default: 32'd128000 ; */
index cd426344e1b75241f60e527fee7fb97c5db28d90..753851c11c026f238f77f816217f14bc2a40d802 100644 (file)
@@ -284,11 +284,37 @@ static void disableAllWdts()
     TIMERG0.wdt_wprotect = 0;
     TIMERG1.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
     TIMERG1.wdt_config0.en = 0;
-    TIMERG0.wdt_wprotect = 0;
+    TIMERG1.wdt_wprotect = 0;
 }
 
 #endif
 
+static void esp_panic_wdt_start()
+{
+    if (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN)) {
+        return;
+    }
+    WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    WRITE_PERI_REG(RTC_CNTL_WDTFEED_REG, 1);
+    REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_SYS_RESET_LENGTH, 7);
+    REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_CPU_RESET_LENGTH, 7);
+    REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_RESET_SYSTEM);
+    // 64KB of core dump data (stacks of about 30 tasks) will produce ~85KB base64 data.
+    // @ 115200 UART speed it will take more than 6 sec to print them out.
+    WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, RTC_CNTL_SLOWCLK_FREQ*7);
+    REG_SET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
+    WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
+}
+
+void esp_panic_wdt_stop()
+{
+    WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    WRITE_PERI_REG(RTC_CNTL_WDTFEED_REG, 1);
+    REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_OFF);
+    REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
+    WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
+}
+
 static inline bool stackPointerIsSane(uint32_t sp)
 {
     return !(sp < 0x3ffae010 || sp > 0x3ffffff0 || ((sp & 0xf) != 0));
@@ -343,6 +369,9 @@ static void commonErrorHandler(XtExcFrame *frame)
         "A14     ", "A15     ", "SAR     ", "EXCCAUSE", "EXCVADDR", "LBEG    ", "LEND    ", "LCOUNT  "
     };
 
+    // start panic WDT to restart system if we hang in this handler
+    esp_panic_wdt_start();
+
     //Feed the watchdogs, so they will give us time to print out debug info
     reconfigureAllWdts();
 
@@ -370,6 +399,7 @@ static void commonErrorHandler(XtExcFrame *frame)
 
 #if CONFIG_ESP32_PANIC_GDBSTUB
     disableAllWdts();
+    esp_panic_wdt_stop();
     panicPutStr("Entering gdb stub now.\r\n");
     esp_gdbstub_panic_handler(frame);
 #else
@@ -383,6 +413,7 @@ static void commonErrorHandler(XtExcFrame *frame)
 #endif
     reconfigureAllWdts();
 #endif
+    esp_panic_wdt_stop();
 #if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
     panicPutStr("Rebooting...\r\n");
     esp_restart_noos();