Skip to content

Commit

Permalink
Merge branch 'bugfix/fix_esp32p4_sleep_psram_access_failure_v5.3' int…
Browse files Browse the repository at this point in the history
…o 'release/v5.3'

fix(esp_hw_support): support esp32p4 psram sleep retention (v5.3)

See merge request espressif/esp-idf!32598
  • Loading branch information
jack0c committed Sep 5, 2024
2 parents 24c2c80 + 21d430c commit d3b1b54
Show file tree
Hide file tree
Showing 22 changed files with 408 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ static void test_gptimer_sleep_retention(bool back_up_before_sleep)
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
}
#endif
esp_sleep_set_sleep_context(NULL);

uint64_t count_value_after_sleep = 0;
TEST_ESP_OK(gptimer_get_raw_count(timer, &count_value_after_sleep));
Expand Down
3 changes: 2 additions & 1 deletion components/esp_hw_support/port/esp32p4/mspi_timing_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe
ESP_EARLY_LOGD(TAG, "psram_freq_mhz: %" PRIu32 " mhz, bus clock div: %" PRIu32, psram_freq_mhz, freqdiv);
PERIPH_RCC_ATOMIC() {
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
psram_ctrlr_ll_set_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_set_core_clock_div(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, freqdiv);
}
Expand Down
40 changes: 31 additions & 9 deletions components/esp_hw_support/port/esp32p4/pmu_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "hal/lp_aon_hal.h"
#include "soc/lp_system_reg.h"
#include "hal/pmu_hal.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/lp_sys_ll.h"
#include "esp_private/esp_pmu.h"
#include "pmu_param.h"
Expand Down Expand Up @@ -168,8 +169,8 @@ 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(pd_flags);
#if CONFIG_SPIRAM
analog_default.hp_sys.analog.pd_cur = 1;
analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = 1;
analog_default.hp_sys.analog.pd_cur = 0;
analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = 0;
#endif

#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
Expand Down Expand Up @@ -290,11 +291,6 @@ void pmu_sleep_shutdown_ldo(void) {
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD);
}

FORCE_INLINE_ATTR void sleep_writeback_l1_dcache(void) {
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);
while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE));
}

static TCM_DRAM_ATTR uint32_t s_mpll_freq_mhz_before_sleep = 0;

TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
Expand All @@ -309,12 +305,28 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);

// For the sleep where powered down the TOP domain, the L1 cache data memory will be lost and needs to be written back here.
// For the sleep without power down the TOP domain, regdma retention may still be enabled, and dirty data in the L1 cache needs
// to be written back so that regdma can get the correct link. So we always need to write back to L1 DCache here.
// !!! Need to manually check that data in L2 memory will not be modified from now on. !!!
sleep_writeback_l1_dcache();
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);

// !!! Need to manually check that data in PSRAM will not be accessed from now on. !!!
#if CONFIG_SPIRAM
psram_ctrlr_ll_wait_all_transaction_done();
#endif
s_mpll_freq_mhz_before_sleep = rtc_clk_mpll_get_freq();
if (s_mpll_freq_mhz_before_sleep) {
#if CONFIG_SPIRAM
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_XTAL);
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_XTAL);
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 disabled by REGDMA
// !!! Need to manually check that data in PSRAM will not be accessed from now on. !!!
_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);
}
#endif
rtc_clk_mpll_disable();
}

Expand Down Expand Up @@ -350,6 +362,16 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(bool 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);
#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);
}
_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
}

// Wait eFuse memory update done.
Expand Down
12 changes: 9 additions & 3 deletions components/esp_hw_support/sleep_gpio.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -63,11 +63,17 @@ void esp_sleep_config_gpio_isolate(void)
}

#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS1), GPIO_PULLUP_ONLY);
int32_t mspi_io_cs1_io_num = esp_mspi_get_io(ESP_MSPI_IO_CS1);
if (GPIO_IS_VALID_GPIO(mspi_io_cs1_io_num)) {
gpio_sleep_set_pull_mode(mspi_io_cs1_io_num, GPIO_PULLUP_ONLY);
}
#endif // CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM

#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS0), GPIO_PULLUP_ONLY);
int32_t mspi_io_cs0_io_num = esp_mspi_get_io(ESP_MSPI_IO_CS0);
if (GPIO_IS_VALID_GPIO(mspi_io_cs0_io_num)) {
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS0), GPIO_PULLUP_ONLY);
}
#endif // CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND

#if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
Expand Down
24 changes: 19 additions & 5 deletions components/esp_hw_support/sleep_system_peripheral.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,24 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_iomux_retention_init(v
return ESP_OK;
}

static __attribute__((unused)) esp_err_t sleep_sys_periph_spimem_retention_init(void *arg)
static __attribute__((unused)) esp_err_t sleep_sys_periph_flash_spimem_retention_init(void *arg)
{
esp_err_t err = sleep_retention_entries_create(spimem_regs_retention, ARRAY_SIZE(spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "SPI mem");
ESP_LOGD(TAG, "SPI Mem sleep retention initialization");
esp_err_t err = sleep_retention_entries_create(flash_spimem_regs_retention, ARRAY_SIZE(flash_spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "Flash SPI mem");
ESP_LOGD(TAG, "Flash SPI Mem sleep retention initialization");
return ESP_OK;
}

#if CONFIG_SPIRAM
static __attribute__((unused)) esp_err_t sleep_sys_periph_psram_spimem_retention_init(void *arg)
{
esp_err_t err = sleep_retention_entries_create(psram_spimem_regs_retention, ARRAY_SIZE(psram_spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "PSRAM SPI mem");
ESP_LOGD(TAG, "PSRAM SPI Mem sleep retention initialization");
return ESP_OK;
}
#endif

static __attribute__((unused)) esp_err_t sleep_sys_periph_systimer_retention_init(void *arg)
{
esp_err_t err = sleep_retention_entries_create(systimer_regs_retention, ARRAY_SIZE(systimer_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
Expand Down Expand Up @@ -130,8 +140,12 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a
#endif
err = sleep_sys_periph_iomux_retention_init(arg);
if(err) goto error;
err = sleep_sys_periph_spimem_retention_init(arg);
err = sleep_sys_periph_flash_spimem_retention_init(arg);
if(err) goto error;
#if CONFIG_SPIRAM
err = sleep_sys_periph_psram_spimem_retention_init(arg);
if(err) goto error;
#endif
err = sleep_sys_periph_systimer_retention_init(arg);
if(err) goto error;
#if SOC_PAU_IN_TOP_DOMAIN
Expand Down
1 change: 1 addition & 0 deletions components/esp_system/test_apps/.build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ components/esp_system/test_apps/console:
components/esp_system/test_apps/esp_system_unity_tests:
disable:
- if: IDF_TARGET == "esp32c5" or (CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1)
- if: IDF_TARGET == "esp32c5" or (CONFIG_NAME == "psram_with_pd_top" and (SOC_SPIRAM_SUPPORTED != 1 or SOC_PM_SUPPORT_TOP_PD != 1))

components/esp_system/test_apps/linux_apis:
enable:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ set(SRC "test_app_main.c"
"test_ipc.c"
"test_reset_reason.c"
"test_shared_stack_printf.c"
"test_sleep.c"
"test_stack_check.c"
"test_system_time.c"
"test_task_wdt.c")

if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED OR CONFIG_SOC_DEEP_SLEEP_SUPPORTED)
list(APPEND SRC "test_sleep.c")
endif()

if(CONFIG_ESP_IPC_ISR_ENABLE)
list(APPEND SRC "test_ipc_isr.c")
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
Expand Down
Loading

0 comments on commit d3b1b54

Please # to comment.