mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
change(esp_hw_support): add sleep_rtc_wdt_prepare api for rtc wdt enable or disable
This commit is contained in:
@@ -282,10 +282,10 @@ menu "Hardware Settings"
|
||||
timeout will be set as the sum of the sleep duration, hardware overhead time, and RTC slow clock
|
||||
compensation time.
|
||||
|
||||
NOTE: In the current phase, the RTC slow clock compensation time remains zero (pending implementation).
|
||||
When using the RC_SLOW_CLK without calibration, the maximum continuous sleep duration is typically
|
||||
around 5 minutes, and may vary between chips. Therefore, avoid configuring sleep periods longer than
|
||||
this when enabling this option.
|
||||
NOTE: This feature only works when a timer wakeup is used. In the current phase, the RTC slow clock
|
||||
compensation time remains zero (pending implementation). When using the RC_SLOW_CLK without
|
||||
calibration, the maximum continuous sleep duration is typically around 5 minutes, and may vary
|
||||
between chips. Therefore, avoid configuring sleep periods longer than this when enabling this option.
|
||||
|
||||
|
||||
config ESP_SLEEP_ENABLE_RTC_WDT_IN_DEEP_SLEEP
|
||||
@@ -296,9 +296,10 @@ menu "Hardware Settings"
|
||||
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.
|
||||
NOTE: This feature only works when a timer wakeup is used. 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"
|
||||
|
||||
@@ -348,7 +348,8 @@ void esp_sleep_overhead_out_time_refresh(void)
|
||||
static uint32_t get_power_down_flags(void);
|
||||
static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep);
|
||||
static uint32_t get_sleep_clock_icg_flags(void);
|
||||
static uint32_t get_slow_clk_zero_drift_compensate(uint32_t sleep_duration);
|
||||
static uint32_t get_sleep_rtc_wdt_timeout(uint64_t sleep_duration);
|
||||
static uint32_t calc_sleep_slow_clk_required_cycles(uint32_t timeout, uint32_t rtc_slow_clk_cal_period);
|
||||
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
||||
static void ext0_wakeup_prepare(void);
|
||||
#endif
|
||||
@@ -766,6 +767,28 @@ static SLEEP_FN_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* RTC WDT prepare for using during sleep
|
||||
*/
|
||||
static SLEEP_FN_ATTR void sleep_rtc_wdt_prepare(bool enable)
|
||||
{
|
||||
wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
|
||||
if (enable) {
|
||||
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
|
||||
// Use default timeout for sleep monitoring
|
||||
uint32_t rtc_wdt_timeout = get_sleep_rtc_wdt_timeout(s_config.sleep_duration);
|
||||
uint32_t rtc_wdt_timeout_required_cycles = calc_sleep_slow_clk_required_cycles(rtc_wdt_timeout, s_config.rtc_clk_cal_period);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, rtc_wdt_timeout_required_cycles, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_enable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
} else {
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static SLEEP_FN_ATTR void sleep_low_power_clock_calibration(bool is_dslp)
|
||||
{
|
||||
// Calibrate rtc slow clock
|
||||
@@ -1223,20 +1246,11 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
#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);
|
||||
bool rtc_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 (!rtc_wdt_was_enabled) {
|
||||
sleep_rtc_wdt_prepare(true);
|
||||
} else {
|
||||
ESP_EARLY_LOGW(TAG, "RTC WDT is enabled and will not be reconfigured again!");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1285,13 +1299,10 @@ 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);
|
||||
if (!rtc_wdt_was_enabled) {
|
||||
sleep_rtc_wdt_prepare(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1566,20 +1577,11 @@ esp_err_t esp_light_sleep_start(void)
|
||||
|
||||
// Safety net: enable WDT in case exit from light 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);
|
||||
bool rtc_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 (!rtc_wdt_was_enabled) {
|
||||
sleep_rtc_wdt_prepare(true);
|
||||
} else {
|
||||
ESP_EARLY_LOGW(TAG, "RTC WDT is enabled and will not be reconfigured again!");
|
||||
}
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
@@ -1651,10 +1653,8 @@ esp_err_t esp_light_sleep_start(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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);
|
||||
if (!rtc_wdt_was_enabled) {
|
||||
sleep_rtc_wdt_prepare(false);
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
@@ -2959,11 +2959,33 @@ static SLEEP_FN_ATTR uint32_t get_sleep_clock_icg_flags(void)
|
||||
return clk_flags;
|
||||
}
|
||||
|
||||
/* Compensate zero drift of rtc slow clock in long-term working scenarios */
|
||||
static uint32_t get_slow_clk_zero_drift_compensate(uint32_t sleep_duration)
|
||||
/* TODO: PM-609 */
|
||||
/* Calculate drift cycles of rtc slow clock in long-term working scenarios. */
|
||||
static SLEEP_FN_ATTR uint32_t calc_sleep_slow_clk_required_cycles(uint32_t timeout, uint32_t rtc_slow_clk_cal_period)
|
||||
{
|
||||
(void) sleep_duration;
|
||||
return 0;
|
||||
uint32_t timeout_cycles = 0;
|
||||
uint32_t required_timeout_cycles = 0;
|
||||
timeout_cycles = (uint32_t)rtc_time_us_to_slowclk(timeout, rtc_slow_clk_cal_period);
|
||||
/* TODO: Add slow clock drift compensation */
|
||||
required_timeout_cycles = timeout_cycles;
|
||||
return required_timeout_cycles;
|
||||
}
|
||||
|
||||
/* Get the timeout in microseconds for the RTC WDT sleep monitoring.
|
||||
* Returns: default_timeout (1 second) + sleep_duration, all in microseconds.
|
||||
*/
|
||||
static SLEEP_FN_ATTR uint32_t get_sleep_rtc_wdt_timeout(uint64_t sleep_duration)
|
||||
{
|
||||
uint32_t default_timeout = 1000000; // 1 second in microseconds
|
||||
uint32_t sleep_timeout = 0;
|
||||
uint32_t rtc_wdt_timeout = 0;
|
||||
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP || CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_DEEP_SLEEP
|
||||
sleep_timeout = (uint32_t)sleep_duration;
|
||||
#endif
|
||||
rtc_wdt_timeout = default_timeout + sleep_timeout;
|
||||
|
||||
return rtc_wdt_timeout;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
Reference in New Issue
Block a user