feat(esp_hw_support): support rtc wdt during deep sleep

This commit is contained in:
hebinglin
2026-01-20 20:09:22 +08:00
parent 8555a9b3c3
commit c02944f8b8
2 changed files with 41 additions and 1 deletions
+12 -1
View File
@@ -275,7 +275,7 @@ menu "Hardware Settings"
config ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
bool "Enable rtc wdt during sleep (EXPERIMENTAL)"
depends on IDF_EXPERIMENTAL_FEATURES
depends on SOC_LIGHT_SLEEP_SUPPORTED
depends on (SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED)
default n
help
If enabled, rtc watchdog will remain active during sleep to prevent program runaway. Specifically, its
@@ -288,6 +288,17 @@ menu "Hardware Settings"
this when enabling this option.
config ESP_SLEEP_ENABLE_RTC_WDT_IN_DEEP_SLEEP
bool "Enable rtc wdt during deep sleep (EXPERIMENTAL)"
depends on IDF_EXPERIMENTAL_FEATURES
depends on SOC_DEEP_SLEEP_SUPPORTED
default n
help
If enabled, rtc watchdog will remain active during deep sleep to prevent program runaway.
NOTE: In the current phase, the RTC watchdog will not be disabled or reset after waking from deep
sleep. Even though it will be reconfigured during the bootloader phase, there remains a concern that
a timeout could occur before this reconfiguration is completed.
endmenu
menu "RTC Clock Config"
+29
View File
@@ -1220,6 +1220,26 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
// Correct the sleep time
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_DEEP_SLEEP
// Safety net: enable WDT in case exit from deep sleep fails
wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
bool wdt_was_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx); // If WDT was enabled in the user code, then do not change it here.
if (!wdt_was_enabled) {
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
uint64_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
uint64_t sleep_timout_ticks = rtc_time_us_to_slowclk(s_config.sleep_duration, s_config.rtc_clk_cal_period);
#else
uint64_t sleep_timout_ticks = 0;
#endif
uint64_t slow_clk_comp_ticks = get_slow_clk_zero_drift_compensate(sleep_timout_ticks + stage_timeout_ticks);
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, (uint32_t)(stage_timeout_ticks + sleep_timout_ticks + slow_clk_comp_ticks), WDT_STAGE_ACTION_RESET_RTC);
wdt_hal_enable(&rtc_wdt_ctx);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
}
#endif
#if SOC_PMU_SUPPORTED
uint32_t force_pd_flags = PMU_SLEEP_PD_TOP | PMU_SLEEP_PD_VDDSDIO | PMU_SLEEP_PD_MODEM | PMU_SLEEP_PD_HP_PERIPH \
| PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_MEM | PMU_SLEEP_PD_XTAL;
@@ -1265,7 +1285,16 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
// can take several CPU cycles for the sleep mode to start.
ESP_INFINITE_LOOP();
}
// Never returns here, except that the sleep is rejected.
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_DEEP_SLEEP
if (!wdt_was_enabled) {
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_disable(&rtc_wdt_ctx);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
}
#endif
esp_ipc_isr_stall_resume();
esp_ipc_isr_release_other_cpu();
esp_os_exit_critical(&spinlock_rtc_deep_sleep);