From 3ffa33c84df3c93d13d0854d6515a08c32163453 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Sun, 4 Aug 2019 19:16:58 +0800 Subject: [PATCH 1/5] esp32s2beta: re-enable int_wdt --- components/esp32s2beta/cpu_start.c | 6 ++--- components/esp32s2beta/int_wdt.c | 36 +++++++----------------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/components/esp32s2beta/cpu_start.c b/components/esp32s2beta/cpu_start.c index 63379a21b..568cc584c 100644 --- a/components/esp32s2beta/cpu_start.c +++ b/components/esp32s2beta/cpu_start.c @@ -311,9 +311,9 @@ void start_cpu0_default(void) do_global_ctors(); #if CONFIG_ESP_INT_WDT - //esp_int_wdt_init(); - //Initialize the interrupt watch dog for CPU0. - //esp_int_wdt_cpu_init(); + esp_int_wdt_init(); + //Initialize the interrupt watch dog + esp_int_wdt_cpu_init(); #endif esp_cache_err_int_init(); esp_crosscore_int_init(); diff --git a/components/esp32s2beta/int_wdt.c b/components/esp32s2beta/int_wdt.c index 2515962db..bd46f3702 100644 --- a/components/esp32s2beta/int_wdt.c +++ b/components/esp32s2beta/int_wdt.c @@ -1,4 +1,4 @@ -// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// Copyright 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. @@ -39,38 +39,18 @@ //Take care: the tick hook can also be called before esp_int_wdt_init() is called. -#if CONFIG_ESP_INT_WDT_CHECK_CPU1 -//Not static; the ISR assembly checks this. -bool int_wdt_app_cpu_ticked=false; -static void IRAM_ATTR tick_hook(void) { - if (xPortGetCoreID()!=0) { - int_wdt_app_cpu_ticked=true; - } else { - //Only feed wdt if app cpu also ticked. - if (int_wdt_app_cpu_ticked) { - TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; - TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt - TIMERG1.wdt_config3=CONFIG_ESP_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset - TIMERG1.wdt_feed=1; - TIMERG1.wdt_wprotect=0; - int_wdt_app_cpu_ticked=false; - } - } -} -#else -static void IRAM_ATTR tick_hook(void) { - if (xPortGetCoreID()!=0) return; +static void IRAM_ATTR tick_hook(void) +{ TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt TIMERG1.wdt_config3=CONFIG_ESP_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset TIMERG1.wdt_feed=1; TIMERG1.wdt_wprotect=0; } -#endif - -void esp_int_wdt_init(void) { +void esp_int_wdt_init(void) +{ periph_module_enable(PERIPH_TIMG1_MODULE); TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG1.wdt_config0.sys_reset_length=7; //3.2uS @@ -92,9 +72,9 @@ void esp_int_wdt_init(void) { void esp_int_wdt_cpu_init(void) { - esp_register_freertos_tick_hook_for_cpu(tick_hook, xPortGetCoreID()); + esp_register_freertos_tick_hook_for_cpu(tick_hook, 0); ESP_INTR_DISABLE(WDT_INT_NUM); - intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM); + intr_matrix_set(0, ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM); //We do not register a handler for the interrupt because it is interrupt level 4 which //is not servicable from C. Instead, xtensa_vectors.S has a call to the panic handler for //this interrupt. @@ -103,4 +83,4 @@ void esp_int_wdt_cpu_init(void) -#endif +#endif // CONFIG_ESP_INT_WDT From d3637cd06b9560be71a9f6a0cdfe2ce4630678ff Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 14 Aug 2019 18:26:36 +0800 Subject: [PATCH 2/5] rtc_wdt: re-enable RTC_WDT --- .../bootloader_support/src/bootloader_init.c | 4 +- components/esp32s2beta/clk.c | 23 ++- components/esp32s2beta/cpu_start.c | 10 +- components/soc/esp32s2beta/rtc_wdt.c | 148 ++++++++++++++++++ components/soc/esp32s2beta/sources.cmake | 1 + 5 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 components/soc/esp32s2beta/rtc_wdt.c diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 9456650f7..59941ad78 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -189,7 +189,7 @@ static esp_err_t bootloader_main(void) ets_set_appcpu_boot_addr(0); #endif -#if CONFIG_BOOTLOADER_WDT_ENABLE && CONFIG_IDF_TARGET_ESP32 +#ifdef CONFIG_BOOTLOADER_WDT_ENABLE ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS); rtc_wdt_protect_off(); rtc_wdt_disable(); @@ -199,7 +199,7 @@ static esp_err_t bootloader_main(void) rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS); rtc_wdt_enable(); rtc_wdt_protect_on(); -#elif CONFIG_IDF_TARGET_ESP32 +#else /* disable watch dog here */ rtc_wdt_disable(); #endif diff --git a/components/esp32s2beta/clk.c b/components/esp32s2beta/clk.c index 1b58527ad..c4d249189 100644 --- a/components/esp32s2beta/clk.c +++ b/components/esp32s2beta/clk.c @@ -28,7 +28,8 @@ #include "soc/dport_access.h" #include "soc/soc.h" #include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_wdt.h" +#include "soc/rtc_periph.h" #include "soc/i2s_reg.h" #include "driver/periph_ctrl.h" #include "xtensa/core-macros.h" @@ -63,12 +64,32 @@ void esp_clk_init(void) rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M); +#ifdef CONFIG_BOOTLOADER_WDT_ENABLE + // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed. + // If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times. + // Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec). + // This prevents excessive delay before resetting in case the supply voltage is drawdown. + // (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec). + rtc_wdt_protect_off(); + rtc_wdt_feed(); + rtc_wdt_set_time(RTC_WDT_STAGE0, 1600); + rtc_wdt_protect_on(); +#endif + #ifdef CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL); #else select_rtc_slow_clk(RTC_SLOW_FREQ_RTC); #endif +#ifdef CONFIG_BOOTLOADER_WDT_ENABLE + // After changing a frequency WDT timeout needs to be set for new frequency. + rtc_wdt_protect_off(); + rtc_wdt_feed(); + rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS); + rtc_wdt_protect_on(); +#endif + uint32_t freq_mhz = CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ; rtc_cpu_freq_t freq = RTC_CPU_FREQ_80M; switch(freq_mhz) { diff --git a/components/esp32s2beta/cpu_start.c b/components/esp32s2beta/cpu_start.c index 568cc584c..4275e5ca5 100644 --- a/components/esp32s2beta/cpu_start.c +++ b/components/esp32s2beta/cpu_start.c @@ -34,7 +34,7 @@ #include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" #include "soc/periph_defs.h" - +#include "soc/rtc_wdt.h" #include "driver/rtc_io.h" #include "freertos/FreeRTOS.h" @@ -368,10 +368,6 @@ static void do_global_ctors(void) static void main_task(void* args) { - // Now that the application is about to start, disable boot watchdogs - REG_CLR_BIT(TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN_S); - REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN); - //Enable allocation in region where the startup stacks were located. heap_caps_enable_nonos_stack_heaps(); @@ -393,6 +389,10 @@ static void main_task(void* args) #endif #endif + // Now that the application is about to start, disable boot watchdog +#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE + rtc_wdt_disable(); +#endif app_main(); vTaskDelete(NULL); } diff --git a/components/soc/esp32s2beta/rtc_wdt.c b/components/soc/esp32s2beta/rtc_wdt.c new file mode 100644 index 000000000..9ef52c17e --- /dev/null +++ b/components/soc/esp32s2beta/rtc_wdt.c @@ -0,0 +1,148 @@ +// Copyright 2018 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 "soc/rtc_wdt.h" +#include "soc/rtc.h" + + +bool rtc_wdt_get_protect_status(void) +{ + return READ_PERI_REG(RTC_CNTL_WDTWPROTECT_REG) != RTC_CNTL_WDT_WKEY_VALUE; +} + +void rtc_wdt_protect_off(void) +{ + WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); +} + +void rtc_wdt_protect_on(void) +{ + WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0); +} + + +void rtc_wdt_enable(void) +{ + REG_SET_BIT(RTC_CNTL_WDTFEED_REG, RTC_CNTL_WDT_FEED); + SET_PERI_REG_MASK(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN | RTC_CNTL_WDT_PAUSE_IN_SLP); +} + +void rtc_wdt_flashboot_mode_enable(void) +{ + REG_SET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN); +} + +void rtc_wdt_disable(void) +{ + bool protect = rtc_wdt_get_protect_status(); + if (protect) { + rtc_wdt_protect_off(); + } + REG_SET_BIT(RTC_CNTL_WDTFEED_REG, RTC_CNTL_WDT_FEED); + rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_OFF); + rtc_wdt_set_stage(RTC_WDT_STAGE1, RTC_WDT_STAGE_ACTION_OFF); + rtc_wdt_set_stage(RTC_WDT_STAGE2, RTC_WDT_STAGE_ACTION_OFF); + rtc_wdt_set_stage(RTC_WDT_STAGE3, RTC_WDT_STAGE_ACTION_OFF); + REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN); + REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN); + if (protect) { + rtc_wdt_protect_on(); + } +} + +void rtc_wdt_feed(void) +{ + bool protect = rtc_wdt_get_protect_status(); + if (protect) { + rtc_wdt_protect_off(); + } + REG_SET_BIT(RTC_CNTL_WDTFEED_REG, RTC_CNTL_WDT_FEED); + if (protect) { + rtc_wdt_protect_on(); + } +} + +static uint32_t get_addr_reg(rtc_wdt_stage_t stage) +{ + uint32_t reg; + if (stage == RTC_WDT_STAGE0) { + reg = RTC_CNTL_WDTCONFIG1_REG; + } else if (stage == RTC_WDT_STAGE1) { + reg = RTC_CNTL_WDTCONFIG2_REG; + } else if (stage == RTC_WDT_STAGE2) { + reg = RTC_CNTL_WDTCONFIG3_REG; + } else { + reg = RTC_CNTL_WDTCONFIG4_REG; + } + return reg; +} + +esp_err_t rtc_wdt_set_time(rtc_wdt_stage_t stage, unsigned int timeout_ms) +{ + if (stage > 3) { + return ESP_ERR_INVALID_ARG; + } + uint32_t timeout = (uint32_t) ((uint64_t) rtc_clk_slow_freq_get_hz() * timeout_ms / 1000); + WRITE_PERI_REG(get_addr_reg(stage), timeout); + return ESP_OK; +} + +esp_err_t rtc_wdt_get_timeout(rtc_wdt_stage_t stage, unsigned int* timeout_ms) +{ + if (stage > 3) { + return ESP_ERR_INVALID_ARG; + } + uint32_t time_tick; + time_tick = READ_PERI_REG(get_addr_reg(stage)); + *timeout_ms = time_tick * 1000 / rtc_clk_slow_freq_get_hz(); + + return ESP_OK; +} + +esp_err_t rtc_wdt_set_stage(rtc_wdt_stage_t stage, rtc_wdt_stage_action_t stage_sel) +{ + if (stage > 3 || stage_sel > 4) { + return ESP_ERR_INVALID_ARG; + } + if (stage == RTC_WDT_STAGE0) { + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, stage_sel); + } else if (stage == RTC_WDT_STAGE1) { + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG1, stage_sel); + } else if (stage == RTC_WDT_STAGE2) { + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG2, stage_sel); + } else { + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG3, stage_sel); + } + + return ESP_OK; +} + +esp_err_t rtc_wdt_set_length_of_reset_signal(rtc_wdt_reset_sig_t reset_src, rtc_wdt_length_sig_t reset_signal_length) +{ + if (reset_src > 1 || reset_signal_length > 7) { + return ESP_ERR_INVALID_ARG; + } + if (reset_src == 0) { + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_SYS_RESET_LENGTH, reset_signal_length); + } else { + REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_CPU_RESET_LENGTH, reset_signal_length); + } + + return ESP_OK; +} + +bool rtc_wdt_is_on(void) +{ + return (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN) != 0) || (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN) != 0); +} diff --git a/components/soc/esp32s2beta/sources.cmake b/components/soc/esp32s2beta/sources.cmake index 8b8849b93..c8a542868 100644 --- a/components/soc/esp32s2beta/sources.cmake +++ b/components/soc/esp32s2beta/sources.cmake @@ -6,6 +6,7 @@ set(SOC_SRCS "cpu_util.c" "rtc_pm.c" "rtc_sleep.c" "rtc_time.c" + "rtc_wdt.c" "soc_memory_layout.c" "spi_periph.c" "ledc_periph.c" From 2644ddc3e19315ae0aea67b5fa52089a68b8b4e3 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 14 Aug 2019 22:54:07 +0800 Subject: [PATCH 3/5] esp32s2beta: Using rtc_wdt API --- components/esp32s2beta/panic.c | 43 +++++++++------------------- components/esp32s2beta/sleep_modes.c | 38 ++++++++++-------------- components/esp32s2beta/system_api.c | 17 +++++------ 3 files changed, 38 insertions(+), 60 deletions(-) diff --git a/components/esp32s2beta/panic.c b/components/esp32s2beta/panic.c index f68c37941..0082e0a85 100644 --- a/components/esp32s2beta/panic.c +++ b/components/esp32s2beta/panic.c @@ -470,32 +470,6 @@ static inline void disableAllWdts(void) TIMERG1.wdt_wprotect = 0; } -static void esp_panic_wdt_start(void) -{ - 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_clk_slow_freq_get_hz() * 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(void) -{ - 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); -} - #if CONFIG_ESP32S2_PANIC_PRINT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT static void esp_panic_dig_reset(void) __attribute__((noreturn)); @@ -628,7 +602,18 @@ static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame) int core_id = xPortGetCoreID(); // start panic WDT to restart system if we hang in this handler - esp_panic_wdt_start(); + if (!rtc_wdt_is_on()) { + rtc_wdt_protect_off(); + rtc_wdt_disable(); + rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us); + rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us); + rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_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. + rtc_wdt_set_time(RTC_WDT_STAGE0, 7000); + rtc_wdt_enable(); + rtc_wdt_protect_on(); + } //Feed the watchdogs, so they will give us time to print out debug info reconfigureAllWdts(); @@ -653,7 +638,7 @@ static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame) #if CONFIG_ESP32S2_PANIC_GDBSTUB disableAllWdts(); - esp_panic_wdt_stop(); + rtc_wdt_disable(); panicPutStr("Entering gdb stub now.\r\n"); esp_gdbstub_panic_handler(frame); #else @@ -674,7 +659,7 @@ static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame) reconfigureAllWdts(); } #endif /* CONFIG_ESP32_ENABLE_COREDUMP */ - esp_panic_wdt_stop(); + rtc_wdt_disable(); #if CONFIG_ESP32S2_PANIC_PRINT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT panicPutStr("Rebooting...\r\n"); if (frame->exccause != PANIC_RSN_CACHEERR) { diff --git a/components/esp32s2beta/sleep_modes.c b/components/esp32s2beta/sleep_modes.c index 5e723f755..f0c5bd24d 100644 --- a/components/esp32s2beta/sleep_modes.c +++ b/components/esp32s2beta/sleep_modes.c @@ -34,6 +34,7 @@ #include "soc/spi_mem_reg.h" #include "soc/sens_reg.h" #include "soc/dport_reg.h" +#include "soc/rtc_wdt.h" #include "driver/rtc_io.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -218,27 +219,6 @@ void IRAM_ATTR esp_deep_sleep_start(void) } } -static void rtc_wdt_enable(int time_ms) -{ - 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_RTC); - WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, rtc_clk_slow_freq_get_hz() * time_ms / 1000); - SET_PERI_REG_MASK(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN | RTC_CNTL_WDT_PAUSE_IN_SLP); - WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0); -} - -static void rtc_wdt_disable(void) -{ - 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); -} - /** * Helper function which handles entry to and exit from light sleep * Placed into IRAM as flash may need some time to be powered on. @@ -305,7 +285,17 @@ esp_err_t esp_light_sleep_start(void) rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails - rtc_wdt_enable(1000); + bool wdt_was_enabled = rtc_wdt_is_on(); // If WDT was enabled in the user code, then do not change it here. + if (!wdt_was_enabled) { + rtc_wdt_protect_off(); + rtc_wdt_disable(); + rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us); + rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us); + rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_RTC); + rtc_wdt_set_time(RTC_WDT_STAGE0, 1000); + rtc_wdt_enable(); + rtc_wdt_protect_on(); + } // Enter sleep, then wait for flash to be ready on wakeup esp_err_t err = esp_light_sleep_inner(pd_flags, @@ -331,7 +321,9 @@ esp_err_t esp_light_sleep_start(void) esp_timer_impl_unlock(); DPORT_STALL_OTHER_CPU_END(); - rtc_wdt_disable(); + if (!wdt_was_enabled) { + rtc_wdt_disable(); + } portEXIT_CRITICAL(&light_sleep_lock); return err; } diff --git a/components/esp32s2beta/system_api.c b/components/esp32s2beta/system_api.c index c27b9bebf..285a83ef6 100644 --- a/components/esp32s2beta/system_api.c +++ b/components/esp32s2beta/system_api.c @@ -31,6 +31,7 @@ #include "soc/timer_group_struct.h" #include "soc/cpu.h" #include "soc/rtc.h" +#include "soc/rtc_wdt.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/xtensa_api.h" @@ -254,14 +255,14 @@ void IRAM_ATTR esp_restart_noos(void) xt_ints_off(0xFFFFFFFF); // Enable RTC watchdog for 1 second - REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); - REG_WRITE(RTC_CNTL_WDTCONFIG0_REG, - RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M | - (RTC_WDT_STG_SEL_RESET_SYSTEM << RTC_CNTL_WDT_STG0_S) | - (RTC_WDT_STG_SEL_RESET_RTC << RTC_CNTL_WDT_STG1_S) | - (1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) | - (1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) ); - REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, rtc_clk_slow_freq_get_hz() * 1); + rtc_wdt_protect_off(); + rtc_wdt_disable(); + rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_RTC); + rtc_wdt_set_stage(RTC_WDT_STAGE1, RTC_WDT_STAGE_ACTION_RESET_SYSTEM); + rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_200ns); + rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_200ns); + rtc_wdt_set_time(RTC_WDT_STAGE0, 1000); + rtc_wdt_flashboot_mode_enable(); // Reset and stall the other CPU. // CPU must be reset before stalling, in case it was running a s32c1i From d1173c8f097204e7b392ee9fc2033453f3dc8b3c Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 14 Aug 2019 18:45:56 +0800 Subject: [PATCH 4/5] esp32s2beta: task_wdt Closes: IDF-753 --- components/esp32s2beta/cpu_start.c | 9 +++---- components/esp32s2beta/task_wdt.c | 38 +++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/components/esp32s2beta/cpu_start.c b/components/esp32s2beta/cpu_start.c index 4275e5ca5..4f3bdc37f 100644 --- a/components/esp32s2beta/cpu_start.c +++ b/components/esp32s2beta/cpu_start.c @@ -373,20 +373,17 @@ static void main_task(void* args) //Initialize task wdt if configured to do so #ifdef CONFIG_ESP_TASK_WDT_PANIC - //ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true)) + ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true)); #elif CONFIG_ESP_TASK_WDT - //ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false)) + ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false)); #endif //Add IDLE 0 to task wdt -// TODO: cpu_start.c: re-enable task WDT - IDF-753 -#if 0 #ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); if(idle_0 != NULL){ - ESP_ERROR_CHECK(esp_task_wdt_add(idle_0)) + ESP_ERROR_CHECK(esp_task_wdt_add(idle_0)); } -#endif #endif // Now that the application is about to start, disable boot watchdog diff --git a/components/esp32s2beta/task_wdt.c b/components/esp32s2beta/task_wdt.c index d43211254..e8ca2f773 100644 --- a/components/esp32s2beta/task_wdt.c +++ b/components/esp32s2beta/task_wdt.c @@ -28,12 +28,14 @@ #include "esp_intr_alloc.h" #include "esp_attr.h" #include "esp_freertos_hooks.h" -#include "soc/timer_group_struct.h" -#include "soc/timer_group_reg.h" +#include "soc/timer_periph.h" #include "esp_log.h" #include "driver/timer.h" #include "driver/periph_ctrl.h" #include "esp_task_wdt.h" +#include "esp_private/system_internal.h" + +static const char *TAG = "task_wdt"; //Assertion macro where, if 'cond' is false, will exit the critical section and return 'ret' #define ASSERT_EXIT_CRIT_RETURN(cond, ret) ({ \ @@ -114,13 +116,24 @@ static void reset_hw_timer(void) } } +/* + * This function is called by task_wdt_isr function (ISR for when TWDT times out). + * It can be redefined in user code to handle twdt events. + * Note: It has the same limitations as the interrupt function. + * Do not use ESP_LOGI functions inside. + */ +void __attribute__((weak)) esp_task_wdt_isr_user_handler(void) +{ + +} + /* * ISR for when TWDT times out. Checks for which tasks have not reset. Also * triggers panic if configured to do so */ static void task_wdt_isr(void *arg) { - portENTER_CRITICAL(&twdt_spinlock); + portENTER_CRITICAL_ISR(&twdt_spinlock); twdt_task_t *twdttask; const char *cpu; //Reset hardware timer so that 2nd stage timeout is not reached (will trigger system reset) @@ -129,7 +142,7 @@ static void task_wdt_isr(void *arg) TIMERG0.wdt_wprotect=0; //Acknowledge interrupt TIMERG0.int_clr.wdt=1; - //We are taking a spinlock while doing I/O (ets_printf) here. Normally, that is a pretty + //We are taking a spinlock while doing I/O (ESP_EARLY_LOGE) here. Normally, that is a pretty //bad thing, possibly (temporarily) hanging up the 2nd core and stopping FreeRTOS. In this case, //something bad already happened and reporting this is considered more important //than the badness caused by a spinlock here. @@ -138,26 +151,29 @@ static void task_wdt_isr(void *arg) ASSERT_EXIT_CRIT_RETURN((twdt_config->list != NULL), VOID_RETURN); //Watchdog got triggered because at least one task did not reset in time. - ets_printf("Task watchdog got triggered. The following tasks did not reset the watchdog in time:\n"); + ESP_EARLY_LOGE(TAG, "Task watchdog got triggered. The following tasks did not reset the watchdog in time:"); for (twdttask=twdt_config->list; twdttask!=NULL; twdttask=twdttask->next) { if (!twdttask->has_reset) { cpu=xTaskGetAffinity(twdttask->task_handle)==0?DRAM_STR("CPU 0"):DRAM_STR("CPU 1"); if (xTaskGetAffinity(twdttask->task_handle)==tskNO_AFFINITY) cpu=DRAM_STR("CPU 0/1"); - ets_printf(" - %s (%s)\n", pcTaskGetTaskName(twdttask->task_handle), cpu); + ESP_EARLY_LOGE(TAG, " - %s (%s)", pcTaskGetTaskName(twdttask->task_handle), cpu); } } - ets_printf(DRAM_STR("Tasks currently running:\n")); + ESP_EARLY_LOGE(TAG, "%s", DRAM_STR("Tasks currently running:")); for (int x=0; xpanic){ //Trigger Panic if configured to do so - ets_printf("Aborting.\n"); - portEXIT_CRITICAL(&twdt_spinlock); + ESP_EARLY_LOGE(TAG, "Aborting."); + portEXIT_CRITICAL_ISR(&twdt_spinlock); + // TODO: Add support reset reason for esp32s2beta. + // esp_reset_reason_set_hint(ESP_RST_TASK_WDT); abort(); } - portEXIT_CRITICAL(&twdt_spinlock); + portEXIT_CRITICAL_ISR(&twdt_spinlock); } /* From e0f7fbc5fa2988d87902d1362467427a51396abc Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Fri, 13 Sep 2019 00:39:37 +0800 Subject: [PATCH 5/5] bootloader: expand the space for iram_loader_seg Fixed ld issue: overflowed iram_loader_seg --- .../bootloader/subproject/main/ld/esp32s2beta/bootloader.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/bootloader/subproject/main/ld/esp32s2beta/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s2beta/bootloader.ld index b211cad61..97bb51e39 100644 --- a/components/bootloader/subproject/main/ld/esp32s2beta/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s2beta/bootloader.ld @@ -13,8 +13,8 @@ MEMORY { /* I/O */ dport0_seg (RW) : org = 0x3FF00000, len = 0x10 - iram_loader_seg (RWX) : org = 0x40062000, len = 0x2000 /* 8KB, IRAM */ - iram_seg (RWX) : org = 0x40064000, len = 0x4000 /* 16KB, IRAM */ + iram_loader_seg (RWX) : org = 0x40062000, len = 0x4000 /* 16KB, IRAM */ + iram_seg (RWX) : org = 0x40066000, len = 0x4000 /* 16KB, IRAM */ /* 16k at the end of DRAM, before ROM data & stack */ dram_seg (RW) : org = 0x3FFF8000, len = 0x4000 }