mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
feat(esp_hw_support): add flash deep power down support during sleep
This commit is contained in:
@@ -219,6 +219,7 @@ menu "Hardware Settings"
|
||||
bool "Set SPI flash to deep power-down mode in light sleep"
|
||||
depends on (!APP_BUILD_TYPE_PURE_RAM_APP && !ESP_SLEEP_POWER_DOWN_FLASH && !SPI_FLASH_ROM_IMPL)
|
||||
default y if (IDF_TARGET_ESP32H4 || IDF_TARGET_ESP32H21)
|
||||
default y if (IDF_TARGET_ESP32P4 && ESP32P4_SELECTS_REV_LESS_V3)
|
||||
default n
|
||||
help
|
||||
Deep Power-Down mode is a power mode supported by most SPI Flash, SPI Flash has better power
|
||||
@@ -236,7 +237,7 @@ menu "Hardware Settings"
|
||||
config ESP_SLEEP_SPI_FLASH_ENTER_DPD_MODE_DELAY
|
||||
int "SPI Flash enter deep power-down time delay (in us)"
|
||||
depends on ESP_SLEEP_SET_FLASH_DPD
|
||||
default 20
|
||||
default 25
|
||||
range 0 100
|
||||
help
|
||||
When used to set the SPI Flash to enter the Deep Power-Down mode, the command is issued by driving
|
||||
|
||||
@@ -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_FLASH_DPD BIT(24)
|
||||
#define RTC_SLEEP_LP_PERIPH_USE_RC_FAST BIT(25)
|
||||
#define RTC_SLEEP_POWER_BY_VBAT BIT(26)
|
||||
#define RTC_SLEEP_DIG_USE_8M BIT(27)
|
||||
|
||||
@@ -530,6 +530,7 @@ typedef struct rtc_sleep_config_s {
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#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)
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
*
|
||||
|
||||
@@ -567,6 +567,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#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)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -615,6 +615,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#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)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -91,7 +91,7 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
|
||||
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100) && (mode == PMU_MODE_HP_SLEEP)) {
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300) && (mode == PMU_MODE_HP_SLEEP)) {
|
||||
pmu_ll_hp_enable_sleep_flash_ldo_channel(ctx->hal->dev, anlg->regulator0.xpd_0p1a);
|
||||
}
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
|
||||
|
||||
@@ -176,7 +176,11 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
analog_default.hp_sys.analog.xpd_0p1a = 0;
|
||||
if (sleep_flags & PMU_SLEEP_PD_VDDSDIO) {
|
||||
analog_default.hp_sys.analog.xpd_0p1a = 0;
|
||||
} else {
|
||||
analog_default.hp_sys.analog.xpd_0p1a = 1;
|
||||
}
|
||||
config->analog = analog_default;
|
||||
|
||||
if (sleep_flags & RTC_SLEEP_POWER_BY_VBAT) {
|
||||
@@ -296,7 +300,7 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) {
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300)) {
|
||||
pmu_ll_hp_enable_sleep_flash_ldo_channel(ctx->hal->dev, analog->hp_sys.analog.xpd_0p1a);
|
||||
}
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias);
|
||||
|
||||
@@ -640,6 +640,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#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)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -626,6 +626,7 @@ typedef struct {
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#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)
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_private/io_mux.h"
|
||||
#include "esp_private/critical_section.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "esp_timer.h"
|
||||
@@ -911,6 +912,14 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
esp_sleep_isolate_digital_gpio();
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if ((sleep_flags & RTC_SLEEP_FLASH_DPD) && (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300))) {
|
||||
/* Switch Flash from standby mode to deep powerdown mode */
|
||||
/* During bootloader phase following wakeup from deepsleep, flash will exit dpd mode */
|
||||
spi_flash_enable_deep_power_down_mode(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB && SOC_DEEP_SLEEP_SUPPORTED
|
||||
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
esp_set_deep_sleep_wake_stub_default_entry();
|
||||
@@ -943,21 +952,28 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
suspend_timers(sleep_flags);
|
||||
/* Cache Suspend 1: will wait cache idle in cache suspend */
|
||||
suspend_cache();
|
||||
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
|
||||
In order to avoid the leakage of the SPI cs pin, hold it here */
|
||||
|
||||
if (!(sleep_flags & RTC_SLEEP_PD_VDDSDIO)) {
|
||||
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if (sleep_flags & RTC_SLEEP_FLASH_DPD) {
|
||||
/* Switch Flash from standby mode to deep powerdown mode */
|
||||
spi_flash_enable_deep_power_down_mode(true);
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
if(!(sleep_flags & RTC_SLEEP_PD_VDDSDIO) && (sleep_flags & PMU_SLEEP_PD_TOP)) {
|
||||
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
|
||||
In order to avoid the leakage of the SPI cs pin, hold it here */
|
||||
if(sleep_flags & PMU_SLEEP_PD_TOP) {
|
||||
#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
|
||||
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
|
||||
gpio_ll_hold_en(&GPIO, MSPI_IOMUX_PIN_NUM_CS0);
|
||||
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
|
||||
gpio_ll_hold_en(&GPIO, MSPI_IOMUX_PIN_NUM_CS0);
|
||||
#endif
|
||||
#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
|
||||
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
|
||||
gpio_ll_hold_en(&GPIO, MSPI_IOMUX_PIN_NUM_CS1);
|
||||
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
|
||||
gpio_ll_hold_en(&GPIO, MSPI_IOMUX_PIN_NUM_CS1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
if (sleep_flags & PMU_SLEEP_PD_TOP) {
|
||||
@@ -1408,6 +1424,13 @@ static SLEEP_FN_ATTR esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint3
|
||||
#endif
|
||||
// Wait for the flash chip to start up
|
||||
esp_rom_delay_us(flash_enable_time_us);
|
||||
} else {
|
||||
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if (sleep_flags & RTC_SLEEP_FLASH_DPD) {
|
||||
//Release Flash out from deep powerdown mode
|
||||
spi_flash_enable_deep_power_down_mode(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
||||
@@ -1592,6 +1615,23 @@ esp_err_t esp_light_sleep_start(void)
|
||||
s_config.sleep_time_adjustment -= flash_enable_time_us;
|
||||
}
|
||||
}
|
||||
} else if (!(sleep_flags & RTC_SLEEP_PD_VDDSDIO)) {
|
||||
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
const uint32_t flash_enable_dpd_us = spi_flash_dpd_get_enter_duration() + spi_flash_dpd_get_exit_duration();
|
||||
if (s_config.sleep_duration > flash_enable_dpd_us) {
|
||||
if (s_config.sleep_time_overhead_out < flash_enable_dpd_us) {
|
||||
s_config.sleep_time_adjustment += flash_enable_dpd_us;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Minimum sleep time is not enough, then reject flash enter deep power-down mode
|
||||
*/
|
||||
sleep_flags &= ~RTC_SLEEP_FLASH_DPD;
|
||||
if (s_config.sleep_time_overhead_out > flash_enable_dpd_us) {
|
||||
s_config.sleep_time_adjustment -= flash_enable_dpd_us;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in);
|
||||
@@ -2757,11 +2797,6 @@ static SLEEP_FN_ATTR uint32_t get_power_down_flags(void)
|
||||
if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option == ESP_PD_OPTION_AUTO) {
|
||||
#ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH
|
||||
s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON;
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) {
|
||||
s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -2850,8 +2885,15 @@ static SLEEP_FN_ATTR uint32_t get_power_down_flags(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if (!(pd_flags & RTC_SLEEP_PD_VDDSDIO)) {
|
||||
// Flash power domain will disable DPD mode.
|
||||
pd_flags |= RTC_SLEEP_FLASH_DPD;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 100)) {
|
||||
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300)) {
|
||||
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
||||
ESP_LOGE(TAG, "ESP32P4 chips lower than v1.0 are not allowed to power down the Flash");
|
||||
}
|
||||
@@ -2934,6 +2976,11 @@ static SLEEP_FN_ATTR uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsle
|
||||
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
sleep_flags &= ~RTC_SLEEP_PD_RTC_PERIPH;
|
||||
}
|
||||
/* The LDO VO1 channel that powers the Flash on esp32p4(<v3) has leakage voltage during deepsleep,
|
||||
which may cause the Flash to enter an abnormal state, so disable Flash power-down feature on esp32p4(<v3). */
|
||||
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300)) {
|
||||
sleep_flags &= ~RTC_SLEEP_PD_VDDSDIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
return sleep_flags;
|
||||
|
||||
Reference in New Issue
Block a user