diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 9456650f7e..59941ad78a 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 1b58527ad6..c4d2491899 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 568cc584c0..4275e5ca5d 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 0000000000..9ef52c17e4 --- /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 8b8849b931..c8a5428681 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"