mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
Merge branch 'feat/support_esp32c5_rtc_wdt_in_sleep' into 'master'
feat(esp_hw_support): support rtc wdt during light or deep sleep Closes PM-609, PM-654, IDFCI-5140, IDFCI-4784, IDFCI-4785, IDFCI-5139, and IDFCI-5050 See merge request espressif/esp-idf!43167
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
/* Functions */
|
||||
wdt_hal_init = 0x4fc001fc;
|
||||
wdt_hal_deinit = 0x4fc00200;
|
||||
wdt_hal_config_stage = 0x4fc00204;
|
||||
rom_wdt_hal_config_stage = 0x4fc00204;
|
||||
wdt_hal_write_protect_disable = 0x4fc00208;
|
||||
wdt_hal_write_protect_enable = 0x4fc0020c;
|
||||
wdt_hal_enable = 0x4fc00210;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -113,4 +113,17 @@ void wdt_hal_deinit(wdt_hal_context_t *hal)
|
||||
//Deinit HAL context
|
||||
hal->mwdt_dev = NULL;
|
||||
}
|
||||
|
||||
#if SOC_IS(ESP32P4)
|
||||
extern void rom_wdt_hal_config_stage(wdt_hal_context_t *hal, wdt_stage_t stage, uint32_t timeout, wdt_stage_action_t behavior);
|
||||
|
||||
/* rwdt_ll_config_stage is implemented erroneously in ESP32P4 rom code, TODO: PM-654*/
|
||||
void wdt_hal_config_stage(wdt_hal_context_t *hal, wdt_stage_t stage, uint32_t timeout_ticks, wdt_stage_action_t behavior)
|
||||
{
|
||||
if (hal->inst == WDT_RWDT && stage == WDT_STAGE0) {
|
||||
timeout_ticks = timeout_ticks >> (1 + REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_WDT_DELAY_SEL));
|
||||
}
|
||||
rom_wdt_hal_config_stage(hal, stage, timeout_ticks, behavior);
|
||||
}
|
||||
#endif // SOC_IS(ESP32P4)
|
||||
#endif // ESP_ROM_WDT_INIT_PATCH
|
||||
|
||||
@@ -272,6 +272,34 @@ menu "Hardware Settings"
|
||||
to configure the value of tRES1, different types of flash require different tRES1 values, usually no
|
||||
more than 35us, please refer to the datasheet of the used Flash to configure this option.
|
||||
|
||||
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 || SOC_DEEP_SLEEP_SUPPORTED)
|
||||
default n
|
||||
help
|
||||
If enabled, rtc watchdog will remain active during sleep to prevent program runaway. Specifically, its
|
||||
timeout will be set as the sum of the sleep duration, hardware overhead time, and RTC slow clock
|
||||
compensation time.
|
||||
|
||||
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 clock 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
|
||||
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: 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"
|
||||
|
||||
@@ -47,6 +47,7 @@ typedef enum {
|
||||
#define RTC_SLEEP_PD_MODEM PMU_SLEEP_PD_MODEM //!< Power down modem(include wifi, ble and 15.4)
|
||||
|
||||
//These flags are not power domains, but will affect some sleep parameters
|
||||
#define RTC_SLEEP_USE_RTC_WDT BIT(23)
|
||||
#define RTC_SLEEP_FLASH_DPD BIT(24)
|
||||
#define RTC_SLEEP_LP_PERIPH_USE_RC_FAST BIT(25)
|
||||
#define RTC_SLEEP_POWER_BY_VBAT BIT(26)
|
||||
|
||||
@@ -510,6 +510,7 @@ typedef struct rtc_sleep_config_s {
|
||||
uint32_t deep_slp_reject : 1; //!< enable deep sleep reject
|
||||
uint32_t light_slp_reject : 1; //!< enable light sleep reject
|
||||
uint32_t dbg_atten_slp : 2; //!< voltage parameter
|
||||
uint32_t rtc_wdt_en : 1; //!< enable rtc wdt, in sleep mode
|
||||
} rtc_sleep_config_t;
|
||||
|
||||
#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain)
|
||||
@@ -531,6 +532,7 @@ typedef struct rtc_sleep_config_s {
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19)
|
||||
#define RTC_SLEEP_FLASH_DPD BIT(20)
|
||||
#define RTC_SLEEP_USE_RTC_WDT BIT(21)
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#include "hal/rwdt_ll.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#define MHZ (1000000)
|
||||
@@ -122,6 +123,12 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
|
||||
// make sure voltage is raised when RTC 8MCLK is enabled
|
||||
out_config->dbias_follow_8m = 1;
|
||||
}
|
||||
|
||||
if (sleep_flags & RTC_SLEEP_USE_RTC_WDT) {
|
||||
out_config->rtc_wdt_en = 1;
|
||||
} else {
|
||||
out_config->rtc_wdt_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
@@ -237,6 +244,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_SLEEP_FOLW_8M);
|
||||
}
|
||||
|
||||
/* enable rtc wdt during sleep */
|
||||
rwdt_ll_write_protect_disable(RWDT_DEV_GET());
|
||||
rwdt_ll_set_pause_in_sleep_en(RWDT_DEV_GET(), !cfg.rtc_wdt_en);
|
||||
rwdt_ll_write_protect_enable(RWDT_DEV_GET());
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
||||
@@ -555,6 +555,7 @@ typedef struct {
|
||||
uint32_t rtc_regulator_fpu : 1; //!< keep rtc regulator powered up in sleep
|
||||
uint32_t deep_slp_reject : 1; //!< enable deep sleep reject
|
||||
uint32_t light_slp_reject : 1; //!< enable light sleep reject
|
||||
uint32_t rtc_wdt_en : 1; //!< enable rtc wdt, in sleep mode
|
||||
} rtc_sleep_config_t;
|
||||
|
||||
#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain)
|
||||
@@ -568,6 +569,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19)
|
||||
#define RTC_SLEEP_FLASH_DPD BIT(20)
|
||||
#define RTC_SLEEP_USE_RTC_WDT BIT(21)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "soc/regi2c_lp_bias.h"
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "hal/rwdt_ll.h"
|
||||
|
||||
static const DRAM_ATTR rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
|
||||
|
||||
@@ -141,6 +142,12 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
|
||||
out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
|
||||
out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
|
||||
}
|
||||
|
||||
if (sleep_flags & RTC_SLEEP_USE_RTC_WDT) {
|
||||
out_config->rtc_wdt_en = 1;
|
||||
} else {
|
||||
out_config->rtc_wdt_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
@@ -182,6 +189,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING);
|
||||
}
|
||||
|
||||
/* enable rtc wdt during sleep */
|
||||
rwdt_ll_write_protect_disable(RWDT_DEV_GET());
|
||||
rwdt_ll_set_pause_in_sleep_en(RWDT_DEV_GET(), !cfg.rtc_wdt_en);
|
||||
rwdt_ll_write_protect_enable(RWDT_DEV_GET());
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_VDD_SPI_PWR_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_VDD_SPI_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
||||
@@ -595,6 +595,7 @@ typedef struct {
|
||||
uint32_t rtc_regulator_fpu : 1; //!< keep rtc regulator powered up in sleep
|
||||
uint32_t deep_slp_reject : 1; //!< enable deep sleep reject
|
||||
uint32_t light_slp_reject : 1; //!< enable light sleep reject
|
||||
uint32_t rtc_wdt_en : 1; //!< enable rtc wdt, in sleep mode
|
||||
} rtc_sleep_config_t;
|
||||
|
||||
#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain)
|
||||
@@ -616,6 +617,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19)
|
||||
#define RTC_SLEEP_FLASH_DPD BIT(20)
|
||||
#define RTC_SLEEP_USE_RTC_WDT BIT(21)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "soc/regi2c_lp_bias.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "hal/rwdt_ll.h"
|
||||
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
#include "soc/systimer_reg.h"
|
||||
#endif
|
||||
@@ -166,6 +167,12 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
|
||||
out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
|
||||
out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
|
||||
}
|
||||
|
||||
if (sleep_flags & RTC_SLEEP_USE_RTC_WDT) {
|
||||
out_config->rtc_wdt_en = 1;
|
||||
} else {
|
||||
out_config->rtc_wdt_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
@@ -233,6 +240,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING);
|
||||
}
|
||||
|
||||
/* enable rtc wdt during sleep */
|
||||
rwdt_ll_write_protect_disable(RWDT_DEV_GET());
|
||||
rwdt_ll_set_pause_in_sleep_en(RWDT_DEV_GET(), !cfg.rtc_wdt_en);
|
||||
rwdt_ll_write_protect_enable(RWDT_DEV_GET());
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
||||
@@ -316,6 +316,7 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
|
||||
{
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
}
|
||||
|
||||
@@ -330,6 +330,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = clk_flags \
|
||||
}
|
||||
@@ -337,6 +338,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
}
|
||||
|
||||
@@ -307,6 +307,7 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
|
||||
{
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
}
|
||||
|
||||
@@ -326,6 +326,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = clk_flags \
|
||||
}
|
||||
@@ -333,6 +334,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
}
|
||||
|
||||
@@ -293,6 +293,7 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
|
||||
{
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
}
|
||||
|
||||
@@ -326,6 +326,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = clk_flags \
|
||||
}
|
||||
@@ -333,6 +334,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
|
||||
{
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
}
|
||||
|
||||
@@ -318,6 +318,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = clk_flags \
|
||||
}
|
||||
@@ -325,6 +326,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
|
||||
{
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
}
|
||||
|
||||
@@ -351,6 +351,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = clk_flags \
|
||||
}
|
||||
@@ -358,6 +359,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi
|
||||
|
||||
static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp)
|
||||
{
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
if (!dslp) {
|
||||
|
||||
@@ -358,6 +358,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = clk_flags \
|
||||
}
|
||||
@@ -365,6 +366,7 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
}
|
||||
|
||||
@@ -267,6 +267,7 @@ static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_c
|
||||
{
|
||||
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.lp_pad_hold_all);
|
||||
pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
|
||||
// Lowpower workaround for LP pad holding, JTAG IOs is located on lp_pad on esp32p4, if hold its
|
||||
// default state on sleep, there's a high current leakage.
|
||||
|
||||
@@ -336,6 +336,7 @@ typedef struct {
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -343,18 +344,21 @@ typedef struct {
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
} \
|
||||
}
|
||||
#else // !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -623,6 +623,7 @@ typedef struct {
|
||||
uint32_t rtc_regulator_fpu : 1; //!< keep rtc regulator powered up in sleep
|
||||
uint32_t deep_slp_reject : 1; //!< enable deep sleep reject
|
||||
uint32_t light_slp_reject : 1; //!< enable light sleep reject
|
||||
uint32_t rtc_wdt_en : 1; //!< enable rtc wdt, in sleep mode
|
||||
} rtc_sleep_config_t;
|
||||
|
||||
#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain)
|
||||
@@ -641,6 +642,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19)
|
||||
#define RTC_SLEEP_FLASH_DPD BIT(20)
|
||||
#define RTC_SLEEP_USE_RTC_WDT BIT(20)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#include "hal/rwdt_ll.h"
|
||||
|
||||
/**
|
||||
* Configure whether certain peripherals are powered down in deep sleep
|
||||
@@ -158,6 +159,12 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
|
||||
out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
|
||||
out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
|
||||
}
|
||||
|
||||
if (sleep_flags & RTC_SLEEP_USE_RTC_WDT) {
|
||||
out_config->rtc_wdt_en = 1;
|
||||
} else {
|
||||
out_config->rtc_wdt_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
@@ -237,6 +244,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
||||
}
|
||||
|
||||
/* enable rtc wdt during sleep */
|
||||
rwdt_ll_write_protect_disable(RWDT_DEV_GET());
|
||||
rwdt_ll_set_pause_in_sleep_en(RWDT_DEV_GET(), !cfg.rtc_wdt_en);
|
||||
rwdt_ll_write_protect_enable(RWDT_DEV_GET());
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
||||
@@ -607,6 +607,7 @@ typedef struct {
|
||||
uint32_t rtc_regulator_fpu : 1; //!< keep rtc regulator powered up in sleep
|
||||
uint32_t deep_slp_reject : 1; //!< enable deep sleep reject
|
||||
uint32_t light_slp_reject : 1; //!< enable light sleep reject
|
||||
uint32_t rtc_wdt_en : 1; //!< enable rtc wdt, in sleep mode
|
||||
} rtc_sleep_config_t;
|
||||
|
||||
#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain)
|
||||
@@ -627,6 +628,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
#define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19)
|
||||
#define RTC_SLEEP_FLASH_DPD BIT(20)
|
||||
#define RTC_SLEEP_USE_RTC_WDT BIT(21)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "soc/fe_reg.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "hal/rwdt_ll.h"
|
||||
|
||||
#define RTC_CNTL_MEM_FOLW_CPU (RTC_CNTL_SLOWMEM_FOLW_CPU | RTC_CNTL_FASTMEM_FOLW_CPU)
|
||||
|
||||
@@ -169,6 +170,12 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
|
||||
out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
|
||||
out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
|
||||
}
|
||||
|
||||
if (sleep_flags & RTC_SLEEP_USE_RTC_WDT) {
|
||||
out_config->rtc_wdt_en = 1;
|
||||
} else {
|
||||
out_config->rtc_wdt_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
@@ -243,6 +250,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
||||
}
|
||||
|
||||
/* enable rtc wdt during sleep */
|
||||
rwdt_ll_write_protect_disable(RWDT_DEV_GET());
|
||||
rwdt_ll_set_pause_in_sleep_en(RWDT_DEV_GET(), !cfg.rtc_wdt_en);
|
||||
rwdt_ll_write_protect_enable(RWDT_DEV_GET());
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
||||
@@ -348,6 +348,10 @@ 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);
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
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);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
||||
static void ext0_wakeup_prepare(void);
|
||||
#endif
|
||||
@@ -765,6 +769,33 @@ 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_required_cycles = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) {
|
||||
uint32_t rtc_wdt_timeout = get_sleep_rtc_wdt_timeout(s_config.sleep_duration);
|
||||
rtc_wdt_timeout_required_cycles = calc_sleep_slow_clk_required_cycles(rtc_wdt_timeout, s_config.rtc_clk_cal_period);
|
||||
}
|
||||
#endif
|
||||
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
|
||||
@@ -1219,6 +1250,15 @@ 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;
|
||||
|
||||
// Safety net: enable WDT in case exit from deep sleep fails
|
||||
wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
|
||||
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!");
|
||||
}
|
||||
|
||||
#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,6 +1305,10 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
ESP_INFINITE_LOOP();
|
||||
}
|
||||
// Never returns here, except that the sleep is rejected.
|
||||
if (!rtc_wdt_was_enabled) {
|
||||
sleep_rtc_wdt_prepare(false);
|
||||
}
|
||||
|
||||
esp_ipc_isr_stall_resume();
|
||||
esp_ipc_isr_release_other_cpu();
|
||||
esp_os_exit_critical(&spinlock_rtc_deep_sleep);
|
||||
@@ -1536,14 +1580,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);
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_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;
|
||||
@@ -1615,10 +1656,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
|
||||
@@ -2868,6 +2907,14 @@ static SLEEP_FN_ATTR uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsle
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) {
|
||||
sleep_flags |= RTC_SLEEP_USE_RTC_WDT;
|
||||
} else {
|
||||
sleep_flags &= ~RTC_SLEEP_USE_RTC_WDT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
/* Due to esp32p4 eco0 hardware bug, if LP peripheral power domain is powerdowned in sleep, there will be a possibility of
|
||||
triggering the EFUSE_CRC reset, so disable the power-down of this power domain on lightsleep for ECO0 version. */
|
||||
@@ -2919,6 +2966,35 @@ static SLEEP_FN_ATTR uint32_t get_sleep_clock_icg_flags(void)
|
||||
return clk_flags;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
|
||||
sleep_timeout = (uint32_t)sleep_duration;
|
||||
rtc_wdt_timeout = default_timeout + sleep_timeout;
|
||||
|
||||
return rtc_wdt_timeout;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* APP core of esp32 can't access to RTC FAST MEMORY, do not define it with RTC_IRAM_ATTR */
|
||||
RTC_SLOW_ATTR
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "esp_system.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_private/rtc_ctrl.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
|
||||
/* As the RTC slow clock used by RWDT is derived using RC oscillator by default,
|
||||
* the timing accuracy is not very precise, and may vary from chip to chip.
|
||||
@@ -178,6 +179,50 @@ static void rtc_wdt_setup_then_reset_RTC(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_LIGHT_SLEEP_SUPPORTED && CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
/* MULTI test case for light sleep prepare timeout then RTC WDT resets RTC */
|
||||
static void rtc_wdt_light_sleep_prepare_timeout(void)
|
||||
{
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1000 * rtc_clk_slow_freq_get_hz() / 1000ULL); /* 1000ms for interrupt */
|
||||
esp_sleep_enable_timer_wakeup(3000000);
|
||||
|
||||
/* Setup RTC WDT */
|
||||
// Here enable RTC_WDT then the setup in sleep flow will be skipped
|
||||
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, true);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_enable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
TEST_ASSERT_TRUE(wdt_hal_is_enabled(&rtc_wdt_ctx));
|
||||
printf("RTC WDT setup stage-0 RESET (1000ms)\n");
|
||||
|
||||
esp_light_sleep_start();
|
||||
/* Wait for RTC WDT to reset the main system and RTC */
|
||||
esp_restart();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_DEEP_SLEEP_SUPPORTED && CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
/* MULTI test case for deep sleep prepare timeout then RTC WDT resets RTC */
|
||||
static void rtc_wdt_deep_sleep_prepare_timeout(void)
|
||||
{
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1000 * rtc_clk_slow_freq_get_hz() / 1000ULL); /* 1000ms for interrupt */
|
||||
esp_sleep_enable_timer_wakeup(3000000);
|
||||
|
||||
/* Setup RTC WDT */
|
||||
// Here enable RTC_WDT then the setup in sleep flow will be skipped
|
||||
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, true);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_enable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
TEST_ASSERT_TRUE(wdt_hal_is_enabled(&rtc_wdt_ctx));
|
||||
printf("RTC WDT setup stage-0 RESET (1000ms)\n");
|
||||
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rtc_wdt_verify_SYSTEM_reset(void)
|
||||
{
|
||||
printf("Confirming if reset reason matches 0x9 (main system reset)\n");
|
||||
@@ -211,3 +256,21 @@ TEST_CASE_MULTIPLE_STAGES(
|
||||
rtc_wdt_setup_then_reset_RTC,
|
||||
rtc_wdt_verify_RTC_reset
|
||||
)
|
||||
|
||||
#if SOC_LIGHT_SLEEP_SUPPORTED && CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
TEST_CASE_MULTIPLE_STAGES(
|
||||
"Light sleep prepare timeout then RTC WDT resets RTC",
|
||||
"[rtc_wdt][lightsleep][reset]",
|
||||
rtc_wdt_light_sleep_prepare_timeout,
|
||||
rtc_wdt_verify_RTC_reset
|
||||
)
|
||||
#endif
|
||||
|
||||
#if SOC_DEEP_SLEEP_SUPPORTED && CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP
|
||||
TEST_CASE_MULTIPLE_STAGES(
|
||||
"Deep sleep prepare timeout then RTC WDT resets RTC",
|
||||
"[rtc_wdt][deepsleep][reset]",
|
||||
rtc_wdt_deep_sleep_prepare_timeout,
|
||||
rtc_wdt_verify_RTC_reset
|
||||
)
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,7 @@ from pytest_embedded_idf.utils import soc_filtered_targets
|
||||
('single_core_esp32', 'esp32'),
|
||||
*(('default', target) for target in soc_filtered_targets('IDF_TARGET not in ["esp32c5"]')),
|
||||
*(('release', target) for target in soc_filtered_targets('IDF_TARGET not in ["esp32c5"]')),
|
||||
*(('rwdt_monitor', target) for target in soc_filtered_targets('IDF_TARGET not in ["esp32c5"]')),
|
||||
],
|
||||
indirect=['config', 'target'],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# enable RTC WDT during sleep period
|
||||
CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
Reference in New Issue
Block a user