diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index 6d5bf4defc1..2beb05fcc1f 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -62,6 +62,7 @@ #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" #include "esp_private/esp_pmu.h" +#include "esp_private/esp_cache_private.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -84,6 +85,22 @@ void IRAM_ATTR esp_rtc_init(void) #endif //SOC_PMU_SUPPORTED } +/* + * Perform the CPU frequency switch with the external memory (PSRAM) cache + * suspended. The frequency switch stalls the HP_ROOT clock and toggles PLL / + * clock gating; when the switch code runs from PSRAM-XIP, a cache-coherency + * transient during the switch can corrupt the external .bss region. Suspending + * the external-memory cache for the duration of the switch keeps the CPU off + * the XIP path, isolating the two. + * Must be IRAM-resident because it runs while the external cache is suspended. + */ +static void IRAM_ATTR esp_clk_cpu_freq_set_config_isolated(const rtc_cpu_freq_config_t *config) +{ + esp_cache_suspend_ext_mem_cache(); + rtc_clk_cpu_freq_set_config(config); + esp_cache_resume_ext_mem_cache(); +} + __attribute__((weak)) void esp_clk_init(void) { assert(rtc_clk_xtal_freq_get() == SOC_XTAL_FREQ_40M); @@ -145,7 +162,7 @@ __attribute__((weak)) void esp_clk_init(void) } if (res) { - rtc_clk_cpu_freq_set_config(&new_config); + esp_clk_cpu_freq_set_config_isolated(&new_config); } // Re calculate the ccount to make time calculation correct.