mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
8dbf23630a
This commit reorganizes SPI flash header files to better reflect their visibility and intended usage: 1. Rename `esp_flash_port/` to `esp_flash_chips/`: - Better reflects that these headers are for chip driver implementations - All chip driver headers moved to `esp_flash_chips/` directory - Added README.md explaining semi-public nature of these headers 2. Move internal headers to `esp_private/`: - `esp_flash_internal.h` -> `esp_private/esp_flash_internal.h` - `memspi_host_driver.h` -> `esp_private/memspi_host_driver.h` 3. Move chip driver related headers to `esp_flash_chips/`: - `esp_private/esp_flash_types.h` -> `esp_flash_chips/esp_flash_types.h` - `spi_flash/spi_flash_defs.h` -> `esp_flash_chips/spi_flash_defs.h` - `spi_flash_override.h` -> `esp_flash_chips/spi_flash_override.h` - All `spi_flash_chip_*.h` headers moved to `esp_flash_chips/` 4. Code improvements: - Remove unused includes (e.g., `spi_flash_override.h` from `cache_utils.c`) - Use public API `esp_flash_get_size()` instead of direct member access - Add `esp_flash_is_quad_mode` to linker.lf for IRAM placement 5. Documentation updates: - Add README.md in `esp_flash_chips/` explaining semi-public headers - Update programming guide with warnings about internal headers - Update both English and Chinese documentation 6. Update all references across the codebase: - Update includes in `spi_flash` component - Update `bootloader_support`, `app_update`, `esp_tee`, `espcoredump` - Update example projects Breaking changes: - Headers moved to new locations require include path updates - `custom_flash_driver` example temporarily disabled until external components are updated
176 lines
6.5 KiB
C
176 lines
6.5 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
//This file implements esp_flash_freq_limit_cb and esp_flash_freq_unlimit_cb callbacks to limit and unlimit CPU
|
|
//frequency when encrypted flash writes are performed.
|
|
|
|
#include "sdkconfig.h"
|
|
|
|
#include "esp_log.h"
|
|
#include "esp_attr.h"
|
|
#include "esp_rom_sys.h"
|
|
#include "soc/chip_revision.h"
|
|
#include "soc/rtc.h"
|
|
#include "hal/efuse_hal.h"
|
|
|
|
#include "esp_private/startup_internal.h"
|
|
#include "esp_private/pm_impl_freq_limit.h"
|
|
#include "esp_private/spi_flash_freq_limit_cbs.h"
|
|
#include "esp_private/esp_clk_utils.h"
|
|
|
|
/**
|
|
* @brief Get the frequency limit for flash encryption lock based on chip revision
|
|
*
|
|
* @return uint32_t Frequency limit (MHz)
|
|
*
|
|
* Logic:
|
|
* - v1.2+: limit to 160MHz
|
|
* - v1.0: limit to 80MHz
|
|
*/
|
|
static uint32_t IRAM_ATTR get_encrypt_lock_freq_limit(void)
|
|
{
|
|
unsigned int chip_revision = efuse_hal_chip_revision();
|
|
if (ESP_CHIP_REV_ABOVE(chip_revision, 102)) {
|
|
return 160;
|
|
} else {
|
|
return 80;
|
|
}
|
|
}
|
|
|
|
#if !CONFIG_PM_ENABLE
|
|
/* Saved original frequency for !PM_ENABLE case (0 means no change was made) */
|
|
static uint32_t s_saved_freq_mhz = 0;
|
|
|
|
// Switch CPU frequency with all necessary synchronization (for !PM_ENABLE case)
|
|
// Similar to do_switch() but without PM-specific state management
|
|
static void IRAM_ATTR esp_pm_impl_switch_cpu_freq(const rtc_cpu_freq_config_t *old_config, const rtc_cpu_freq_config_t *new_config)
|
|
{
|
|
if (new_config->freq_mhz != old_config->freq_mhz) {
|
|
//No need to run on_freq_update for ccount, since that's not supported on C5.
|
|
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
|
|
/* Synchronize MSPI speed mode before CPU frequency switching */
|
|
esp_clk_utils_mspi_speed_mode_sync_before_cpu_freq_switching(new_config->source_freq_mhz, new_config->freq_mhz);
|
|
#endif
|
|
|
|
//Not taking s_time_update_lock since C5 have fixed divider for systimer
|
|
rtc_clk_cpu_freq_set_config_fast(new_config);
|
|
|
|
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
|
|
/* Synchronize MSPI speed mode after CPU frequency switching */
|
|
esp_clk_utils_mspi_speed_mode_sync_after_cpu_freq_switching(new_config->source_freq_mhz, new_config->freq_mhz);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Limit CPU frequency to target frequency (for !PM_ENABLE case only)
|
|
*
|
|
* This function automatically reads the current CPU frequency, saves it,
|
|
* and switches to the target frequency if current frequency is higher.
|
|
* The original frequency can be restored by calling unlimit_cpu_freq().
|
|
*
|
|
* @param target_freq_mhz Target frequency limit in MHz
|
|
* @note limit->unlimit cannot be nested, and this function must not be called concurrently
|
|
* @note This is a private function, only for use by spi_flash component.
|
|
* @note This function is only available when CONFIG_PM_WORKAROUND_FREQ_LIMIT_ENABLED is enabled and CONFIG_PM_ENABLE is not set.
|
|
*/
|
|
static void IRAM_ATTR limit_cpu_freq(uint32_t target_freq_mhz)
|
|
{
|
|
/* PM not enabled, directly switch frequency and save original frequency */
|
|
rtc_cpu_freq_config_t old_config, new_config;
|
|
rtc_clk_cpu_freq_get_config(&old_config);
|
|
|
|
if (old_config.freq_mhz > target_freq_mhz) {
|
|
s_saved_freq_mhz = old_config.freq_mhz;
|
|
if (rtc_clk_cpu_freq_mhz_to_config(target_freq_mhz, &new_config)) {
|
|
/* Use PM implementation function to switch frequency with all necessary synchronization */
|
|
esp_pm_impl_switch_cpu_freq(&old_config, &new_config);
|
|
const unsigned wait_clock_stable_us = 10;
|
|
esp_rom_delay_us(wait_clock_stable_us);
|
|
}
|
|
} else {
|
|
s_saved_freq_mhz = 0; /* No change needed */
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Unlimit CPU frequency, restoring to original frequency (for !PM_ENABLE case only)
|
|
*
|
|
* This function restores the CPU frequency to the value saved by
|
|
* limit_cpu_freq(). If no frequency change was made, this function
|
|
* does nothing.
|
|
*
|
|
* @note limit->unlimit cannot be nested, and this function must not be called concurrently
|
|
* @note This is a private function, only for use by spi_flash component.
|
|
* @note This function is only available when CONFIG_PM_WORKAROUND_FREQ_LIMIT_ENABLED is enabled and CONFIG_PM_ENABLE is not set.
|
|
*/
|
|
static void IRAM_ATTR unlimit_cpu_freq(void)
|
|
{
|
|
/* PM not enabled, restore to original frequency */
|
|
if (s_saved_freq_mhz > 0) {
|
|
rtc_cpu_freq_config_t old_config, new_config;
|
|
rtc_clk_cpu_freq_get_config(&old_config);
|
|
if (rtc_clk_cpu_freq_mhz_to_config(s_saved_freq_mhz, &new_config)) {
|
|
/* Use PM implementation function to switch frequency with all necessary synchronization */
|
|
esp_pm_impl_switch_cpu_freq(&old_config, &new_config);
|
|
const unsigned wait_clock_stable_us = 10;
|
|
esp_rom_delay_us(wait_clock_stable_us);
|
|
}
|
|
}
|
|
/* If s_saved_freq_mhz == 0, no change was made, so no need to restore */
|
|
s_saved_freq_mhz = 0;
|
|
}
|
|
#endif // !CONFIG_PM_ENABLE
|
|
|
|
ESP_SYSTEM_INIT_FN(init_pm_flash_freq_limit, SECONDARY, BIT(0), 202)
|
|
{
|
|
uint32_t limit_freq_mhz = get_encrypt_lock_freq_limit();
|
|
ESP_EARLY_LOGW("spi_flash", "CPU frequency is set to 240MHz. esp_flash_write_encrypted() will automatically limit CPU frequency to %dMHz during execution.", limit_freq_mhz);
|
|
#ifdef CONFIG_PM_ENABLE
|
|
/* Pre-calculate and store forced frequency configuration during initialization.
|
|
* This is done here to avoid runtime calculation overhead in lock/unlock functions.
|
|
*/
|
|
esp_pm_impl_cpu_max_freq_force_init(limit_freq_mhz);
|
|
#endif
|
|
return ESP_OK;
|
|
}
|
|
|
|
void pm_c5_flash_freq_limit_init_include_func(void)
|
|
{
|
|
// Linker hook function, exists to make the linker examine this file
|
|
}
|
|
|
|
void IRAM_ATTR esp_flash_freq_limit_cb(void)
|
|
{
|
|
/* Limit the frequency */
|
|
#ifdef CONFIG_PM_ENABLE
|
|
/* PM enabled, use force mechanism */
|
|
esp_pm_impl_cpu_max_freq_force();
|
|
#else
|
|
/* PM not enabled, use limit mechanism */
|
|
uint32_t limit_freq_mhz = get_encrypt_lock_freq_limit();
|
|
/* Call PM implementation function to limit CPU frequency.
|
|
* This function automatically reads current frequency, saves it, and switches to target frequency.
|
|
*/
|
|
limit_cpu_freq(limit_freq_mhz);
|
|
#endif
|
|
}
|
|
|
|
void IRAM_ATTR esp_flash_freq_unlimit_cb(void)
|
|
{
|
|
/* Restore the frequency */
|
|
#ifdef CONFIG_PM_ENABLE
|
|
/* PM enabled, use unforce mechanism */
|
|
esp_pm_impl_cpu_max_freq_unforce();
|
|
#else
|
|
/* PM not enabled, use unlimit mechanism */
|
|
/* Call PM implementation function to unlimit CPU frequency.
|
|
* This function restores the original frequency saved by limit_cpu_freq().
|
|
*/
|
|
unlimit_cpu_freq();
|
|
#endif
|
|
}
|