From c142b9b9e5daf6fd66dcc01104abb0d9e428e8d8 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Wed, 29 Mar 2017 21:09:47 +0300 Subject: [PATCH] esp32: RWDT is used to reboot system in case of panic handler crash also fixes TG1WDG protection bug in panic handler --- components/esp32/cpu_start.c | 23 +++++++++++++- components/esp32/include/esp_panic.h | 5 ++++ components/esp32/include/soc/rtc_cntl_reg.h | 6 ++++ components/esp32/panic.c | 33 ++++++++++++++++++++- 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 495a178034..9c06a49f26 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -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)); } diff --git a/components/esp32/include/esp_panic.h b/components/esp32/include/esp_panic.h index e9668facc5..c9ee14099d 100644 --- a/components/esp32/include/esp_panic.h +++ b/components/esp32/include/esp_panic.h @@ -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 diff --git a/components/esp32/include/soc/rtc_cntl_reg.h b/components/esp32/include/soc/rtc_cntl_reg.h index 40d65f21f6..ae287fd676 100644 --- a/components/esp32/include/soc/rtc_cntl_reg.h +++ b/components/esp32/include/soc/rtc_cntl_reg.h @@ -1650,6 +1650,12 @@ #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 ; */ diff --git a/components/esp32/panic.c b/components/esp32/panic.c index cd426344e1..753851c11c 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -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();