diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 73a799562..fe0d756fb 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -39,6 +39,7 @@ #include "soc/timer_group_reg.h" #include "soc/gpio_reg.h" #include "soc/gpio_sig_map.h" +#include "soc/rtc_wdt.h" #include "sdkconfig.h" #include "esp_image_format.h" @@ -143,7 +144,7 @@ static esp_err_t bootloader_main() ets_set_appcpu_boot_addr(0); /* disable watch dog here */ - REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN ); + rtc_wdt_disable(); REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN ); #ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 4d907f333..1c9ca7397 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -29,6 +29,7 @@ #include "soc/io_mux_reg.h" #include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" +#include "soc/rtc_wdt.h" #include "driver/rtc_io.h" @@ -136,7 +137,7 @@ void IRAM_ATTR call_start_cpu0() || rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET #endif ) { - esp_panic_wdt_stop(); + rtc_wdt_disable(); } //Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this. @@ -435,7 +436,7 @@ 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); + rtc_wdt_disable(); #if !CONFIG_FREERTOS_UNICORE // Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack while (port_xSchedulerRunning[1] == 0) { diff --git a/components/esp32/include/esp_panic.h b/components/esp32/include/esp_panic.h index 4e0630a24..b9e192f04 100644 --- a/components/esp32/include/esp_panic.h +++ b/components/esp32/include/esp_panic.h @@ -61,12 +61,6 @@ 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); - /** * @brief Checks stack pointer */ diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 8edb70b23..5a000574b 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -30,6 +30,7 @@ #include "soc/timer_group_reg.h" #include "soc/cpu.h" #include "soc/rtc.h" +#include "soc/rtc_wdt.h" #include "esp_gdbstub.h" #include "esp_panic.h" @@ -374,32 +375,6 @@ static inline void disableAllWdts() TIMERG1.wdt_wprotect = 0; } -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_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() -{ - 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 void esp_panic_dig_reset() __attribute__((noreturn)); static void esp_panic_dig_reset() @@ -528,7 +503,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(); @@ -553,7 +539,7 @@ static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame) #if CONFIG_ESP32_PANIC_GDBSTUB disableAllWdts(); - esp_panic_wdt_stop(); + rtc_wdt_disable(); panicPutStr("Entering gdb stub now.\r\n"); esp_gdbstub_panic_handler(frame); #else @@ -574,7 +560,7 @@ static __attribute__((noreturn)) void commonErrorHandler(XtExcFrame *frame) reconfigureAllWdts(); } #endif /* CONFIG_ESP32_ENABLE_COREDUMP */ - esp_panic_wdt_stop(); + rtc_wdt_disable(); #if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT panicPutStr("Rebooting...\r\n"); if (frame->exccause != PANIC_RSN_CACHEERR) { diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index f4cefb98b..91713ad6b 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -32,6 +32,7 @@ #include "soc/spi_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" @@ -238,27 +239,6 @@ void IRAM_ATTR esp_deep_sleep_start() } } -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() -{ - 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. @@ -326,7 +306,17 @@ esp_err_t esp_light_sleep_start() 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, @@ -352,7 +342,9 @@ esp_err_t esp_light_sleep_start() 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/esp32/system_api.c b/components/esp32/system_api.c index 8068f3bc4..f56bf622e 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/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" @@ -270,14 +271,15 @@ void IRAM_ATTR esp_restart_noos() 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_enable(); + rtc_wdt_protect_on(); // Reset and stall the other CPU. // CPU must be reset before stalling, in case it was running a s32c1i diff --git a/components/soc/esp32/rtc_wdt.c b/components/soc/esp32/rtc_wdt.c new file mode 100644 index 000000000..8daa352f3 --- /dev/null +++ b/components/soc/esp32/rtc_wdt.c @@ -0,0 +1,125 @@ +// 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() +{ + return READ_PERI_REG(RTC_CNTL_WDTWPROTECT_REG) != RTC_CNTL_WDT_WKEY_VALUE; +} + +void rtc_wdt_protect_off() +{ + WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); +} + +void rtc_wdt_protect_on() +{ + WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0); +} + + +void rtc_wdt_enable() +{ + 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_disable() +{ + 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() +{ + 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(); + } +} + +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 = rtc_clk_slow_freq_get_hz() * timeout_ms / 1000; + if (stage == RTC_WDT_STAGE0) { + WRITE_PERI_REG(RTC_CNTL_WDTCONFIG1_REG, timeout); + } else if (stage == RTC_WDT_STAGE1) { + WRITE_PERI_REG(RTC_CNTL_WDTCONFIG2_REG, timeout); + } else if (stage == RTC_WDT_STAGE2) { + WRITE_PERI_REG(RTC_CNTL_WDTCONFIG3_REG, timeout); + } else { + WRITE_PERI_REG(RTC_CNTL_WDTCONFIG4_REG, timeout); + } + + 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() +{ + 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/include/soc/rtc_wdt.h b/components/soc/include/soc/rtc_wdt.h new file mode 100644 index 000000000..9094a305a --- /dev/null +++ b/components/soc/include/soc/rtc_wdt.h @@ -0,0 +1,181 @@ +// 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. + +/* Recommendation of using API RTC_WDT. +1) Setting and enabling rtc_wdt: +@code + 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_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM); //RTC_WDT_STAGE_ACTION_RESET_SYSTEM or RTC_WDT_STAGE_ACTION_RESET_RTC + rtc_wdt_set_time(RTC_WDT_STAGE0, 7000); // timeout rtd_wdt 7000ms. + rtc_wdt_enable(); + rtc_wdt_protect_on(); + @endcode + +* If you use this option RTC_WDT_STAGE_ACTION_RESET_SYSTEM then after reset you can see these messages. +They can help to understand where the CPUs were when the WDT was triggered. + W (30) boot: PRO CPU has been reset by WDT. + W (30) boot: WDT reset info: PRO CPU PC=0x400xxxxx + ... function where it happened + + W (31) boot: WDT reset info: APP CPU PC=0x400xxxxx + ... function where it happened + +* If you use this option RTC_WDT_STAGE_ACTION_RESET_RTC then you will see message (rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)) +without description where were CPUs when it happened. + +2) Reset counter of rtc_wdt: +@code + rtc_wdt_feed(); +@endcode + +3) Disable rtc_wdt: +@code + rtc_wdt_disable(); +@endcode + */ + +#ifndef _SOC_RTC_WDT_H +#define _SOC_RTC_WDT_H + +#include +#include +#include "soc/rtc_cntl_reg.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/// List of stage of rtc watchdog. WDT has 4 stage. +typedef enum { + RTC_WDT_STAGE0 = 0, /*!< Stage 0 */ + RTC_WDT_STAGE1 = 1, /*!< Stage 1 */ + RTC_WDT_STAGE2 = 2, /*!< Stage 2 */ + RTC_WDT_STAGE3 = 3 /*!< Stage 3 */ +} rtc_wdt_stage_t; + +/// List of action. When the time of stage expires this action will be triggered. +typedef enum { + RTC_WDT_STAGE_ACTION_OFF = RTC_WDT_STG_SEL_OFF, /*!< Disabled. This stage will have no effects on the system. */ + RTC_WDT_STAGE_ACTION_INTERRUPT = RTC_WDT_STG_SEL_INT, /*!< Trigger an interrupt. When the stage expires an interrupt is triggered. */ + RTC_WDT_STAGE_ACTION_RESET_CPU = RTC_WDT_STG_SEL_RESET_CPU, /*!< Reset a CPU core. */ + RTC_WDT_STAGE_ACTION_RESET_SYSTEM = RTC_WDT_STG_SEL_RESET_SYSTEM, /*!< Reset the main system includes the CPU and all peripherals. The RTC is an exception to this, and it will not be reset. */ + RTC_WDT_STAGE_ACTION_RESET_RTC = RTC_WDT_STG_SEL_RESET_RTC /*!< Reset the main system and the RTC. */ +} rtc_wdt_stage_action_t; + +/// Type of reset signal +typedef enum { + RTC_WDT_SYS_RESET_SIG = 0, /*!< System reset signal length selection */ + RTC_WDT_CPU_RESET_SIG = 1 /*!< CPU reset signal length selection */ +} rtc_wdt_reset_sig_t; + +/// Length of reset signal +typedef enum { + RTC_WDT_LENGTH_100ns = 0, /*!< 100 ns */ + RTC_WDT_LENGTH_200ns = 1, /*!< 200 ns */ + RTC_WDT_LENGTH_300ns = 2, /*!< 300 ns */ + RTC_WDT_LENGTH_400ns = 3, /*!< 400 ns */ + RTC_WDT_LENGTH_500ns = 4, /*!< 500 ns */ + RTC_WDT_LENGTH_800ns = 5, /*!< 800 ns */ + RTC_WDT_LENGTH_1_6us = 6, /*!< 1.6 us */ + RTC_WDT_LENGTH_3_2us = 7 /*!< 3.2 us */ +} rtc_wdt_length_sig_t; + +/** + * @brief Get status of protect of rtc_wdt. + * + * @return + * - True if the protect of RTC_WDT is set + */ +bool rtc_wdt_get_protect_status(); + +/** + * @brief Set protect of rtc_wdt. + */ +void rtc_wdt_protect_on(); + +/** + * @brief Reset protect of rtc_wdt. + */ +void rtc_wdt_protect_off(); + +/** + * @brief Enable rtc_wdt. + */ +void rtc_wdt_enable(); + +/** + * @brief Disable rtc_wdt. + */ +void rtc_wdt_disable(); + +/** + * @brief Reset counter rtc_wdt. + * + * It returns to stage 0 and its expiry counter restarts from 0. + */ +void rtc_wdt_feed(); + +/** + * @brief Set time for required stage. + * + * @param[in] stage Stage of rtc_wdt. + * @param[in] timeout_ms Timeout for this stage. + * + * @return + * - ESP_OK In case of success + * - ESP_ERR_INVALID_ARG If stage has invalid value + */ +esp_err_t rtc_wdt_set_time(rtc_wdt_stage_t stage, unsigned int timeout_ms); + +/** + * @brief Set an action for required stage. + * + * @param[in] stage Stage of rtc_wdt. + * @param[in] stage_sel Action for this stage. When the time of stage expires this action will be triggered. + * + * @return + * - ESP_OK In case of success + * - ESP_ERR_INVALID_ARG If stage or stage_sel have invalid value + */ +esp_err_t rtc_wdt_set_stage(rtc_wdt_stage_t stage, rtc_wdt_stage_action_t stage_sel); + +/** + * @brief Set a length of reset signal. + * + * @param[in] reset_src Type of reset signal. + * @param[in] reset_signal_length A length of reset signal. + * + * @return + * - ESP_OK In case of success + * - ESP_ERR_INVALID_ARG If reset_src or reset_signal_length have invalid value + */ +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); + +/** + * @brief Return true if rtc_wdt is enabled. + * + * @return + * - True rtc_wdt is enabled + */ +bool rtc_wdt_is_on(); + +#ifdef __cplusplus +} +#endif + +#endif // _SOC_RTC_WDT_H