mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'feature/psram_halfsleep_mode_support_v5.5' into 'release/v5.5'
feat(psram): allow PSRAM to enter halfsleep mode during light sleep (v5.5) See merge request espressif/esp-idf!49760
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#if CONFIG_SPIRAM
|
||||
#include "hal/ldo_ll.h"
|
||||
#include "hal/mspi_ll.h"
|
||||
#include "esp_private/esp_psram_impl.h"
|
||||
#endif
|
||||
|
||||
#if (CONFIG_ESP_REV_MIN_FULL == 300)
|
||||
@@ -192,7 +193,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
// Get light sleep analog default
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
#if CONFIG_SPIRAM && CONFIG_ESP32P4_SELECTS_REV_LESS_V3
|
||||
// Adjust analog parameters to keep EXT_LDO PSRAM channel volt outputting during light-sleep.
|
||||
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
|
||||
analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
|
||||
@@ -402,11 +403,15 @@ SPM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
|
||||
// to be written back so that regdma can get the correct link.
|
||||
// 3. We cannot use the API provided by ROM to invalidate the cache, since it is a function calling that writes data to the stack during
|
||||
// the return process, which results in dirty cachelines in L1 Cache again.
|
||||
pmu_sleep_cache_sync_items(SMMU_GID_DEFAULT, CACHE_SYNC_WRITEBACK, CACHE_MAP_L1_DCACHE, 0, 0);
|
||||
pmu_sleep_cache_sync_items(SMMU_GID_DEFAULT, CACHE_SYNC_WRITEBACK, CACHE_MAP_L1_DCACHE, 0, 0); // No PSRAM dirty data after this time write back
|
||||
|
||||
if (!dslp) {
|
||||
#if CONFIG_SPIRAM
|
||||
psram_ctrlr_ll_wait_all_transaction_done();
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
esp_psram_impl_enter_halfsleep_mode();
|
||||
#endif
|
||||
mspi_ll_hold_all_psram_pins();
|
||||
#endif
|
||||
s_mpll_freq_mhz_before_sleep = rtc_clk_mpll_get_freq();
|
||||
if (s_mpll_freq_mhz_before_sleep) {
|
||||
@@ -420,10 +425,10 @@ SPM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
|
||||
_psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, false);
|
||||
_psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, false);
|
||||
}
|
||||
mspi_ll_hold_all_psram_pins();
|
||||
#endif
|
||||
rtc_clk_mpll_disable();
|
||||
}
|
||||
pmu_sleep_cache_sync_items(SMMU_GID_DEFAULT, CACHE_SYNC_WRITEBACK, CACHE_MAP_L1_DCACHE, 0, 0); // No L2 MEM dirty data after this time write back
|
||||
} else {
|
||||
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
|
||||
if (efuse_hal_chip_revision() == 300) {
|
||||
@@ -487,19 +492,26 @@ SPM_IRAM_ATTR bool pmu_sleep_finish(bool dslp)
|
||||
// Wait eFuse memory update done.
|
||||
while(efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE);
|
||||
|
||||
if (s_mpll_freq_mhz_before_sleep && !dslp) {
|
||||
rtc_clk_mpll_enable();
|
||||
rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), s_mpll_freq_mhz_before_sleep, true);
|
||||
if (!dslp) {
|
||||
if (s_mpll_freq_mhz_before_sleep) {
|
||||
rtc_clk_mpll_enable();
|
||||
rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), s_mpll_freq_mhz_before_sleep, true);
|
||||
#if CONFIG_SPIRAM
|
||||
if (!s_pmu_sleep_regdma_backup_enabled) {
|
||||
// MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
|
||||
// If it's a PD_TOP sleep, psram MSPI core clock will be enabled by REGDMA
|
||||
_psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
_psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
if (!s_pmu_sleep_regdma_backup_enabled) {
|
||||
// MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
|
||||
// If it's a PD_TOP sleep, psram MSPI core clock will be enabled by REGDMA
|
||||
_psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
_psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
}
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_MPLL);
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_MPLL);
|
||||
#endif
|
||||
}
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_MPLL);
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_MPLL);
|
||||
#if CONFIG_SPIRAM
|
||||
mspi_ll_unhold_all_psram_pins();
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
esp_psram_impl_exit_halfsleep_mode();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
__attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
|
||||
@@ -209,7 +210,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
|
||||
return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_get(void)
|
||||
SPM_IRAM_ATTR uint64_t rtc_time_get(void)
|
||||
{
|
||||
return lp_timer_hal_get_cycle_count();
|
||||
}
|
||||
|
||||
@@ -156,6 +156,10 @@
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
#include "esp_private/esp_psram_impl.h"
|
||||
#endif
|
||||
|
||||
// If light sleep time is less than that, don't power down flash
|
||||
#define FLASH_PD_MIN_SLEEP_TIME_US 2000
|
||||
|
||||
@@ -985,6 +989,13 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
#endif
|
||||
#endif // !SOC_MSPI_HAS_INDEPENT_IOMUX
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED && (CONFIG_SPIRAM_XIP_FROM_PSRAM || !CONFIG_PM_SLP_IRAM_OPT)
|
||||
// Code outside of esp_sleep_start_safe may be linked to FLASH if CONFIG_PM_SLP_IRAM_OPT is false,
|
||||
// Code that accesses flash memory may cause cached PSRAM data to be replaced back into PSRAM before
|
||||
// it has fully resumed. And if CONFIG_SPIRAM_XIP_FROM_PSRAM is enabled, code in Flash will be copied
|
||||
// to PSRAM for execution. We need to wait here until PSRAM exits half-sleep before returning.
|
||||
esp_psram_impl_resume_from_halfsleep_mode(s_config.rtc_clk_cal_period);
|
||||
#endif
|
||||
/* Cache Resume 1: Resume cache for continue running*/
|
||||
resume_cache();
|
||||
@@ -1628,6 +1639,14 @@ esp_err_t esp_light_sleep_start(void)
|
||||
esp_clk_private_unlock();
|
||||
esp_timer_private_unlock();
|
||||
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED && !CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_PM_SLP_IRAM_OPT
|
||||
// If CONFIG_SPIRAM_XIP_FROM_PSRAM is not enabled and CONFIG_PM_SLP_IRAM_OPT is enable,
|
||||
// the sleep-wake process prior to this point does not access the PSRAM, so we can postpone waiting
|
||||
// for the PSRAM to resume until here, in order to reuse the time overhead
|
||||
// of the wake-up process as much as possible.
|
||||
esp_psram_impl_resume_from_halfsleep_mode(s_config.rtc_clk_cal_period);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
|
||||
/* Cache Resume 0: sleep process done, resume cache for continue running */
|
||||
if (!(s_config.wakeup_triggers & ignore_check_wakeup_triggers)) {
|
||||
|
||||
Reference in New Issue
Block a user