mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(esp_hw_support): support rtc wdt during light sleep
This commit is contained in:
@@ -272,6 +272,22 @@ 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
|
||||
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: 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.
|
||||
|
||||
|
||||
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,7 @@ 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);
|
||||
#if SOC_PM_SUPPORT_EXT0_WAKEUP
|
||||
static void ext0_wakeup_prepare(void);
|
||||
#endif
|
||||
@@ -1539,9 +1540,15 @@ esp_err_t esp_light_sleep_start(void)
|
||||
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);
|
||||
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, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
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);
|
||||
}
|
||||
@@ -2868,6 +2875,10 @@ 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
|
||||
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 +2930,13 @@ 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)
|
||||
{
|
||||
(void) sleep_duration;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user