mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(spi_flash): implement dynamic CPU frequency switching workaround for encrypted writes
This commit implements a workaround that allows ESP32-C5 to run at 240MHz CPU frequency normally, while automatically reducing CPU frequency during encrypted flash writes to ensure correct operation. The frequency limit is chip revision dependent: - v1.2 and above: limited to 160MHz during encrypted writes - v1.0 and below: limited to 80MHz during encrypted writes Key implementation details: - Frequency limiting is triggered automatically when esp_flash_write_encrypted() is called - Uses start() flags (ESP_FLASH_START_FLAG_LIMIT_CPU_FREQ) to integrate with OS layer - Works with both PM enabled and disabled configurations - Frequency is automatically restored after encrypted write completes - For ESP32-C5 with 120MHz flash, Flash clock and timing registers are adjusted when CPU frequency is reduced to 80MHz - SPI1 timing registers are configured during frequency switching since encrypted writes use SPI1 and must work correctly at reduced CPU frequencies Code improvements: - Use SOC_MSPI_FREQ_AXI_CONSTRAINED capability macro instead of hardcoded chip checks - Control workaround via Kconfig (CONFIG_PM_WORKAROUND_FREQ_LIMIT_ENABLED) instead of hardcoded macros - Add comprehensive test cases covering various PM configurations and edge cases This workaround enables ESP32-C5 applications to benefit from 240MHz CPU performance while maintaining reliable encrypted flash write functionality.
This commit is contained in:
@@ -20,9 +20,12 @@
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
#include "esp_private/cache_utils.h"
|
||||
|
||||
#include "esp_private/spi_share_hw_ctrl.h"
|
||||
|
||||
// For C5 encrypted write workaround
|
||||
// Functions are only available when CONFIG_SPI_FLASH_FREQ_LIMIT_C5_240MHZ is true
|
||||
#include "esp_private/spi_flash_freq_limit_cbs.h"
|
||||
|
||||
#define SPI_FLASH_CACHE_NO_DISABLE (CONFIG_SPI_FLASH_AUTO_SUSPEND || (CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA) || CONFIG_APP_BUILD_TYPE_RAM)
|
||||
static const char TAG[] = "spi_flash";
|
||||
|
||||
@@ -53,6 +56,7 @@ typedef struct {
|
||||
bool no_protect; //to decide whether to check protected region (for the main chip) or not.
|
||||
uint32_t acquired_since_us; // Time since last explicit yield()
|
||||
uint32_t released_since_us; // Time since last end() (implicit yield)
|
||||
uint32_t start_flags; // Flags passed to start() function, used to determine if freq_limit was called
|
||||
} app_func_arg_t;
|
||||
|
||||
static inline void on_spi_released(app_func_arg_t* ctx);
|
||||
@@ -90,21 +94,27 @@ static IRAM_ATTR esp_err_t release_spi_bus_lock(void *arg)
|
||||
return spi_bus_lock_acquire_end(((app_func_arg_t *)arg)->dev_lock);
|
||||
}
|
||||
|
||||
static esp_err_t spi23_start(void *arg){
|
||||
static esp_err_t spi23_start(void *arg, uint32_t flags)
|
||||
{
|
||||
(void)flags;
|
||||
esp_err_t ret = acquire_spi_bus_lock(arg);
|
||||
on_spi_acquired((app_func_arg_t*)arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t spi23_end(void *arg){
|
||||
static esp_err_t spi23_end(void *arg)
|
||||
{
|
||||
esp_err_t ret = release_spi_bus_lock(arg);
|
||||
on_spi_released((app_func_arg_t*)arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static IRAM_ATTR esp_err_t spi1_start(void *arg)
|
||||
static IRAM_ATTR esp_err_t spi1_start(void *arg, uint32_t flags)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
app_func_arg_t* ctx = (app_func_arg_t*)arg;
|
||||
ctx->start_flags = flags;
|
||||
|
||||
/**
|
||||
* There are three ways for ESP Flash API lock:
|
||||
* 1. spi bus lock, this is used when SPI1 is shared with GPSPI Master Driver
|
||||
@@ -136,13 +146,28 @@ static IRAM_ATTR esp_err_t spi1_start(void *arg)
|
||||
}
|
||||
#endif // CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
|
||||
on_spi_acquired((app_func_arg_t*)arg);
|
||||
#if CONFIG_SPI_FLASH_FREQ_LIMIT_C5_240MHZ
|
||||
if (flags & ESP_FLASH_START_FLAG_LIMIT_CPU_FREQ) {
|
||||
esp_flash_freq_limit_cb();
|
||||
}
|
||||
#endif
|
||||
|
||||
on_spi_acquired(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static IRAM_ATTR esp_err_t spi1_end(void *arg)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
app_func_arg_t* ctx = (app_func_arg_t*)arg;
|
||||
|
||||
// Call freq_limit_unlock if needed, before releasing the lock
|
||||
#if CONFIG_SPI_FLASH_FREQ_LIMIT_C5_240MHZ
|
||||
uint32_t flags = ctx->start_flags;
|
||||
if (flags & ESP_FLASH_START_FLAG_LIMIT_CPU_FREQ) {
|
||||
esp_flash_freq_unlimit_cb();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* There are three ways for ESP Flash API lock, see `spi1_start`
|
||||
@@ -166,7 +191,7 @@ static IRAM_ATTR esp_err_t spi1_end(void *arg)
|
||||
}
|
||||
#endif // CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
|
||||
on_spi_released((app_func_arg_t*)arg);
|
||||
on_spi_released(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user