diff --git a/components/esp8266/Kconfig b/components/esp8266/Kconfig index 711b2bf1..98900d5a 100644 --- a/components/esp8266/Kconfig +++ b/components/esp8266/Kconfig @@ -71,6 +71,45 @@ config MAIN_TASK_STACK_SIZE which calls app_main(). If app_main() returns then this task is deleted and its stack memory is freed. +config TASK_WDT + bool "Initialize Task Watchdog Timer on startup" + default y + help + The Task Watchdog Timer can be used to make sure individual tasks are still + running. Enabling this option will cause the Task Watchdog Timer to be + initialized automatically at startup. The Task Watchdog timer can be + initialized after startup as well. + +config TASK_WDT_PANIC + bool "Invoke panic handler on Task Watchdog timeout" + depends on TASK_WDT + default n + help + If this option is enabled, the Task Watchdog Timer will be configured to + trigger the panic handler when it times out. And it may cost some time. + +choice TASK_WDT_TIMEOUT_S + prompt "Task Watchdog timeout period (seconds)" + depends on TASK_WDT + default TASK_WDT_TIMEOUT_13N + help + Timeout period configuration for the Task Watchdog Timer in seconds. + This is also configurable at run time. + +config TASK_WDT_TIMEOUT_13N + bool "6.5536s" +config TASK_WDT_TIMEOUT_14N + bool "13.1072s" +config TASK_WDT_TIMEOUT_15N + bool "26.2144s" +endchoice + +config TASK_WDT_TIMEOUT_S + int + default 13 if TASK_WDT_TIMEOUT_13N + default 14 if TASK_WDT_TIMEOUT_14N + default 15 if TASK_WDT_TIMEOUT_15N + endmenu menu WIFI diff --git a/components/esp8266/include/esp8266/eagle_soc.h b/components/esp8266/include/esp8266/eagle_soc.h index 1a49b12c..28d105a8 100644 --- a/components/esp8266/include/esp8266/eagle_soc.h +++ b/components/esp8266/include/esp8266/eagle_soc.h @@ -117,10 +117,31 @@ //Interrupt remap control registers define{{ #define EDGE_INT_ENABLE_REG (PERIPHS_DPORT_BASEADDR + 0x04) +#define WDT_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT0) #define TM1_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) #define TM1_EDGE_INT_DISABLE() CLEAR_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) //}} + +//Watch dog reg {{ +#define PERIPHS_WDT_BASEADDR 0x60000900 + +#define WDT_CTL_ADDRESS 0 +#define WDT_OP_ADDRESS 0x4 +#define WDT_OP_ND_ADDRESS 0x8 +#define WDT_RST_ADDRESS 0x14 + +#define WDT_CTL_RSTLEN_MASK 0x38 +#define WDT_CTL_RSPMOD_MASK 0x6 +#define WDT_CTL_EN_MASK 0x1 + +#define WDT_CTL_RSTLEN_LSB 0x3 +#define WDT_CTL_RSPMOD_LSB 0x1 +#define WDT_CTL_EN_LSB 0 + +#define WDT_FEED_VALUE 0x73 +//}} + //RTC reg {{ #define REG_RTC_BASE PERIPHS_RTC_BASEADDR diff --git a/components/esp8266/include/esp_task_wdt.h b/components/esp8266/include/esp_task_wdt.h new file mode 100644 index 00000000..1a7edcc1 --- /dev/null +++ b/components/esp8266/include/esp_task_wdt.h @@ -0,0 +1,37 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include "esp_err.h" + +/** + * @brief Initialize the Task Watchdog Timer (TWDT) + * + * @return + * - ESP_OK: Initialization was successful + * - ESP_ERR_NO_MEM: Initialization failed due to lack of memory + * + * @note esp_task_wdt_init() must only be called after the scheduler + * started + */ +esp_err_t esp_task_wdt_init(void); + +/** + * @brief Reset(Feed) the Task Watchdog Timer (TWDT) on behalf of the currently + * running task + */ +void esp_task_wdt_reset(void); diff --git a/components/esp8266/include/esp_wifi_osi.h b/components/esp8266/include/esp_wifi_osi.h index 9e19dcc9..763d6f28 100644 --- a/components/esp8266/include/esp_wifi_osi.h +++ b/components/esp8266/include/esp_wifi_osi.h @@ -149,6 +149,8 @@ extern wifi_osi_funcs_t s_wifi_osi_funcs; #define wifi_rand() \ s_wifi_osi_funcs.rand() +void *osi_task_top_sp(void); + #ifdef __cplusplus } #endif diff --git a/components/esp8266/lib/VERSION b/components/esp8266/lib/VERSION index 3d43a58f..b70096dd 100644 --- a/components/esp8266/lib/VERSION +++ b/components/esp8266/lib/VERSION @@ -1,9 +1,9 @@ gwen: - core: b9f2d3e - net80211: 48cd36b - pp: 82269d9 - smartconfig:eca7811 - wpa: b9f2d3e - espnow: 95a55d0 - wps: 48cd36b + core: 103fbb8 + net80211: 103fbb8 + pp: 103fbb8 + smartconfig:103fbb8 + wpa: 103fbb8 + espnow: 103fbb8 + wps: 103fbb8 phy: 1055_8 \ No newline at end of file diff --git a/components/esp8266/lib/libcore.a b/components/esp8266/lib/libcore.a index 7a8b7c4f..6083e5ad 100644 Binary files a/components/esp8266/lib/libcore.a and b/components/esp8266/lib/libcore.a differ diff --git a/components/esp8266/lib/libespnow.a b/components/esp8266/lib/libespnow.a index 44f9d76d..9a99a2d2 100644 Binary files a/components/esp8266/lib/libespnow.a and b/components/esp8266/lib/libespnow.a differ diff --git a/components/esp8266/lib/libnet80211.a b/components/esp8266/lib/libnet80211.a index 6cc12eb8..1646ebd4 100644 Binary files a/components/esp8266/lib/libnet80211.a and b/components/esp8266/lib/libnet80211.a differ diff --git a/components/esp8266/lib/libpp.a b/components/esp8266/lib/libpp.a index 7ddef11c..6d2e8921 100644 Binary files a/components/esp8266/lib/libpp.a and b/components/esp8266/lib/libpp.a differ diff --git a/components/esp8266/lib/libsmartconfig.a b/components/esp8266/lib/libsmartconfig.a index 1c830c59..badcf14d 100644 Binary files a/components/esp8266/lib/libsmartconfig.a and b/components/esp8266/lib/libsmartconfig.a differ diff --git a/components/esp8266/lib/libwpa.a b/components/esp8266/lib/libwpa.a index bb7a3595..1d6f85c3 100644 Binary files a/components/esp8266/lib/libwpa.a and b/components/esp8266/lib/libwpa.a differ diff --git a/components/esp8266/lib/libwps.a b/components/esp8266/lib/libwps.a index 3ca31eec..55bfc4cb 100644 Binary files a/components/esp8266/lib/libwps.a and b/components/esp8266/lib/libwps.a differ diff --git a/components/esp8266/source/esp_wifi_os_adapter.c b/components/esp8266/source/esp_wifi_os_adapter.c index 51541748..bf6ddfaf 100644 --- a/components/esp8266/source/esp_wifi_os_adapter.c +++ b/components/esp8266/source/esp_wifi_os_adapter.c @@ -341,6 +341,13 @@ static int32_t rand_wrapper(void) return (int32_t)esp_random(); } +void *osi_task_top_sp(void) +{ + extern uint32_t **pxCurrentTCB; + + return pxCurrentTCB[0]; +} + const wifi_osi_funcs_t s_wifi_osi_funcs = { .version = ESP_WIFI_OS_ADAPTER_VERSION, diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c index 1adc724f..36ceddb6 100644 --- a/components/esp8266/source/startup.c +++ b/components/esp8266/source/startup.c @@ -27,6 +27,7 @@ #include "esp_phy_init.h" #include "esp_wifi_osi.h" #include "esp_heap_caps_init.h" +#include "esp_task_wdt.h" #include "internal/esp_wifi_internal.h" #define FLASH_MAP_ADDR 0x40200000 @@ -58,11 +59,14 @@ static void user_init_entry(void *param) assert(mac_init() == 0); assert(base_gpio_init() == 0); esp_phy_load_cal_and_init(0); - assert(watchdog_init() == 0); assert(wifi_timer_init() == 0); esp_wifi_set_rx_pbuf_mem_type(WIFI_RX_PBUF_DRAM); +#ifdef CONFIG_TASK_WDT + esp_task_wdt_init(); +#endif + app_main(); wifi_task_delete(NULL); diff --git a/components/esp8266/source/task_wdt.c b/components/esp8266/source/task_wdt.c new file mode 100644 index 00000000..1700bf50 --- /dev/null +++ b/components/esp8266/source/task_wdt.c @@ -0,0 +1,102 @@ +// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "esp_log.h" +#include "esp_libc.h" +#include "esp_wifi_osi.h" +#include "esp_task_wdt.h" +#include "portmacro.h" +#include "esp8266/eagle_soc.h" + +#define WDT_REG_READ(_reg) REG_READ(PERIPHS_WDT_BASEADDR + _reg) +#define WDT_REG_WRITE(_reg, _val) REG_WRITE(PERIPHS_WDT_BASEADDR + _reg, _val) +#define CLEAR_WDT_REG_MASK(_reg, _mask) WDT_REG_WRITE(_reg, WDT_REG_READ(_reg) & (~_mask)) +#define WDT_FEED() WDT_REG_WRITE(WDT_RST_ADDRESS, WDT_FEED_VALUE) + +static const char *TAG = "wdt"; + +#ifdef CONFIG_TASK_WDT_PANIC +/** + * @brief Task watch dog interrupt function and it should do panic + */ +static void esp_task_wdt_isr(void *param) +{ + extern void panicHandler(void *frame, int wdt); + + panicHandler(osi_task_top_sp(), 1); +} +#endif + +/** + * @brief Just for pass compiling and mark wdt calling line + */ +esp_err_t esp_task_wdt_init(void) +{ + CLEAR_WDT_REG_MASK(WDT_CTL_ADDRESS, BIT0); + +#ifdef CONFIG_TASK_WDT_PANIC + const uint32_t panic_time_param = 11; + + _xt_isr_attach(ETS_WDT_INUM, esp_task_wdt_isr, NULL); + _xt_isr_unmask(1 << ETS_WDT_INUM); + + WDT_EDGE_INT_ENABLE(); + + ESP_LOGD(TAG, "Enable task watch dog panic, panic time parameter is %u", panic_time_param); +#else + const uint32_t panic_time_param = 1; +#endif + + ESP_LOGD(TAG, "task watch dog trigger time parameter is %u", CONFIG_TASK_WDT_TIMEOUT_S); + + WDT_REG_WRITE(WDT_OP_ADDRESS, CONFIG_TASK_WDT_TIMEOUT_S); // 2^n * 0.8ms, mask 0xf, n = 13 -> (2^13 = 8192) * 0.8 * 0.001 = 6.5536 + WDT_REG_WRITE(WDT_OP_ND_ADDRESS, panic_time_param); // 2^n * 0.8ms, mask 0xf, n = 11 -> (2^11 = 2048) * 0.8 * 0.001 = 1.6384 + + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_RSTLEN_MASK, 7 << WDT_CTL_RSTLEN_LSB, 0); + // interrupt then reset + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_RSPMOD_MASK, 0 << WDT_CTL_RSPMOD_LSB, 0); + // start task watch dog1 + SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_EN_MASK, 1 << WDT_CTL_EN_LSB, 0); + + WDT_FEED(); + + return 0; +} + +/** + * @brief Reset(Feed) the Task Watchdog Timer (TWDT) on behalf of the currently + * running task + */ +void esp_task_wdt_reset(void) +{ + WDT_FEED(); +} + +/** + * @brief Just for pass compiling and mark wdt calling line + */ +void pp_soft_wdt_stop(void) +{ + +} + +/** + * @brief Just for pass compiling and mark wdt calling line + */ +void pp_soft_wdt_restart(void) +{ + +} diff --git a/components/freertos/port/esp8266/panic.c b/components/freertos/port/esp8266/panic.c index 8917aad6..6dc86421 100644 --- a/components/freertos/port/esp8266/panic.c +++ b/components/freertos/port/esp8266/panic.c @@ -131,7 +131,7 @@ static void panic_stack(StackType_t *start_stk, StackType_t *end_stk) * * @return none */ -void panic_info(void *frame) +static void panic_info(void *frame, int wdt) { task_info_t *task; int *regs = (int *)frame; @@ -144,14 +144,14 @@ void panic_info(void *frame) " A14", " A15", " SAR", "EXCCAUSE" }; - extern int _Pri_3_NMICount; - panic_str("\r\n\r\n"); - if (_Pri_3_NMICount == -1) { - panic_str("Soft watch dog triggle:\r\n\r\n"); + if (wdt) { + panic_str("Task watchdog got triggered.\r\n\r\n"); show_critical_info(); - } else if (xPortInIsrContext()) + } + + if (xPortInIsrContext()) panic_str("Core 0 was running in ISR context:\r\n\r\n"); if ((task = (task_info_t *)xTaskGetCurrentTaskHandle())) { @@ -195,7 +195,7 @@ void panic_info(void *frame) while (1); } -void IRAM_ATTR panicHandler(void *frame) +void IRAM_ATTR panicHandler(void *frame, int wdt) { int cnt = 10; @@ -208,7 +208,7 @@ void IRAM_ATTR panicHandler(void *frame) // for panic the function that disable cache Cache_Read_Enable_New(); - panic_info(frame); + panic_info(frame, wdt); } void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) diff --git a/components/freertos/port/esp8266/port.c b/components/freertos/port/esp8266/port.c index 49e9dfde..f13b79fe 100644 --- a/components/freertos/port/esp8266/port.c +++ b/components/freertos/port/esp8266/port.c @@ -386,3 +386,12 @@ BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void * const pvBuffer, configASSERT(xJustPeeking == 0); return xQueueReceive(xQueue, pvBuffer, xTicksToWait); } + +void vApplicationIdleHook(void) +{ + extern void pmIdleHook(void); + extern void esp_task_wdt_reset(void); + + pmIdleHook(); + esp_task_wdt_reset(); +} diff --git a/components/freertos/port/esp8266/xtensa_vectors.S b/components/freertos/port/esp8266/xtensa_vectors.S index 2d74d6fe..b7c8ffb8 100644 --- a/components/freertos/port/esp8266/xtensa_vectors.S +++ b/components/freertos/port/esp8266/xtensa_vectors.S @@ -1418,96 +1418,6 @@ nmi_rfi: #endif #endif /* NMI */ - .section .text, "ax" - .global ShowCritical - .type ShowCritical, @function - .align 4 -ShowCritical: - movi a2, LABEL(_Pri_,_NMICount) - l32i a2, a2, 0 - bnei a2, 1, nmi_reentry_panic - - /* - * a2 == 1, the function is not NMI exception function and its stack - * is stored at LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE - * - * a2 >= 1, the function is NMI exception function and its stack - * is stored at LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2 - */ - movi a2, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE - j nmi_common_panic -nmi_reentry_panic: - movi a2, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2 -nmi_common_panic: - movi a1, 0XFFFFFFFF - movi a3, LABEL(_Pri_,_NMICount) - s32i a1, a3, 0 - - movi a1, _chip_interrupt_tmp - addi a1, a1, -XT_STK_FRMSZ - - l32i a3, a2, HESF_AR(0) - s32i a3, a1, XT_STK_A0 - - l32i a3, a2, HESF_AR(1) - s32i a3, a1, XT_STK_A1 - - l32i a3, a2, HESF_AR(2) - s32i a3, a1, XT_STK_A2 - - l32i a3, a2, HESF_AR(3) - s32i a3, a1, XT_STK_A3 - - l32i a3, a2, HESF_AR(4) - s32i a3, a1, XT_STK_A4 - - l32i a3, a2, HESF_AR(5) - s32i a3, a1, XT_STK_A5 - - l32i a3, a2, HESF_AR(6) - s32i a3, a1, XT_STK_A6 - - l32i a3, a2, HESF_AR(7) - s32i a3, a1, XT_STK_A7 - - l32i a3, a2, HESF_AR(8) - s32i a3, a1, XT_STK_A8 - - l32i a3, a2, HESF_AR(9) - s32i a3, a1, XT_STK_A9 - - l32i a3, a2, HESF_AR(10) - s32i a3, a1, XT_STK_A10 - - l32i a3, a2, HESF_AR(11) - s32i a3, a1, XT_STK_A11 - - l32i a3, a2, HESF_AR(12) - s32i a3, a1, XT_STK_A12 - - l32i a3, a2, HESF_AR(13) - s32i a3, a1, XT_STK_A13 - - l32i a3, a2, HESF_AR(14) - s32i a3, a1, XT_STK_A14 - - l32i a3, a2, HESF_AR(15) - s32i a3, a1, XT_STK_A15 - - l32i a3, a2, HESF_EXCCAUSE - s32i a3, a1, XT_STK_EXCCAUSE - - l32i a3, a2, HESF_EPC3 - s32i a3, a1, XT_STK_PC - - l32i a3, a2, HESF_EPS3 - s32i a3, a1, XT_STK_PS - - mov a2, a1 - - call0 panicHandler - - .global _xt_ext_panic .type _xt_ext_panic, @function .align 4 @@ -1555,4 +1465,5 @@ _xt_ext_panic: //Call panic handler mov a2, sp + movi a3, 0 call0 panicHandler diff --git a/components/spi_flash/src/spi_flash.c b/components/spi_flash/src/spi_flash.c index 703b9dfb..3866bee5 100644 --- a/components/spi_flash/src/spi_flash.c +++ b/components/spi_flash/src/spi_flash.c @@ -20,6 +20,7 @@ #include "esp_wifi_osi.h" #include "esp_system.h" #include "esp_log.h" +#include "esp_task_wdt.h" #include "esp8266/eagle_soc.h" #include "esp8266/rom_functions.h" #include "esp8266/pin_mux_register.h" @@ -136,7 +137,6 @@ bool special_flash_write_status(uint8_t command, uint32_t status, int len, bool esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size); uint8_t en25q16x_read_sfdp(); -extern void pp_soft_wdt_feed(void); extern void pp_soft_wdt_stop(void); extern void pp_soft_wdt_restart(void); @@ -494,7 +494,7 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t si #define FLASH_WRITE(dest, src, size) \ { \ ret = spi_flash_write_raw(dest, src, size); \ - pp_soft_wdt_feed(); \ + esp_task_wdt_reset(); \ if (ret) { \ return ret; \ } \ @@ -607,7 +607,7 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t src_addr, void *dest, size_t size) #define FLASH_READ(addr, dest, size) \ { \ ret = spi_flash_read_raw(addr, dest, size); \ - pp_soft_wdt_feed(); \ + esp_task_wdt_reset(); \ if (ret) \ return ret; \ } @@ -1028,7 +1028,7 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_address, size_t size) do { ret = spi_flash_erase_sector(sec++); - pp_soft_wdt_feed(); + esp_task_wdt_reset(); } while (ret == ESP_OK && --num); return ret;