Merge branch 'fix/s3_xip_opt_os_startup_v5.2' into 'release/v5.2'

fix(mspi): fixed possible boot failure in some builds when psram is enabled (v5.2)

See merge request espressif/esp-idf!48592
This commit is contained in:
Jiang Jiang Jian
2026-08-06 11:16:36 +08:00
5 changed files with 63 additions and 12 deletions
@@ -30,6 +30,21 @@ void mspi_timing_enter_low_speed_mode(bool control_spi1);
*/
void mspi_timing_enter_high_speed_mode(bool control_spi1);
/**
* @brief Switch MSPI to low speed while suspending external memory cache to avoid in-flight cache line fills across the
* clock change.
*
* @note Early init only. Not safe for general runtime use: does not coordinate with other cores or freeze cache.
*/
void mspi_timing_enter_low_speed_early(void);
/**
* @brief Switch MSPI to high speed while suspending external memory cache.
*
* @note Same usage constraints as @ref mspi_timing_enter_low_speed_early.
*/
void mspi_timing_enter_high_speed_early(void);
/**
* @brief Switch MSPI into low speed mode / high speed mode.
* @note This API is cache safe, it will freeze both D$ and I$ and restore them after MSPI is switched
+26 -6
View File
@@ -16,6 +16,7 @@
#include "hal/spi_flash_hal.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "esp_private/cache_utils.h"
#include "esp_private/mspi_timing_tuning.h"
#include "mspi_timing_config.h"
#include "mspi_timing_by_mspi_delay.h"
@@ -320,9 +321,9 @@ void mspi_timing_flash_tuning(void)
{
/**
* set MSPI related regs to 20mhz configuration, to get reference data from FLASH
* see detailed comments in this function (`mspi_timing_enter_low_speed_mode`)
* see detailed comments in this function (`mspi_timing_enter_low_speed_early`)
*/
mspi_timing_enter_low_speed_mode(true);
mspi_timing_enter_low_speed_early();
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
mspi_tuning_cfg_drv_t drv = {
@@ -349,7 +350,7 @@ void mspi_timing_flash_tuning(void)
s_do_tuning(reference_data, &timing_configs, true);
mspi_timing_enter_high_speed_mode(true);
mspi_timing_enter_high_speed_early();
}
#else
void mspi_timing_flash_tuning(void)
@@ -367,9 +368,9 @@ void mspi_timing_psram_tuning(void)
{
/**
* set MSPI related regs to 20mhz configuration, to write reference data to PSRAM
* see detailed comments in this function (`mspi_timing_enter_low_speed_mode`)
* see detailed comments in this function (`mspi_timing_enter_low_speed_early`)
*/
mspi_timing_enter_low_speed_mode(true);
mspi_timing_enter_low_speed_early();
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
// write data into psram, used to do timing tuning test.
@@ -399,7 +400,7 @@ void mspi_timing_psram_tuning(void)
//Get required config, and set them to PSRAM related registers
s_do_tuning(reference_data, &timing_configs, false);
mspi_timing_enter_high_speed_mode(true);
mspi_timing_enter_high_speed_early();
}
#else
@@ -499,6 +500,25 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down)
#endif //#if SOC_CACHE_FREEZE_SUPPORTED
}
/*------------------------------------------------------------------------------
* Early-init MSPI speed switch (see mspi_timing_tuning.h)
*----------------------------------------------------------------------------*/
void mspi_timing_enter_low_speed_early(void)
{
uint32_t cache_state = 0;
spi_flash_disable_cache(0, &cache_state);
mspi_timing_enter_low_speed_mode(true);
spi_flash_restore_cache(0, cache_state);
}
void mspi_timing_enter_high_speed_early(void)
{
uint32_t cache_state = 0;
spi_flash_disable_cache(0, &cache_state);
mspi_timing_enter_high_speed_mode(true);
spi_flash_restore_cache(0, cache_state);
}
/*------------------------------------------------------------------------------
* APIs to inform SPI1 Flash driver of necessary timing configurations
*----------------------------------------------------------------------------*/
@@ -341,8 +341,8 @@ esp_err_t esp_psram_impl_enable(void)
s_set_psram_cs_timing();
s_configure_psram_ecc();
//enter MSPI slow mode to init PSRAM device registers
mspi_timing_enter_low_speed_mode(true);
//enter MSPI slow mode to init PSRAM device registers (early init: see mspi_timing_enter_low_speed_early)
mspi_timing_enter_low_speed_early();
//set to variable dummy mode
SET_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY);
@@ -377,7 +377,7 @@ esp_err_t esp_psram_impl_enable(void)
//Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly
mspi_timing_psram_tuning();
//Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly
mspi_timing_enter_high_speed_mode(true);
mspi_timing_enter_high_speed_early();
/**
* Tuning may change SPI1 regs, whereas legacy spi_flash APIs rely on these regs.
@@ -327,8 +327,8 @@ esp_err_t esp_psram_impl_enable(void) //psram init
psram_gpio_config();
psram_set_cs_timing();
//enter MSPI slow mode to init PSRAM device registers
mspi_timing_enter_low_speed_mode(true);
//enter MSPI slow mode to init PSRAM device registers (early init: see mspi_timing_enter_low_speed_early)
mspi_timing_enter_low_speed_early();
//We use SPI1 to init PSRAM
psram_disable_qio_mode(SPI1_NUM);
@@ -369,7 +369,7 @@ esp_err_t esp_psram_impl_enable(void) //psram init
//Configure SPI0 PSRAM related SPI Phases
config_psram_spi_phases();
//Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly
mspi_timing_enter_high_speed_mode(true);
mspi_timing_enter_high_speed_early();
return ESP_OK;
}
@@ -81,6 +81,22 @@ bool spi_flash_cache_enabled(void);
*/
void spi_flash_enable_cache(uint32_t cpuid);
/**
* @brief Suspend the Cache access to external memory, will disable branch predictor if supported.
*
* @param cpuid the core number to enable the cache for, meaning less on shared cache.
* @param saved_state Cache status hold by hal (Used only on ROM impl. in idf, this param unused)
*/
void spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state);
/**
* @brief Resume the Cache access to external memory, will enable branch predictor if supported.
*
* @param cpuid the core number to enable the cache for, meaning less on shared cache.
* @param saved_state Cache status hold by hal (Used only on ROM impl. in idf, this param unused)
*/
void spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
#ifdef __cplusplus
}
#endif