From f7b83db2660cd6c25bd2d8f888262b9a33838f16 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Thu, 5 Mar 2020 17:15:04 +0800 Subject: [PATCH] feat(esp8266): add non-mask watch dog to panic critical function --- components/esp8266/Kconfig | 10 +++ components/esp8266/driver/ir_tx.c | 9 -- components/esp8266/driver/pwm.c | 9 -- .../esp8266/include/esp8266/eagle_soc.h | 9 ++ components/esp8266/source/task_wdt.c | 82 +++++++++++++++++++ .../freertos/port/esp8266/xtensa_vectors.S | 10 +-- 6 files changed, 106 insertions(+), 23 deletions(-) diff --git a/components/esp8266/Kconfig b/components/esp8266/Kconfig index 5497ed12..ee62e2fd 100644 --- a/components/esp8266/Kconfig +++ b/components/esp8266/Kconfig @@ -1,5 +1,15 @@ menu "ESP8266-specific" +config ESP8266_NMI_WDT + bool "Enable non-mask watch dog" + default y + help + Important: this non-mask watch dog is registered to non-mask timer0, + so it can not work together with PWM. + + Enable this non-mask watch dog can help users to debug blocking code + when CPU is at critical state(disable interrupt). + choice ESP8266_DEFAULT_CPU_FREQ_MHZ prompt "CPU frequency" default ESP8266_DEFAULT_CPU_FREQ_160 diff --git a/components/esp8266/driver/ir_tx.c b/components/esp8266/driver/ir_tx.c index ed93365c..b39fca9e 100644 --- a/components/esp8266/driver/ir_tx.c +++ b/components/esp8266/driver/ir_tx.c @@ -29,15 +29,6 @@ static const char *TAG = "ir tx"; -#define WDEVTSF0_TIME_LO 0x3ff21004 -#define WDEVTSF0_TIME_HI 0x3ff21008 -#define WDEVTSFSW0_LO 0x3ff21018 -#define WDEVTSFSW0_HI 0x3ff2101C -#define WDEVTSF0_TIMER_LO 0x3ff2109c -#define WDEVTSF0_TIMER_HI 0x3ff210a0 -#define WDEVTSF0TIMER_ENA 0x3ff21098 -#define WDEV_TSF0TIMER_ENA BIT(31) - int wDev_MacTimSetFunc(void (*handle)(void)); #define IR_TX_CHECK(a, str, ret_val) \ diff --git a/components/esp8266/driver/pwm.c b/components/esp8266/driver/pwm.c index bd7330f6..fe653624 100644 --- a/components/esp8266/driver/pwm.c +++ b/components/esp8266/driver/pwm.c @@ -55,15 +55,6 @@ static const char *TAG = "pwm"; #define AHEAD_TICKS3 2 #define MAX_TICKS 10000000ul -#define WDEVTSF0_TIME_LO 0x3ff21004 -#define WDEVTSF0_TIME_HI 0x3ff21008 -#define WDEVTSFSW0_LO 0x3ff21018 -#define WDEVTSFSW0_HI 0x3ff2101C -#define WDEVTSF0_TIMER_LO 0x3ff2109c -#define WDEVTSF0_TIMER_HI 0x3ff210a0 -#define WDEVTSF0TIMER_ENA 0x3ff21098 -#define WDEV_TSF0TIMER_ENA BIT(31) - #define PWM_VERSION "PWM v3.2" typedef struct { diff --git a/components/esp8266/include/esp8266/eagle_soc.h b/components/esp8266/include/esp8266/eagle_soc.h index 9cf38e0a..2fc00d91 100644 --- a/components/esp8266/include/esp8266/eagle_soc.h +++ b/components/esp8266/include/esp8266/eagle_soc.h @@ -146,6 +146,15 @@ #define WDEV_COUNT_REG (0x3ff20c00) +#define WDEVTSF0_TIME_LO 0x3ff21004 +#define WDEVTSF0_TIME_HI 0x3ff21008 +#define WDEVTSFSW0_LO 0x3ff21018 +#define WDEVTSFSW0_HI 0x3ff2101C +#define WDEVTSF0_TIMER_LO 0x3ff2109c +#define WDEVTSF0_TIMER_HI 0x3ff210a0 +#define WDEVTSF0TIMER_ENA 0x3ff21098 +#define WDEV_TSF0TIMER_ENA BIT(31) + //Watch dog reg {{ #define PERIPHS_WDT_BASEADDR 0x60000900 diff --git a/components/esp8266/source/task_wdt.c b/components/esp8266/source/task_wdt.c index 744ed87a..bb207342 100644 --- a/components/esp8266/source/task_wdt.c +++ b/components/esp8266/source/task_wdt.c @@ -17,7 +17,9 @@ #include "esp_log.h" #include "esp_libc.h" #include "esp_task_wdt.h" +#include "esp_attr.h" #include "portmacro.h" +#include "esp8266/rom_functions.h" #include "esp8266/eagle_soc.h" #include "driver/soc.h" @@ -36,6 +38,73 @@ static void esp_task_wdt_isr(void *param) } #endif +#ifdef CONFIG_ESP8266_NMI_WDT + +#if CONFIG_ESP_TASK_WDT_TIMEOUT_S == 13 +#define NMI_WD_TOTAL_PERIOD (6553600) +#elif CONFIG_ESP_TASK_WDT_TIMEOUT_S == 14 +#define NMI_WD_TOTAL_PERIOD (13107200) +#elif CONFIG_ESP_TASK_WDT_TIMEOUT_S == 15 +#define NMI_WD_TOTAL_PERIOD (26214400) +#endif + +#define NMI_WD_CHECK_PERIOD (1 * 1000 * 1000) + +static int s_nmi_wd_state; + +static void nmi_panic_wd(void) +{ + extern uint32_t _chip_nmi_cnt; + extern uint8_t _chip_nmi_stk[]; + extern void panicHandler(void *frame, int wdt); + uint32_t *p; + + if (_chip_nmi_cnt == 1) { + p = (uint32_t *)&_chip_nmi_stk[512]; + } else { + p = (uint32_t *)&_chip_nmi_stk[512 + 124 + 256]; + } + + panicHandler(p - 1, 1); +} + +static void IRAM_ATTR nmi_set_wd_time(uint32_t us) +{ + REG_WRITE(WDEVTSF0TIMER_ENA, REG_READ(WDEVTSF0TIMER_ENA) & (~WDEV_TSF0TIMER_ENA)); + + REG_WRITE(WDEVTSFSW0_LO, 0); + REG_WRITE(WDEVTSFSW0_HI, 0); + REG_WRITE(WDEVTSFSW0_LO, 0); + + REG_WRITE(WDEVTSF0_TIMER_LO, 0); + REG_WRITE(WDEVTSF0_TIMER_HI, 0); + + REG_WRITE(WDEVTSF0_TIMER_LO, us); + + REG_WRITE(WDEVTSF0TIMER_ENA, WDEV_TSF0TIMER_ENA); +} + +static void IRAM_ATTR nmi_check_wd(void) +{ + switch (s_nmi_wd_state) { + case 0: + s_nmi_wd_state = 1; + nmi_set_wd_time(NMI_WD_CHECK_PERIOD); + break; + case 1: + s_nmi_wd_state = 2; + nmi_set_wd_time(NMI_WD_TOTAL_PERIOD - NMI_WD_CHECK_PERIOD); + break; + case 2: + Cache_Read_Enable_New(); + nmi_panic_wd(); + break; + default: + break; + } +} +#endif + /** * @brief Just for pass compiling and mark wdt calling line */ @@ -72,6 +141,15 @@ esp_err_t esp_task_wdt_init(void) WDT_FEED(); +#ifdef CONFIG_ESP8266_NMI_WDT + { + extern void wDev_MacTimSetFunc(void *func); + + wDev_MacTimSetFunc(nmi_check_wd);; + nmi_set_wd_time(NMI_WD_CHECK_PERIOD); + } +#endif + return 0; } @@ -82,6 +160,10 @@ esp_err_t esp_task_wdt_init(void) void esp_task_wdt_reset(void) { WDT_FEED(); + +#ifdef CONFIG_ESP8266_NMI_WDT + s_nmi_wd_state = 0; +#endif } /** diff --git a/components/freertos/port/esp8266/xtensa_vectors.S b/components/freertos/port/esp8266/xtensa_vectors.S index 755edc1a..3485d74b 100644 --- a/components/freertos/port/esp8266/xtensa_vectors.S +++ b/components/freertos/port/esp8266/xtensa_vectors.S @@ -80,14 +80,14 @@ Add to compile passing. #define _INTERRUPT_LEVEL 3 STRUCT_BEGIN -STRUCT_FIELD (long,4,HESF_,SAR) -STRUCT_FIELD (long,4,HESF_,EPC1) -STRUCT_FIELD (long,4,HESF_,EXCCAUSE) -STRUCT_FIELD (long,4,HESF_,EXCVADDR) -STRUCT_FIELD (long,4,HESF_,EXCSAVE1) STRUCT_FIELD (long,4,HESF_,EPC3) STRUCT_FIELD (long,4,HESF_,EPS3) STRUCT_AFIELD(long,4,HESF_,AREG, 16) /* address registers ar0..ar15 */ +STRUCT_FIELD (long,4,HESF_,SAR) +STRUCT_FIELD (long,4,HESF_,EXCCAUSE) +STRUCT_FIELD (long,4,HESF_,EPC1) +STRUCT_FIELD (long,4,HESF_,EXCVADDR) +STRUCT_FIELD (long,4,HESF_,EXCSAVE1) #define HESF_AR(n) HESF_AREG+((n)*4) STRUCT_END(HighPriFrame) #define HESF_TOTALSIZE HighPriFrameSize+32 /* 32 bytes for interrupted code's save areas under SP */