mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'refactor/spi_flash_private_v5.4' into 'release/v5.4'
fix(spi_flash): fixed overboundary check skipping of erase and write_encrypted (v5.4) See merge request espressif/esp-idf!45664
This commit is contained in:
@@ -7,34 +7,38 @@
|
||||
#include <sys/param.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "esp_private/mspi_timing_tuning.h"
|
||||
#include "esp_private/esp_clk_utils.h"
|
||||
|
||||
// Not directly divide to avoid truncation issue
|
||||
// DIG-498
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#define BELOW_FREQ_THRESHOLD(freq) ((freq) < CONFIG_SPIRAM_SPEED)
|
||||
#endif
|
||||
|
||||
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
|
||||
void esp_clk_utils_mspi_speed_mode_sync_before_cpu_freq_switching(uint32_t target_cpu_src_freq, uint32_t target_cpu_freq)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
(void) target_cpu_freq;
|
||||
/* For ESP32S3, the clock source of MSPI is same as the CPU. When CPU use XTAL as clock source, we need to sync the
|
||||
* MSPI speed mode. */
|
||||
if (target_cpu_src_freq <= clk_ll_xtal_load_freq_mhz()) {
|
||||
mspi_timing_change_speed_mode_cache_safe(true);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
(void) target_cpu_src_freq;
|
||||
/**
|
||||
* Workaround for ESP32P4,
|
||||
* f_cpu >= f_mspi
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4 && CONFIG_SPIRAM
|
||||
/* On chips with AXI bus, currently there is a restriction that AXI frequency (usually equals to a portion of CPU
|
||||
* frequency) needs to be greater than or equal to MSPI PSRAM frequency to avoid writing MSPI FIFO overflow.
|
||||
*/
|
||||
if (((target_cpu_freq) < CONFIG_ESPTOOLPY_FLASHFREQ_VAL)
|
||||
#if CONFIG_SPIRAM
|
||||
|| ((target_cpu_freq) < CONFIG_SPIRAM_SPEED)
|
||||
#endif
|
||||
) {
|
||||
if (BELOW_FREQ_THRESHOLD(target_cpu_freq)) {
|
||||
// Before switching to low speed mode, verify CPU frequency meets the constraint
|
||||
assert(target_cpu_freq >= mspi_timing_get_psram_low_speed_freq_mhz());
|
||||
mspi_timing_change_speed_mode_cache_safe(true);
|
||||
}
|
||||
#else
|
||||
@@ -50,17 +54,11 @@ void esp_clk_utils_mspi_speed_mode_sync_after_cpu_freq_switching(uint32_t target
|
||||
if (target_cpu_src_freq > clk_ll_xtal_load_freq_mhz()) {
|
||||
mspi_timing_change_speed_mode_cache_safe(false);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
(void) target_cpu_src_freq;
|
||||
/**
|
||||
* Workaround for ESP32P4,
|
||||
* f_cpu >= f_mspi
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4 && CONFIG_SPIRAM
|
||||
/* On chips with AXI bus, currently there is a restriction that AXI frequency (usually equals to a portion of CPU
|
||||
* frequency) needs to be greater than or equal to MSPI PSRAM frequency to avoid writing MSPI FIFO overflow.
|
||||
*/
|
||||
if (((target_cpu_freq) >= CONFIG_ESPTOOLPY_FLASHFREQ_VAL)
|
||||
#if CONFIG_SPIRAM
|
||||
&& ((target_cpu_freq) >= CONFIG_SPIRAM_SPEED)
|
||||
#endif
|
||||
) {
|
||||
if (!BELOW_FREQ_THRESHOLD(target_cpu_freq)) {
|
||||
mspi_timing_change_speed_mode_cache_safe(false);
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -24,6 +24,12 @@ extern "C" {
|
||||
*/
|
||||
void mspi_timing_enter_low_speed_mode(bool control_spi1);
|
||||
|
||||
/**
|
||||
* @brief Get PSRAM frequency in low speed mode (MHz)
|
||||
* @return PSRAM frequency in MHz when in low speed mode
|
||||
*/
|
||||
uint32_t mspi_timing_get_psram_low_speed_freq_mhz(void);
|
||||
|
||||
/**
|
||||
* @brief Make MSPI work under the frequency as users set, may add certain delays to MSPI RX direction to meet timing requirements.
|
||||
* @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1
|
||||
@@ -54,7 +60,6 @@ void mspi_timing_psram_tuning(void);
|
||||
*/
|
||||
void mspi_timing_set_pin_drive_strength(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -474,6 +474,11 @@ void mspi_timing_psram_tuning(void)
|
||||
/*------------------------------------------------------------------------------
|
||||
* APIs to make SPI0 (and SPI1) FLASH work for high/low freq
|
||||
*----------------------------------------------------------------------------*/
|
||||
uint32_t mspi_timing_get_psram_low_speed_freq_mhz(void)
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
void mspi_timing_enter_low_speed_mode(bool control_spi1)
|
||||
{
|
||||
#if SOC_MEMSPI_FLASH_CLK_SRC_IS_INDEPENDENT
|
||||
@@ -497,14 +502,14 @@ void mspi_timing_enter_low_speed_mode(bool control_spi1)
|
||||
* Should be extended to other no-timing-tuning chips if needed. e.g.:
|
||||
* we still need to turn down Flash / PSRAM clock speed at a certain period of time
|
||||
*/
|
||||
mspi_timing_config_set_flash_clock(20, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1);
|
||||
mspi_timing_config_set_psram_clock(20, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1);
|
||||
#endif //#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
|
||||
|
||||
uint32_t low_speed_freq_mhz = mspi_timing_get_psram_low_speed_freq_mhz();
|
||||
mspi_timing_config_set_flash_clock(low_speed_freq_mhz, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1);
|
||||
mspi_timing_config_set_psram_clock(low_speed_freq_mhz, MSPI_TIMING_SPEED_MODE_LOW_PERF, control_spi1);
|
||||
#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
mspi_timing_flash_config_clear_tuning_regs(control_spi1);
|
||||
mspi_timing_psram_config_clear_tuning_regs(control_spi1);
|
||||
#endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
|
||||
#endif //#if SOC_SPI_MEM_SUPPORT_TIMING_TUNING
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,15 +148,6 @@ static const char io_mode_str[][IO_STR_LEN] = {
|
||||
|
||||
_Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_io_mode_t defined in spi_flash_types.h");
|
||||
|
||||
esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
|
||||
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL || ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
static esp_err_t spiflash_start_default(esp_flash_t *chip);
|
||||
static esp_err_t spiflash_end_default(esp_flash_t *chip, esp_err_t err);
|
||||
static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip);
|
||||
static esp_err_t flash_end_flush_cache(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length);
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL || ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
|
||||
typedef struct {
|
||||
esp_err_t (*start)(esp_flash_t *chip);
|
||||
esp_err_t (*end)(esp_flash_t *chip, esp_err_t err);
|
||||
@@ -164,7 +155,22 @@ typedef struct {
|
||||
esp_err_t (*flash_end_flush_cache)(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length);
|
||||
} rom_spiflash_api_func_t;
|
||||
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL || ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id);
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
extern rom_spiflash_api_func_t *esp_flash_api_funcs;
|
||||
#define rom_spiflash_api_funcs esp_flash_api_funcs
|
||||
#else
|
||||
#define rom_spiflash_api_funcs esp_flash_api_funcs_patched_ptr
|
||||
#endif
|
||||
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
// API funcs case 1: Not using ROM - define our own pointer and all functions
|
||||
static esp_err_t spiflash_start_default(esp_flash_t *chip);
|
||||
static esp_err_t spiflash_end_default(esp_flash_t *chip, esp_err_t err);
|
||||
static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip);
|
||||
static esp_err_t flash_end_flush_cache(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length);
|
||||
|
||||
// These functions can be placed in the ROM. For now we use the code in IDF.
|
||||
DRAM_ATTR static rom_spiflash_api_func_t default_spiflash_rom_api = {
|
||||
.start = spiflash_start_default,
|
||||
@@ -174,17 +180,41 @@ DRAM_ATTR static rom_spiflash_api_func_t default_spiflash_rom_api = {
|
||||
};
|
||||
|
||||
DRAM_ATTR rom_spiflash_api_func_t *rom_spiflash_api_funcs = &default_spiflash_rom_api;
|
||||
#else
|
||||
extern rom_spiflash_api_func_t *esp_flash_api_funcs;
|
||||
#define rom_spiflash_api_funcs esp_flash_api_funcs
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL || ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
|
||||
#else // CONFIG_SPI_FLASH_ROM_IMPL
|
||||
// Using ROM implementation
|
||||
|
||||
# if ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
// API funcs case 2: Using ROM APIs but patch flash_end_flush_cache function
|
||||
// When ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV, the api_funcs provided by ROM does not have flash_end_flush_cache member.
|
||||
static esp_err_t flash_end_flush_cache(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length);
|
||||
DRAM_ATTR static rom_spiflash_api_func_t esp_flash_api_funcs_patched;
|
||||
|
||||
// Copy ROM structure to RAM and patch flash_end_flush_cache function
|
||||
void esp_flash_rom_api_funcs_init(void)
|
||||
{
|
||||
rom_spiflash_api_func_t *rom_ptr = esp_flash_api_funcs;
|
||||
memcpy(&esp_flash_api_funcs_patched, rom_ptr, sizeof(rom_spiflash_api_func_t));
|
||||
esp_flash_api_funcs_patched.flash_end_flush_cache = flash_end_flush_cache;
|
||||
esp_flash_api_funcs = &esp_flash_api_funcs_patched;
|
||||
}
|
||||
|
||||
# else
|
||||
// API funcs case 3: Using All ROM APIs directly
|
||||
void esp_flash_rom_api_funcs_init(void)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
# endif // ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
/* Static function to notify OS of a new SPI flash operation.
|
||||
|
||||
If returns an error result, caller must abort. If returns ESP_OK, caller must
|
||||
call rom_spiflash_api_funcs->end() before returning.
|
||||
*/
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL || ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
static esp_err_t IRAM_ATTR spiflash_start_default(esp_flash_t *chip)
|
||||
{
|
||||
if (chip->os_func != NULL && chip->os_func->start != NULL) {
|
||||
@@ -224,7 +254,13 @@ static IRAM_ATTR esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip)
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
#if !CONFIG_SPI_FLASH_ROM_IMPL || ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV
|
||||
/* ROM and patch information
|
||||
* Latest: No change
|
||||
* V1 (!ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV): Added to ROM
|
||||
*/
|
||||
static IRAM_ATTR esp_err_t flash_end_flush_cache(esp_flash_t* chip, esp_err_t err, bool bus_acquired, uint32_t address, uint32_t length)
|
||||
{
|
||||
if (!bus_acquired) {
|
||||
@@ -731,7 +767,7 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
|
||||
if (len == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
if (len > chip->size - start) {
|
||||
if (start > chip->size || len > chip->size - start) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return rom_esp_flash_erase_region(chip, start, len);
|
||||
@@ -744,7 +780,7 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
if (len > chip->size - start) {
|
||||
if (start > chip->size || len > chip->size - start) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return rom_esp_flash_erase_region(chip, start, len);
|
||||
@@ -1501,7 +1537,7 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
if (length > chip->size - address) {
|
||||
if (buffer == NULL || address > chip->size || length > chip->size - address) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return rom_esp_flash_write_encrypted(chip, address, buffer, length);
|
||||
|
||||
@@ -396,6 +396,10 @@ esp_err_t esp_flash_init_default_chip(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
esp_flash_rom_api_funcs_init();
|
||||
#endif // CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
// ROM TODO: account for non-standard default pins in efuse
|
||||
// ROM TODO: to account for chips which are slow to power on, maybe keep probing in a loop here
|
||||
err = esp_flash_init_main(&default_chip);
|
||||
|
||||
@@ -117,6 +117,16 @@ esp_err_t esp_flash_app_disable_os_functions(esp_flash_t* chip);
|
||||
*/
|
||||
esp_err_t esp_flash_set_dangerous_write_protection(esp_flash_t *chip, const bool protect);
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
/**
|
||||
* @brief Initialize ROM API functions structure
|
||||
*
|
||||
* This function initializes the ROM API functions structure, either by pointing
|
||||
* to a custom structure or by patching the ROM structure in RAM.
|
||||
*/
|
||||
void esp_flash_rom_api_funcs_init(void);
|
||||
#endif // CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user