refactor(spi_flash): move os layer to esp_mspi and chip configs to spi_flash

Also fixes the implicit dependency on esp_partition.
This commit is contained in:
armando
2026-06-02 11:12:03 +08:00
committed by Armando (Dou Yiwen)
parent c565262ded
commit 6e3abd12a1
197 changed files with 1227 additions and 1139 deletions

View File

@@ -114,6 +114,7 @@
/components/esp_libc/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
/components/esp_mm/ @esp-idf-codeowners/peripherals
/components/esp_mspi/ @esp-idf-codeowners/peripherals
/components/esp_netif/ @esp-idf-codeowners/network
/components/esp_netif_stack/ @esp-idf-codeowners/network
/components/esp_partition/ @esp-idf-codeowners/storage

View File

@@ -10,7 +10,7 @@ The core components are organized into two groups.
The first group (referred to as `G0`) includes `hal`, `arch` (where `arch` is either `riscv` or `xtensa` depending on the chip), `esp_rom`, `esp_common`, and `soc`. This group contains information about and provides low-level access to the underlying hardware. In the case of `esp_common`, it contains hardware-agnostic code and utilities. These components may have dependencies on each other within the group, but outside dependencies should be minimized. The reason for this approach is that these components are fundamental, and many other components may require them. Ideally, the dependency relationship only goes one way, making it easier for this group to be usable in other projects.
The second group (referred to as `G1`) operates at a higher level than the first group. `G1` includes the components `esp_hw_support`, `esp_system`, `esp_libc`, `spi_flash`, `freertos`, `log`, and `heap`. Like the first group, circular dependencies within this group are allowed, and these components can have dependencies on the first group. G1 components represent essential software mechanisms for building other components.
The second group (referred to as `G1`) operates at a higher level than the first group. `G1` includes the components `esp_hw_support`, `esp_mspi`, `esp_system`, `esp_libc`, `freertos`, `log`, and `heap`. Like the first group, circular dependencies within this group are allowed, and these components can have dependencies on the first group. G1 components represent essential software mechanisms for building other components.
## Descriptions
@@ -69,10 +69,6 @@ Example:
### `G1` Components
#### `spi_flash`
SPI flash device access implementation.
#### `freertos`
FreeRTOS port to targets supported by ESP-IDF.
@@ -131,6 +127,14 @@ merely as facilitator to hardware access. Currently, this encompasses the follow
- CPU utilities
- MAC settings
#### `esp_mspi`
Contains the CPU XiP related MSPI (Memory SPI) implementation for the external SPI flash and PSRAM controller. Currently, this encompasses the following, but not limited to:
- MSPI timing tuning
- MSPI interrupt handling
- XiP on OPI/Octal flash support
### `esp_hw_support` vs `esp_system`
This section details list some implementations and the reason for placing it in either `esp_hw_support` or `esp_system`.

View File

@@ -100,8 +100,8 @@ else()
set(priv_requires spi_flash efuse heap esp_bootloader_format esp_app_format
esptool_py)
# `esp_hal_ana_conv` is required by bootloader_random_esp32xx.c
list(APPEND priv_requires esp_hal_wdt esp_hal_gpio esp_hal_uart esp_hal_ana_conv esp_hal_rtc_timer
esp_hal_clock esp_hal_security esp_hal_debug_assist)
list(APPEND priv_requires esp_mspi esp_hal_wdt esp_hal_gpio esp_hal_uart esp_hal_ana_conv
esp_hal_rtc_timer esp_hal_clock esp_hal_security esp_hal_debug_assist)
endif()
# src/flash_encrypt.c includes esp_security/esp_key_mgr.h on

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,8 +7,7 @@
#include <stdint.h>
#include <esp_err.h>
#include "spi_flash_mmap.h" /* including in bootloader for error values */
#include "esp_private/spi_flash_os.h"
#include "esp_rom_spiflash.h"
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "bootloader_flash_override.h"
@@ -59,6 +58,7 @@ esp_err_t bootloader_flash_reset_chip(void);
*
* @return True if flash is in octal mode, false else
*/
__attribute__((deprecated("in favor of spi_flash_is_octal_mode_enabled")))
bool bootloader_flash_is_octal_mode_enabled(void);
/**

View File

@@ -1,46 +1,22 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __BOOTLOADER_FLASH_H
#define __BOOTLOADER_FLASH_H
#pragma once
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <esp_err.h>
#include <spi_flash_mmap.h> /* including in bootloader for error values */
#include "sdkconfig.h"
#include "bootloader_flash.h"
#include "soc/ext_mem_defs.h"
#include "bootloader_flash_override.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FLASH_SECTOR_SIZE 0x1000
#define FLASH_BLOCK_SIZE 0x10000
#define MMAP_ALIGNED_MASK (SPI_FLASH_MMU_PAGE_SIZE - 1)
#define MMU_FLASH_MASK (~(SPI_FLASH_MMU_PAGE_SIZE - 1))
#define MMU_FLASH_MASK_FROM_VAL(PAGE_SZ) (~((PAGE_SZ) - 1))
#define MMU_DROM_END_ENTRY_VADDR_FROM_VAL(PAGE_SZ) (SOC_DRAM_FLASH_ADDRESS_HIGH - (PAGE_SZ))
/**
* MMU mapping must always be in the unit of a SPI_FLASH_MMU_PAGE_SIZE
* This macro is a helper for you to get needed page nums to be mapped. e.g.:
* Let's say SPI_FLASH_MMU_PAGE_SIZE is 64KB.
* - v_start = 0x4200_0004
* - size = 4 * 64KB
*
* You should map from 0x4200_0000, then map 5 pages.
/*
* SPI commands
* These are deprecated, use the ones in spi_flash_defs.h instead.
*/
#define GET_REQUIRED_MMU_PAGES(size, v_start) ((size + (v_start - (v_start & MMU_FLASH_MASK)) + SPI_FLASH_MMU_PAGE_SIZE - 1) / SPI_FLASH_MMU_PAGE_SIZE)
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the bootloader_execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
@@ -62,146 +38,3 @@ extern "C" {
#define CMD_FASTRD_DUAL_4B 0x3C
#define CMD_FASTRD_4B 0x0C
#define CMD_SLOWRD_4B 0x13
/* Provide a Flash API for bootloader_support code,
that can be used from bootloader or app code.
This header is available to source code in the bootloader &
bootloader_support components only.
*/
/**
* @brief Get number of free pages
*
* @return Number of free pages
*/
uint32_t bootloader_mmap_get_free_pages(void);
/**
* @brief Map a region of flash to data memory
*
* @important In bootloader code, only one region can be bootloader_mmaped at once. The previous region must be bootloader_munmapped before another region is mapped.
*
* @important In app code, these functions are not thread safe.
*
* Call bootloader_munmap once for each successful call to bootloader_mmap.
*
* In esp-idf app, this function maps directly to spi_flash_mmap with the @ref
* spi_flash_mmap_flag_t::SPI_FLASH_MMAP_FLAG_BLOCKS_WRITE flag set. When XIP on PSRAM (`CONFIG_SPIRAM_XIP_FROM_PSRAM`) enabled, flash erasing/writing
* will be blocked until unmap.
*
* @param offset - Starting flash offset to map to memory.
* @param length - Length of data to map.
*
* @return Pointer to mapped data memory (at src_addr), or NULL
* if an allocation error occurred.
*/
const void *bootloader_mmap(uint32_t src_addr, uint32_t size);
/**
* @brief Unmap a previously mapped region of flash
*
* Call bootloader_munmap once for each successful call to bootloader_mmap.
*/
void bootloader_munmap(const void *mapping);
/**
* @brief Read data from Flash.
*
*
* @note All of src, dest and size have to be 4-byte aligned.
*
* @param src source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
* @param allow_decrypt If true and flash encryption is enabled, data on flash
* will be decrypted transparently as part of the read.
*
* @return ESP_OK on success, ESP_ERR_FLASH_OP_FAIL on SPI failure,
* ESP_ERR_FLASH_OP_TIMEOUT on SPI timeout.
*/
esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt);
/**
* @brief Write data to Flash.
*
* @note All of dest_addr, src and size have to be 4-byte aligned. If write_encrypted is set, dest_addr and size must be 32-byte aligned.
*
* @note In bootloader, when write_encrypted == true, the src buffer is encrypted in place.
*
* @note [ESP-TEE] Using this API from the TEE will return an error if the dest_addr lies
* within the active TEE partition range.
*
* @param dest_addr Destination address to write in Flash.
* @param src Pointer to the data to write to flash
* @param size Length of data in bytes.
* @param write_encrypted If true, data will be written encrypted on flash.
*
* @return ESP_OK on success, ESP_ERR_FLASH_OP_FAIL on SPI failure,
* ESP_ERR_FLASH_OP_TIMEOUT on SPI timeout.
*/
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted);
/**
* @brief Erase the Flash sector.
*
* @param sector Sector number, the count starts at sector 0, 4KB per sector.
*
* @return esp_err_t
*/
esp_err_t bootloader_flash_erase_sector(size_t sector);
/**
* @brief Erase the Flash range.
*
* @note [ESP-TEE] Using this API from the TEE will return an error if the start_addr lies
* within the active TEE partition range.
*
* @param start_addr start address of flash offset
* @param size sector aligned size to be erased
*
* @return esp_err_t
*/
esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size);
/**
* @brief Execute a user command on the flash
*
* @param command The command value to execute.
* @param mosi_data MOSI data to send
* @param mosi_len Length of MOSI data, in bits
* @param miso_len Length of MISO data to receive, in bits
* @return Received MISO data
*/
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/**
* @brief Read the SFDP of the flash
*
* @param sfdp_addr Address of the parameter to read
* @param miso_byte_num Bytes to read
* @return The read SFDP, little endian, 4 bytes at most
*/
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
/**
* @brief Enable the flash write protect (WEL bit).
*/
void bootloader_enable_wp(void);
/**
* @brief Once this function is called,
* any on-going internal operations will be terminated and the device will return to its default power-on
* state and lose all the current volatile settings, such as Volatile Status Register bits, Write Enable Latch
* (WEL) status, Program/Erase Suspend status, etc.
*/
void bootloader_spi_flash_reset(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -4,17 +4,22 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <bootloader_flash_priv.h>
#include <esp_log.h>
#include "esp_efuse.h"
#include "sdkconfig.h"
#include "esp_efuse.h"
#include "esp_log.h"
#include "esp_flash_encrypt.h"
#include "esp_private/bootloader_flash_internal.h"
#include "soc/soc_caps.h"
#include "hal/efuse_ll.h"
#include "hal/efuse_hal.h"
#include "hal/spi_flash_types.h"
#include "hal/esp_flash_err.h"
#include "spi_flash_defs.h"
#if !NON_OS_BUILD
#include "spi_flash_mmap.h"
// This dependency will be removed in the future. IDF-5025
#include "esp_flash.h"
#endif
#include "hal/spi_flash_ll.h"
#include "rom/spi_flash.h"
@@ -23,9 +28,6 @@
#include "hal/spimem_flash_ll.h"
#endif
// This dependency will be removed in the future. IDF-5025
#include "esp_flash.h"
#include "esp_rom_spiflash.h"
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
@@ -64,7 +66,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
return NULL; /* existing mapping in use... */
}
const void *result = NULL;
uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
uint32_t src_page = src_addr & ~(CONFIG_MMU_PAGE_SIZE - 1);
size += (src_addr - src_page);
esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_FLAG_DATA | SPI_FLASH_MMAP_FLAG_BLOCKS_WRITE, &result, &map);
if (err != ESP_OK) {
@@ -123,7 +125,6 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "esp_flash_chips/spi_flash_defs.h"
#if ESP_TEE_BUILD
#include "esp_fault.h"
@@ -362,7 +363,7 @@ const void *bootloader_mmap(uint32_t src_paddr, uint32_t size)
#if CONFIG_IDF_TARGET_ESP32
uint32_t count = GET_REQUIRED_MMU_PAGES(size, src_paddr);
int e = cache_flash_mmu_set(0, 0, FLASH_MMAP_VADDR, src_paddr_aligned, 64, count);
ESP_EARLY_LOGV(TAG, "after mapping, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", src_paddr_aligned, (uint32_t)FLASH_MMAP_VADDR, count * SPI_FLASH_MMU_PAGE_SIZE);
ESP_EARLY_LOGV(TAG, "after mapping, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", src_paddr_aligned, (uint32_t)FLASH_MMAP_VADDR, count * CONFIG_MMU_PAGE_SIZE);
if (e != 0) {
ESP_EARLY_LOGE(TAG, "cache_flash_mmu_set failed: %d", e);
Cache_Read_Enable(0);
@@ -491,20 +492,20 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
#else
cache_hal_suspend(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
//---------------Invalidating entries at to-be-mapped v_addr------------------------
cache_hal_invalidate_addr(FLASH_READ_VADDR, SPI_FLASH_MMU_PAGE_SIZE);
cache_hal_invalidate_addr(FLASH_READ_VADDR, CONFIG_MMU_PAGE_SIZE);
#endif
#endif
//---------------Do mapping------------------------
ESP_EARLY_LOGD(TAG, "mmu set block paddr=0x%08" PRIx32 " (was 0x%08" PRIx32 ")", map_at, current_read_mapping);
#if CONFIG_IDF_TARGET_ESP32
//Should never fail if we only map a SPI_FLASH_MMU_PAGE_SIZE to the vaddr starting from FLASH_READ_VADDR
//Should never fail if we only map a CONFIG_MMU_PAGE_SIZE to the vaddr starting from FLASH_READ_VADDR
// Return value unused if asserts are disabled
int e __attribute__((unused)) = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
assert(e == 0);
#else
uint32_t actual_mapped_len = 0;
mmu_hal_map_region(0, MMU_TARGET_FLASH0, FLASH_READ_VADDR, map_at, SPI_FLASH_MMU_PAGE_SIZE - 1, &actual_mapped_len);
mmu_hal_map_region(0, MMU_TARGET_FLASH0, FLASH_READ_VADDR, map_at, CONFIG_MMU_PAGE_SIZE - 1, &actual_mapped_len);
#endif
current_read_mapping = map_at;
@@ -1017,15 +1018,6 @@ esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
return ESP_OK;
}
bool IRAM_ATTR bootloader_flash_is_octal_mode_enabled(void)
{
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
return efuse_ll_get_flash_type();
#else
return false;
#endif
}
esp_rom_spiflash_read_mode_t bootloader_flash_get_spi_mode(void)
{
esp_rom_spiflash_read_mode_t spi_mode = ESP_ROM_SPIFLASH_FASTRD_MODE;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,7 +20,8 @@
#include "soc/soc_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_config.h"
#include "bootloader_flash_priv.h"
#include "esp_private/bootloader_flash_internal.h"
#include "spi_flash_defs.h"
#include "bootloader_common.h"
#include "bootloader_flash.h"
#include "bootloader_init.h"
@@ -28,6 +29,7 @@
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "hal/efuse_ll.h"
#define FLASH_IO_MATRIX_DUMMY_40M 0
#define FLASH_IO_MATRIX_DUMMY_80M 0
@@ -50,7 +52,7 @@ void bootloader_flash_update_size(uint32_t size)
void IRAM_ATTR bootloader_flash_cs_timing_config()
{
//SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH, so we only need to set SPI0 related registers here
if (bootloader_flash_is_octal_mode_enabled()) {
if (efuse_ll_get_flash_type()) {
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_CS_HOLD_TIME_S);
@@ -286,7 +288,7 @@ esp_err_t bootloader_init_spi_flash(void)
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
if (!bootloader_flash_is_octal_mode_enabled()) {
if (!efuse_ll_get_flash_type()) {
bootloader_enable_qio_mode();
}
#endif

View File

@@ -19,9 +19,10 @@
#include "soc/efuse_reg.h"
#include "soc/chip_revision.h"
#include "hal/efuse_hal.h"
#include "hal/misc.h"
#include "esp_image_format.h"
#include "sys/param.h"
#include "bootloader_flash_priv.h"
#include "esp_private/bootloader_flash_internal.h"
#include "esp_rom_caps.h"
#include "esp_macros.h"

View File

@@ -38,7 +38,7 @@
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"
#include "bootloader_flash_priv.h"
#include "esp_private/bootloader_flash_internal.h"
#include "bootloader_random.h"
#include "bootloader_config.h"
#include "bootloader_common.h"
@@ -1067,12 +1067,12 @@ static void set_cache_and_start_app(
//The addr is aligned, so we add the mask off length to the size, to make sure the corresponding buses are enabled.
drom_size = (drom_load_addr - drom_load_addr_aligned) + drom_size;
#if CONFIG_IDF_TARGET_ESP32
uint32_t drom_page_count = (drom_size + SPI_FLASH_MMU_PAGE_SIZE - 1) / SPI_FLASH_MMU_PAGE_SIZE;
uint32_t drom_page_count = (drom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;
rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr_aligned, 64, drom_page_count);
ESP_EARLY_LOGV(TAG, "rc=%d", rc);
rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr_aligned, 64, drom_page_count);
ESP_EARLY_LOGV(TAG, "rc=%d", rc);
ESP_EARLY_LOGV(TAG, "after mapping rodata, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, drom_load_addr_aligned, drom_page_count * SPI_FLASH_MMU_PAGE_SIZE);
ESP_EARLY_LOGV(TAG, "after mapping rodata, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, drom_load_addr_aligned, drom_page_count * CONFIG_MMU_PAGE_SIZE);
#else
uint32_t actual_mapped_len = 0;
if (s_flash_seg_needs_map(drom_load_addr_aligned)) {
@@ -1091,12 +1091,12 @@ static void set_cache_and_start_app(
//The addr is aligned, so we add the mask off length to the size, to make sure the corresponding buses are enabled.
irom_size = (irom_load_addr - irom_load_addr_aligned) + irom_size;
#if CONFIG_IDF_TARGET_ESP32
uint32_t irom_page_count = (irom_size + SPI_FLASH_MMU_PAGE_SIZE - 1) / SPI_FLASH_MMU_PAGE_SIZE;
uint32_t irom_page_count = (irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;
rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr_aligned, 64, irom_page_count);
ESP_EARLY_LOGV(TAG, "rc=%d", rc);
rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr_aligned, 64, irom_page_count);
ESP_LOGV(TAG, "rc=%d", rc);
ESP_EARLY_LOGV(TAG, "after mapping text, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", irom_addr_aligned, irom_load_addr_aligned, irom_page_count * SPI_FLASH_MMU_PAGE_SIZE);
ESP_EARLY_LOGV(TAG, "after mapping text, starting from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", irom_addr_aligned, irom_load_addr_aligned, irom_page_count * CONFIG_MMU_PAGE_SIZE);
#else
if (s_flash_seg_needs_map(irom_load_addr_aligned)) {
mmu_hal_map_region(0, MMU_TARGET_FLASH0, irom_load_addr_aligned, irom_addr_aligned, irom_size, &actual_mapped_len);

View File

@@ -33,6 +33,7 @@
#include "hal/assist_debug_ll.h"
#include "esp_rom_sys.h"
#include "soc/regi2c_bias.h"
#include "soc/regi2c_mpll.h"
#include "hal/regi2c_ctrl.h"
#include "hal/psram_ctrlr_ll.h"

View File

@@ -32,15 +32,15 @@ list(APPEND srcs "src/esp_efuse_api.c"
if(non_os_build)
idf_component_register(SRCS "${srcs}"
PRIV_REQUIRES bootloader_support soc spi_flash esp_hal_security
PRIV_REQUIRES bootloader_support soc esp_hal_security
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS "${private_include}")
else()
list(APPEND srcs "src/esp_efuse_startup.c")
if(${target} STREQUAL "linux")
set(priv_requires soc spi_flash esp_system esp_partition esp_hal_security)
set(priv_requires soc esp_system esp_partition esp_hal_security)
else()
set(priv_requires bootloader_support soc spi_flash esp_system esp_partition esp_app_format esp_hal_security)
set(priv_requires bootloader_support soc esp_system esp_partition esp_app_format esp_hal_security)
endif()
idf_component_register(SRCS "${srcs}"
PRIV_REQUIRES "${priv_requires}"

View File

@@ -6,7 +6,7 @@ endif()
set(srcs)
set(include "include")
set(priv_requires esp_driver_gpio esp_driver_dma esp_pm esp_mm esp_hal_clock)
set(priv_requires esp_driver_gpio esp_driver_dma esp_pm esp_mm esp_hal_clock esp_mspi)
# TODO(IDF-15984): potentially remove __ULP_BUILDV2 handling from esp_driver_i2s
if(__ULP_BUILDV2)

View File

@@ -11,6 +11,6 @@ if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED)
endif()
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity esp_driver_pcnt spi_flash
esp_driver_gpio esp_driver_i2s esp_driver_uart esp_psram esp_driver_gptimer
PRIV_REQUIRES unity esp_driver_pcnt esp_driver_gpio esp_driver_i2s esp_driver_uart
esp_psram esp_mspi esp_driver_gptimer
WHOLE_ARCHIVE)

View File

@@ -30,6 +30,6 @@ idf_component_register(
SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES esp_pm esp_hal_gpspi esp_driver_dma
PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio spi_flash
PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio spi_flash esp_mspi
LDFRAGMENTS "linker.lf"
)

View File

@@ -11,6 +11,6 @@ set(srcs
idf_component_register(
SRCS ${srcs}
# esp_psram is required for CONFIG_SPIRAM, used by the release configs
PRIV_REQUIRES esp_driver_spi spi_flash esp_driver_gpio esp_psram
PRIV_REQUIRES esp_driver_spi esp_driver_gpio esp_mspi esp_psram
WHOLE_ARCHIVE
)

View File

@@ -1,7 +1,4 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs)
set(public_include "include")

View File

@@ -1,14 +1,15 @@
idf_build_get_property(target IDF_TARGET)
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
if(${target} STREQUAL "linux")
idf_component_register(INCLUDE_DIRS "include"
REQUIRES soc hal)
return()
endif()
set(srcs)
set(includes "include" "${target}/include")
set(requires soc hal esp_hal_gpspi)
set(priv_requires esp_hal_gpio)
if(NOT "${target}" STREQUAL "linux")
# TODO: IDF-15106 remove esp_hal_clock dependency
list(APPEND requires "esp_hal_clock")
endif()
if(esp_tee_build)
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
@@ -35,6 +36,6 @@ list(APPEND srcs "${target}/mspi_periph.c")
idf_component_register(
SRCS ${srcs}
INCLUDE_DIRS ${includes}
REQUIRES soc hal esp_hal_gpspi esp_hal_clock # TODO: IDF-15106 remove esp_hal_clock dependency
PRIV_REQUIRES esp_hal_gpio
REQUIRES ${requires}
PRIV_REQUIRES ${priv_requires}
)

View File

@@ -25,6 +25,7 @@
#include "soc/pcr_struct.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/spi_mem_c_reg.h"
#ifdef __cplusplus
extern "C" {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -0,0 +1,5 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -14,8 +14,6 @@ endif()
set(public_include_dirs "include" "include/soc"
"ldo/include" "debug_probe/include" "etm/include"
"mspi/mspi_timing_tuning/include" "mspi/mspi_timing_tuning/tuning_scheme_impl/include"
"mspi/mspi_intr/include"
"mspi/esp_mspi_align/include"
"mspi/mspi_mem_barrier/include"
"power_supply/include" "modem/include")
@@ -44,7 +42,7 @@ endif()
set(requires esp_hal_gpio esp_hal_usb esp_hal_pmu esp_hal_regi2c esp_hal_uart esp_hal_debug_assist)
set(priv_requires efuse # only esp_hw_support/adc_share_hw_ctrl.c requires efuse component
spi_flash
esp_mspi
bootloader_support
esp_hal_wdt
esp_hal_rtc_timer
@@ -156,27 +154,6 @@ if(NOT non_os_build)
"port/regdma_link.c")
endif()
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
list(APPEND srcs "mspi/mspi_timing_tuning/mspi_timing_tuning.c")
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY AND NOT CONFIG_IDF_TARGET_ESP32S3)
set(mspi_delay_file
"${CMAKE_CURRENT_LIST_DIR}/mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c"
)
if(EXISTS "${mspi_delay_file}")
list(APPEND srcs "mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c")
endif()
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY)
list(APPEND srcs "mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c")
endif()
list(APPEND srcs "mspi/mspi_intr/mspi_intr.c")
endif()
if(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED AND CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB)
list(APPEND srcs "sleep_wake_stub.c")
endif()
@@ -196,18 +173,6 @@ if(NOT non_os_build)
else()
if(ESP_TEE_BUILD)
list(APPEND srcs "esp_clk.c" "hw_random.c")
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
list(APPEND srcs "mspi/mspi_timing_tuning/mspi_timing_tuning.c")
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY)
list(APPEND srcs "mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY)
list(APPEND srcs "mspi/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c")
endif()
endif()
endif()
# Requires "_esp_error_check_failed()" function
@@ -230,9 +195,6 @@ idf_define_esp_err_codes(HEADERS include/esp_memprot_err.h)
idf_build_get_property(target IDF_TARGET)
add_subdirectory(port/${target})
if(CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING)
add_subdirectory(mspi/mspi_timing_tuning/port/${target})
endif()
add_subdirectory(lowpower)
add_subdirectory(modem)

View File

@@ -86,7 +86,7 @@ This document describes the implementation differences of MSPI interrupt handlin
| File | Description |
|------|-------------|
| `components/esp_hw_support/mspi/mspi_intr/mspi_intr.c` | Shared MSPI interrupt management |
| `components/esp_mspi/mspi_intr/mspi_intr.c` | Shared MSPI interrupt management |
| `components/esp_psram/system_layer/esp_psram_mspi.c` | PSRAM specific interrupt handling |
---

View File

@@ -4,19 +4,3 @@ entries:
if APP_BUILD_TYPE_PURE_RAM_APP = n:
esp_mspi_align:esp_mspi_get_alignment (noflash)
esp_mspi_align:esp_mspi_buffer_alignment_satisfied (noflash)
[mapping:mspi_timing_tuning_driver]
archive: libesp_hw_support.a
entries:
if APP_BUILD_TYPE_PURE_RAM_APP = n:
mspi_timing_tuning (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY = y:
mspi_timing_by_mspi_delay (noflash)
mspi_timing_config (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y:
mspi_timing_by_dqs (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY = y:
mspi_timing_by_flash_delay (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY = y:
mspi_timing_config (noflash)

View File

@@ -40,7 +40,6 @@
#include "esp_private/sleep_gpio.h"
#include "esp_private/spi_flash_os.h"
#include "esp_private/startup_internal.h"
#include "bootloader_flash.h"
ESP_LOG_ATTR_TAG(TAG, "sleep_gpio");
@@ -152,7 +151,7 @@ void esp_sleep_config_gpio_isolate(void)
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_HD), GPIO_PULLUP_ONLY);
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_WP), GPIO_PULLUP_ONLY);
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
bool octal_mspi_required = bootloader_flash_is_octal_mode_enabled();
bool octal_mspi_required = spi_flash_is_octal_mode_enabled();
#if CONFIG_SPIRAM_MODE_OCT
octal_mspi_required |= true;
#endif // CONFIG_SPIRAM_MODE_OCT

View File

@@ -22,18 +22,6 @@ components/esp_hw_support/test_apps/host_test_linux:
depends_components:
- esp_hw_support
components/esp_hw_support/test_apps/mspi:
depends_components:
- esp_hw_support
- spi_flash
- esp_partition
- esp_hal_mspi
- soc
disable:
- if: IDF_TARGET not in ["esp32s3", "esp32p4", "esp32c61", "esp32c5", "esp32s31"]
- if: CONFIG_NAME in ["generic_timing_tuning_log_safe", "generic_timing_tuning_xip"] and IDF_TARGET in ["esp32s31"]
- if: CONFIG_NAME == "120sdr_120sdr" and IDF_TARGET in ["esp32s3", "esp32p4", "esp32s31"]
components/esp_hw_support/test_apps/mspi_psram_with_dfs:
depends_components:
- esp_hw_support

View File

@@ -10,7 +10,7 @@
#include <esp_fault.h>
#include <esp_log.h>
#include <esp_attr.h>
#include <bootloader_flash_priv.h>
#include <esp_private/bootloader_flash_internal.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>
#include "bootloader_util.h"
@@ -22,7 +22,6 @@
#include "soc/soc_caps.h"
#include "hal/mmu_types.h"
#include "hal/cache_ll.h"
#include "spi_flash_mmap.h"
#include "hal/efuse_hal.h"
#include "sdkconfig.h"
#include "esp_macros.h"
@@ -688,7 +687,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
return ESP_ERR_NO_MEM;
}
uint32_t max_image_len;
if (__builtin_mul_overflow(max_pages, SPI_FLASH_MMU_PAGE_SIZE, &max_image_len)) {
if (__builtin_mul_overflow(max_pages, CONFIG_MMU_PAGE_SIZE, &max_image_len)) {
max_image_len = UINT32_MAX;
}
segment_data.data_len = MIN(data_len_remain, max_image_len);
@@ -899,18 +898,18 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
metadata->mmu_page_size = (1UL << mmu_page_size);
} else {
// Fall back to default MMU page size
metadata->mmu_page_size = SPI_FLASH_MMU_PAGE_SIZE;
metadata->mmu_page_size = CONFIG_MMU_PAGE_SIZE;
}
if (metadata->mmu_page_size != SPI_FLASH_MMU_PAGE_SIZE) {
ESP_LOGI(TAG, "MMU page size mismatch, configured: 0x%x, found: 0x%"PRIx32, SPI_FLASH_MMU_PAGE_SIZE, metadata->mmu_page_size);
if (metadata->mmu_page_size != CONFIG_MMU_PAGE_SIZE) {
ESP_LOGI(TAG, "MMU page size mismatch, configured: 0x%x, found: 0x%"PRIx32, CONFIG_MMU_PAGE_SIZE, metadata->mmu_page_size);
}
} else if (index == 0 && is_bootloader(metadata->start_addr)) {
// Bootloader always uses the default MMU page size
metadata->mmu_page_size = SPI_FLASH_MMU_PAGE_SIZE;
metadata->mmu_page_size = CONFIG_MMU_PAGE_SIZE;
}
#else // SOC_MMU_PAGE_SIZE_CONFIGURABLE
metadata->mmu_page_size = SPI_FLASH_MMU_PAGE_SIZE;
metadata->mmu_page_size = CONFIG_MMU_PAGE_SIZE;
#endif // !SOC_MMU_PAGE_SIZE_CONFIGURABLE
const int mmu_page_size = metadata->mmu_page_size;

View File

@@ -5,5 +5,5 @@ set(srcs "test_app_main.c"
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES esp_lcd unity esp_timer spi_flash esp_driver_ppa efuse
PRIV_REQUIRES esp_lcd unity esp_timer esp_mspi esp_driver_ppa efuse
WHOLE_ARCHIVE)

View File

@@ -82,7 +82,7 @@ else()
list(APPEND ldfragments src/picolibc/libc.lf)
endif()
set(priv_reqs soc spi_flash)
set(priv_reqs soc esp_mspi)
if(IDF_BUILD_V2)
if(CONFIG_VFS_SUPPORT_IO)

View File

@@ -21,5 +21,5 @@ if(CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS)
endif()
idf_component_register(SRCS "${srcs}"
PRIV_REQUIRES unity vfs cmock esp_timer spi_flash test_utils pthread esp_psram
PRIV_REQUIRES unity vfs cmock esp_timer esp_mspi test_utils pthread esp_psram
WHOLE_ARCHIVE)

View File

@@ -6,8 +6,8 @@ endif()
set(includes "include")
# Note: requires spi_flash for cache_utils, will be refactored
set(priv_requires heap spi_flash esp_hal_dma)
# Note: requires esp_mspi for cache_utils
set(priv_requires heap esp_hal_dma esp_mspi)
set(srcs)

View File

@@ -0,0 +1,106 @@
idf_build_get_property(target IDF_TARGET)
idf_build_get_property(non_os_build NON_OS_BUILD)
if(${target} STREQUAL "linux")
idf_component_register(SRCS "linux/cache_utils.c"
INCLUDE_DIRS include
REQUIRES esp_hal_mspi)
return()
endif()
if(non_os_build OR CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
set(priv_requires bootloader_support soc esp_hal_gpio)
set(requires hal esp_hal_mspi)
set(srcs "spi_flash_wrap.c" "spi_flash_os_tee_stub.c")
if(ESP_TEE_BUILD)
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
list(APPEND srcs "mspi_timing_tuning/mspi_timing_tuning.c")
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c")
endif()
endif()
endif()
else()
set(priv_requires bootloader_support soc esp_hal_gpio esp_mm)
set(requires hal esp_hal_mspi)
set(srcs "flash_brownout_hook.c" "cache_utils.c" "flash_ops.c" "spi_flash_wrap.c")
# MSPI0 Octal flash init
if(CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE)
list(APPEND srcs "${target}/spi_flash_oct_flash_init.c")
endif()
if(CONFIG_SPI_FLASH_HPM_ON)
list(APPEND srcs "spi_flash_hpm_enable.c")
endif()
if(CONFIG_ESP_SLEEP_SET_FLASH_DPD)
list(APPEND srcs "spi_flash_dpd_enable.c")
endif()
# MSPI timing tuning
list(APPEND srcs "mspi_timing_tuning/mspi_timing_tuning.c")
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY AND NOT CONFIG_IDF_TARGET_ESP32S3)
set(mspi_delay_file
"${CMAKE_CURRENT_LIST_DIR}/mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c"
)
if(EXISTS "${mspi_delay_file}")
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c")
endif()
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c")
endif()
# MSPI intr
list(APPEND srcs "mspi_intr/mspi_intr.c")
endif()
set(include_dirs include
"mspi_timing_tuning/include"
"mspi_timing_tuning/tuning_scheme_impl/include"
"mspi_intr/include")
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}")
list(APPEND include_dirs "${target}")
endif()
set(ldfragments linker.lf)
idf_component_register(SRCS "${srcs}"
REQUIRES ${requires}
PRIV_REQUIRES "${priv_requires}"
INCLUDE_DIRS ${include_dirs}
LDFRAGMENTS ${ldfragments})
# Avoid cache miss by unexpected inlineing when built by -Os
set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS "-fno-inline-functions")
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
# These flags are GCC specific
set_property(SOURCE ${cache_srcs} APPEND_STRING PROPERTY COMPILE_FLAGS
" -fno-inline-small-functions -fno-inline-functions-called-once")
endif()
if(NOT non_os_build AND NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
if(CONFIG_SPIRAM)
# esp_mspi_get_io() queries esp_psram_io_get_cs_io() for the PSRAM CS pin
idf_component_optional_requires(PRIVATE esp_psram)
endif()
# Force linking init_flash_os ESP_SYSTEM_INIT_FN to ensure it's not discarded by linker
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_mspi_flash_ops_include_func")
endif()
idf_build_get_property(target IDF_TARGET)
if(CONFIG_SOC_SPI_MEM_SUPPORT_TIMING_TUNING)
add_subdirectory(mspi_timing_tuning/port/${target})
endif()

View File

@@ -0,0 +1,85 @@
menu "MSPI Flash configuration"
depends on !APP_BUILD_TYPE_PURE_RAM_APP
menu "SPI Flash behavior when brownout"
config SPI_FLASH_BROWNOUT_RESET_XMC
bool "Enable sending reset when brownout for XMC flash chips"
default y
select SPI_FLASH_BROWNOUT_RESET
help
When this option is selected, the patch will be enabled for XMC.
Follow the recommended flow by XMC for better stability.
DO NOT DISABLE UNLESS YOU KNOW WHAT YOU ARE DOING.
config SPI_FLASH_BROWNOUT_RESET
bool
default y
select ESP_BROWNOUT_USE_INTR
help
When brownout happens during flash erase/write operations,
send reset command to stop the flash operations to improve stability.
endmenu
menu "Optional and Experimental MSPI Features (READ DOCS FIRST)"
comment "Features here require specific hardware (READ DOCS FIRST!)"
config SPI_FLASH_UNDER_HIGH_FREQ
bool
default y if ESPTOOLPY_FLASHFREQ_120M
help
This is a helper config for HPM. Invisible for users.
choice SPI_FLASH_HPM
prompt "High Performance Mode (READ DOCS FIRST, > 80MHz)"
depends on SOC_SPI_MEM_FLASH_SUPPORT_HPM && !ESPTOOLPY_OCT_FLASH
default SPI_FLASH_HPM_AUTO
help
Whether the High Performance Mode of Flash is enabled. As an optional feature, user needs to manually
enable this option as a confirmation. To be back-compatible with earlier IDF version, this option is
automatically enabled with warning when Flash running > 80Mhz.
config SPI_FLASH_HPM_ENA
# Not using name of SPI_FLASH_HPM_ENABLE because it was used as an invisible option and we don't want
# to inherit the value of that one
bool "Enable"
config SPI_FLASH_HPM_AUTO
bool "Auto (Not recommended)"
config SPI_FLASH_HPM_DIS
bool "Disabled"
endchoice
config SPI_FLASH_HPM_ON
bool
# For ESP32-S3, it's enabled by default. For later chips it should be disabled by default
default y if (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && ((SPI_FLASH_HPM_ENA || SPI_FLASH_HPM_AUTO)) || \
(!IDF_TARGET_ESP32S3 && SPI_FLASH_HPM_ENA)
help
This option is invisible, and will be selected automatically
when ``ESPTOOLPY_FLASHFREQ_120M`` is selected.
choice SPI_FLASH_HPM_DC
prompt "Support HPM using DC (READ DOCS FIRST)"
depends on SPI_FLASH_HPM_ON
default SPI_FLASH_HPM_DC_AUTO
help
This feature needs your bootloader to be compiled DC-aware (BOOTLOADER_FLASH_DC_AWARE=y). Otherwise the
chip will not be able to boot after a reset.
config SPI_FLASH_HPM_DC_AUTO
bool "Auto (Enable when bootloader support enabled (BOOTLOADER_FLASH_DC_AWARE))"
config SPI_FLASH_HPM_DC_DISABLE
bool "Disable (READ DOCS FIRST)"
endchoice
config SPI_FLASH_HPM_DC_ON
bool
default y if SPI_FLASH_HPM_DC_AUTO && BOOTLOADER_FLASH_DC_AWARE
help
This is a helper config for HPM. Whether HPM-DC is enabled is also determined by bootloader.
Invisible for users.
endmenu
endmenu

View File

@@ -0,0 +1,8 @@
# `esp_mspi`
The `esp_mspi` component provides shared low-level support for flash and PSRAM connected through the MSPI peripheral.
- Coordinates flash operations, cache handling, and memory access.
- Provides MSPI timing tuning, high-performance mode, and power management support.
- Provides shared alignment and memory-barrier utilities.
- Serves as the common MSPI layer used by `spi_flash` for flash access and by `esp_psram` for external RAM support.

View File

@@ -305,7 +305,6 @@ void spi_flash_op_unlock(void)
#endif // #if ( ( CONFIG_FREERTOS_SMP ) && ( !CONFIG_FREERTOS_UNICORE ) )
}
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
{
spi_flash_op_lock();
@@ -350,7 +349,6 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os(void)
#endif // CONFIG_FREERTOS_UNICORE
void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid)
{
#if CONFIG_IDF_TARGET_ESP32
@@ -851,7 +849,6 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
#endif
#if (CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM)
extern bool psram_support_wrap_size(uint32_t wrap_size);
if (!psram_support_wrap_size(spiram_wrap_size)) {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -1,14 +1,14 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_flash_chips/spi_flash_defs.h"
#include "spi_flash_defs.h"
//MXIC OPI mode needs two bytes of command - 2nd byte is the inversion of the command (1st) byte. S3 HW send LSB first
#define MXIC_CMD16(cmd8) ( (uint8_t)(cmd8) | ((uint8_t)(~(cmd8)) << 8) )
#define MXIC_CMD16(cmd8) ( (uint8_t)(cmd8) | ((uint8_t)(~(cmd8)) << 8) )
#define OPI_CMD_FORMAT_MXIC_STR() { \
.rdid = { \

View File

@@ -10,7 +10,7 @@
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/opi_flash.h"
#include "esp_private/spi_flash_os.h"
#include "opi_flash_private.h"
#include "esp_private/opi_flash_private.h"
#include "soc/spi_mem_reg.h"
#include "soc/io_mux_reg.h"
#include "opi_flash_cmd_format_mxic.h"
@@ -31,11 +31,9 @@ const static char *TAG = "Octal Flash";
extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs;
static uint32_t s_chip_id;
static void s_register_rom_function(void)
{
static spiflash_legacy_funcs_t rom_func =
{
static spiflash_legacy_funcs_t rom_func = {
.read_sub_len = 32,
.write_sub_len = 32,
.unlock = esp_rom_opiflash_wait_idle,
@@ -233,7 +231,6 @@ static void s_mxic_set_required_regs(uint32_t chip_id)
}
#endif
/*----------------------------------------------------------------------------------------------------
General Functions
-----------------------------------------------------------------------------------------------------*/

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,10 +9,6 @@
#include <string.h>
#include <stdio.h>
#include <sys/param.h> // For MIN/MAX(a, b)
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <soc/soc.h>
#include <soc/soc_memory_layout.h>
#include "soc/io_mux_reg.h"
@@ -20,9 +16,9 @@
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_cpu.h"
#include "spi_flash_mmap.h"
#include "esp_log.h"
#include "esp_private/system_internal.h"
#include "esp_private/startup_internal.h"
#include "esp_private/spi_flash_os.h"
#include "esp_private/esp_clk.h"
#include "esp_private/esp_gpio_reserve.h"
@@ -35,7 +31,7 @@
#include "soc/spi_mem_reg.h"
#include "esp32s3/rom/opi_flash.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/opi_flash_private.h"
#include "esp_private/opi_flash_private.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32C2
@@ -46,10 +42,8 @@
#include "esp32c61/rom/cache.h"
#endif
#include "esp_rom_spiflash.h"
#include "esp_flash_partitions.h"
#include "esp_private/mspi_timing_tuning.h"
#include "esp_private/cache_utils.h"
#include "esp_flash.h"
#include "esp_attr.h"
#include "bootloader_flash.h"
#include "bootloader_flash_config.h"
@@ -103,28 +97,12 @@ const spi_flash_guard_funcs_t *IRAM_ATTR spi_flash_guard_get(void)
return s_flash_guard_ops;
}
#ifdef CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS
#define UNSAFE_WRITE_ADDRESS abort()
#else
#define UNSAFE_WRITE_ADDRESS return false
#endif
static __attribute__((unused)) bool is_safe_write_address(size_t addr, size_t size)
{
if (!esp_partition_main_flash_region_safe(addr, size)) {
UNSAFE_WRITE_ADDRESS;
}
return true;
}
#if CONFIG_SPI_FLASH_ROM_IMPL
#include "esp_heap_caps.h"
void IRAM_ATTR *spi_flash_malloc_internal(size_t size)
{
return heap_caps_malloc(size, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
return heap_caps_malloc(size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
}
void IRAM_ATTR spi_flash_rom_impl_init(void)
@@ -142,10 +120,19 @@ void IRAM_ATTR spi_flash_rom_impl_init(void)
}
#endif
bool IRAM_ATTR spi_flash_is_octal_mode_enabled(void)
{
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
return efuse_ll_get_flash_type();
#else
return false;
#endif
}
void IRAM_ATTR esp_mspi_pin_init(void)
{
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
bool octal_mspi_required = bootloader_flash_is_octal_mode_enabled();
bool octal_mspi_required = spi_flash_is_octal_mode_enabled();
#if CONFIG_SPIRAM_MODE_OCT
octal_mspi_required |= true;
#endif
@@ -164,8 +151,8 @@ void esp_mspi_pin_reserve(void)
uint8_t mspi_io;
for (esp_mspi_io_t i = 0; i < ESP_MSPI_IO_MAX; i++) {
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
if (!bootloader_flash_is_octal_mode_enabled()
&& i >= ESP_MSPI_IO_DQS && i <= ESP_MSPI_IO_D7) {
if (!spi_flash_is_octal_mode_enabled()
&& i >= ESP_MSPI_IO_DQS && i <= ESP_MSPI_IO_D7) {
continue;
}
#endif
@@ -180,12 +167,12 @@ void esp_mspi_pin_reserve(void)
esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
{
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
if (bootloader_flash_is_octal_mode_enabled()) {
if (spi_flash_is_octal_mode_enabled()) {
return esp_opiflash_init(rom_spiflash_legacy_data->chip.device_id);
}
#endif
#if CONFIG_SPI_FLASH_HPM_ON
return spi_flash_enable_high_performance_mode();
return spi_flash_enable_high_performance_mode();
#endif // CONFIG_SPI_FLASH_HPM_ON
return ESP_OK;
}
@@ -193,7 +180,7 @@ esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
void IRAM_ATTR spi_flash_set_rom_required_regs(void)
{
#if SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE
if (bootloader_flash_is_octal_mode_enabled()) {
if (spi_flash_is_octal_mode_enabled()) {
//Disable the variable dummy mode when doing timing tuning
CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY);
/**
@@ -205,21 +192,6 @@ void IRAM_ATTR spi_flash_set_rom_required_regs(void)
#endif
}
#if CONFIG_IDF_TARGET_ESP32S3 && CONFIG_SPIRAM_MODE_OCT
// This function will only be called when Octal PSRAM enabled.
void IRAM_ATTR spi_flash_set_vendor_required_regs(void)
{
if (bootloader_flash_is_octal_mode_enabled()) {
esp_opiflash_set_required_regs();
SET_PERI_REG_BITS(SPI_MEM_CACHE_FCTRL_REG(1), SPI_MEM_CACHE_USR_CMD_4BYTE_V, 1, SPI_MEM_CACHE_USR_CMD_4BYTE_S);
} else {
//Flash chip requires MSPI specifically, call this function to set them
// Set back MSPI registers after Octal PSRAM initialization.
SET_PERI_REG_BITS(SPI_MEM_CACHE_FCTRL_REG(1), SPI_MEM_CACHE_USR_CMD_4BYTE_V, 0, SPI_MEM_CACHE_USR_CMD_4BYTE_S);
}
}
#endif
static const uint8_t s_mspi_io_num_default[] = {
MSPI_IOMUX_PIN_NUM_CLK,
MSPI_IOMUX_PIN_NUM_MISO,
@@ -323,3 +295,41 @@ esp_err_t IRAM_ATTR esp_mspi_32bit_address_flash_feature_check(void)
return ESP_OK;
}
#endif // !CONFIG_IDF_TARGET_ESP32P4 || !CONFIG_APP_BUILD_TYPE_RAM
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
static esp_err_t dpd_enter_func(void)
{
spi_flash_ll_enter_dpd(&SPIMEM_LL_APB);
while (!spi_flash_ll_cmd_is_done(&SPIMEM_LL_APB)) {
//nop
}
return ESP_OK;
}
static esp_err_t dpd_exit_func(void)
{
spi_flash_ll_exit_dpd(&SPIMEM_LL_APB);
while (!spi_flash_ll_cmd_is_done(&SPIMEM_LL_APB)) {
//nop
}
return ESP_OK;
}
ESP_SYSTEM_INIT_FN(init_flash_dpd, CORE, BIT(0), 125)
{
// Register DPD function pointers
static spi_flash_dpd_funcs_t dpd_funcs = {
.enter_dpd = dpd_enter_func,
.exit_dpd = dpd_exit_func,
};
spi_flash_dpd_register_funcs(&dpd_funcs);
return ESP_OK;
}
#endif // CONFIG_ESP_SLEEP_SET_FLASH_DPD
void esp_mspi_flash_ops_include_func(void)
{
// Linker hook function, exists to make the linker examine this file so that
// the init_flash_dpd ESP_SYSTEM_INIT_FN above is not discarded.
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -14,19 +14,18 @@
#include "sdkconfig.h"
#include "esp_rom_spiflash.h"
#include "esp_err.h"
#include "esp_bit_defs.h"
#include "soc/soc_caps.h"
#include "soc/clk_tree_defs.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_flash_chips/esp_flash_types.h"
#include "esp_private/spi_share_hw_ctrl.h"
#include "esp_flash_chips/spi_flash_override.h"
#ifdef __cplusplus
extern "C" {
#endif
//-------------------Chip Related------------------//
// Type of MSPI IO
typedef enum {
ESP_MSPI_IO_CLK = 0,
@@ -53,6 +52,13 @@ typedef enum {
*/
esp_err_t spi_flash_init_chip_state(void);
/**
* @brief Check if octal flash mode is enabled in eFuse
*
* @return True if flash is in octal mode, false else
*/
bool spi_flash_is_octal_mode_enabled(void);
/**
* @brief To initislize the MSPI pins
*/
@@ -154,6 +160,22 @@ bool spi_flash_hpm_dummy_adjust(void);
#endif //CONFIG_SPI_FLASH_HPM_ON
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
//-------------------DPD Related------------------//
/**
* @brief Structure holding DPD function pointers
*/
typedef struct {
esp_err_t (*enter_dpd)(void);
esp_err_t (*exit_dpd)(void);
} spi_flash_dpd_funcs_t;
/**
* @brief Register DPD function pointers
*
* @param dpd_funcs Pointer to structure holding DPD function pointers
* @return ESP_OK on success
*/
esp_err_t spi_flash_dpd_register_funcs(spi_flash_dpd_funcs_t *dpd_funcs);
/**
* @brief Get the duration of entering deep power-down mode.
@@ -176,7 +198,7 @@ uint32_t spi_flash_dpd_get_exit_duration(void);
* @param wait_delay If true, wait tDP (enter) or tRES1 (exit) after the command.
* If false, skip the delay; the caller must ensure timing is met elsewhere
*
* @note If using self-provided flash (not the chips factory-default flash), consult its datasheet to use this API safely.
* @note If using self-provided flash (not the chip's factory-default flash), consult its datasheet to use this API safely.
*
* @return ESP_OK if success.
*/
@@ -252,7 +274,6 @@ typedef struct {
spi_flash_guard_end_func_t end; /**< critical section end function. */
} spi_flash_guard_funcs_t;
/**
* @brief Sets guard functions to access flash.
*
@@ -292,8 +313,6 @@ extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
*/
void spi_flash_rom_impl_init(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,92 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
#pragma once
// SPI commands
#define CMD_RDID 0x9F
#define CMD_RDUID 0x4B /* Read the flash unique ID*/
#define CMD_WRSR 0x01
#define SR_WIP (1<<0) /* Status register write-in-progress bit */
#define SR_WREN (1<<1) /* Status register write enable bit */
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WRSR3 0x11 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRENVSR 0x50 /* Flash write enable for volatile SR bits */
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_RDSR3 0x15 /* Not all SPI flash uses this command */
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
#define CMD_RDSCUR 0x2B /* MXIC-specific, read security register */
#define CMD_8READ 0xEC /* MXIC-specific, 8 I/O read */
#define CMD_8DTRD 0xEE /* MXIC-specific, 8 I/O DTR read */
#define CMD_RDFR 0x48 /* ISSI-specific, read function register */
#define CMD_FASTRD_QIO 0xEB
#define CMD_FASTRD_QIO_4B 0xEC
#define CMD_FASTRD_QUAD 0x6B
#define CMD_FASTRD_QUAD_4B 0x6C
#define CMD_FASTRD_DIO 0xBB
#define CMD_FASTRD_DIO_4B 0xBC
#define CMD_FASTRD_DUAL 0x3B
#define CMD_FASTRD_DUAL_4B 0x3C
#define CMD_FASTRD 0x0B
#define CMD_FASTRD_4B 0x0C
#define CMD_READ 0x03 /* Speed limited */
#define CMD_READ_4B 0x13 /* Speed limited */
#define CMD_SLOWRD_4B 0x13
#define CMD_CHIP_ERASE 0xC7
#define CMD_SECTOR_ERASE 0x20
#define CMD_SECTOR_ERASE_4B 0x21
#define CMD_LARGE_BLOCK_ERASE 0xD8 /* 64KB block erase command */
#define CMD_LARGE_BLOCK_ERASE_4B 0xDC /* 64KB block erase command */
#define CMD_PROGRAM_PAGE 0x02
#define CMD_PROGRAM_PAGE_4B 0x12
#define CMD_SUSPEND 0x75
#define CMD_RESUME 0x7A
#define CMD_HPMEN 0xA3 /* Enable High Performance mode on flash */
#define CMD_WRAP 0x77
#define CMD_BURST_RD 0xC0 /* wrap(0x77) and burst read are functionally same. But commands and formats is different */
#define CMD_RST_EN 0x66
#define CMD_RST_DEV 0x99
#define CMD_RESETEN 0x66
#define CMD_RESET 0x99
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
// Flash vendors.
#define SPI_FLASH_GD 0xC8
#define SPI_FLASH_ISSI 0x9D
#define SPI_FLASH_MXIC 0xC2
#define SPI_FLASH_XMC_1 0x20
#define SPI_FLASH_XMC_2 0x46
#define SPI_FLASH_WINBOND 0xEF
#define SPI_FLASH_TH 0xCD
#define SPI_FLASH_BY 0x68
#define SPI_FLASH_DIO_DUMMY_BITLEN 4
#define SPI_FLASH_QIO_DUMMY_BITLEN 6
#define SPI_FLASH_DIO_ADDR_BITLEN 24
#define SPI_FLASH_QIO_ADDR_BITLEN 24
#define SPI_FLASH_QOUT_ADDR_BITLEN 24
#define SPI_FLASH_QOUT_DUMMY_BITLEN 8
#define SPI_FLASH_DOUT_ADDR_BITLEN 24
#define SPI_FLASH_DOUT_DUMMY_BITLEN 8
#define SPI_FLASH_FASTRD_ADDR_BITLEN 24
#define SPI_FLASH_FASTRD_DUMMY_BITLEN 8
#define SPI_FLASH_SLOWRD_ADDR_BITLEN 24
#define SPI_FLASH_SLOWRD_DUMMY_BITLEN 0
#define SPI_FLASH_OPISTR_ADDR_BITLEN 32
#define SPI_FLASH_OPISTR_DUMMY_BITLEN 20
#define SPI_FLASH_OPIDTR_ADDR_BITLEN 32
#define SPI_FLASH_OPIDTR_DUMMY_BITLEN 40
#define SPI_FLASH_QIO_HPM_DUMMY_BITLEN 10
#define SPI_FLASH_DIO_HPM_DUMMY_BITLEN 8

View File

@@ -0,0 +1,38 @@
[mapping:esp_mspi]
archive: libesp_mspi.a
entries:
if APP_BUILD_TYPE_PURE_RAM_APP = n:
flash_brownout_hook (noflash)
if SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM = y:
spi_flash_wrap (noflash)
if ESPTOOLPY_OCT_FLASH = y || ESPTOOLPY_FLASH_MODE_AUTO_DETECT = y:
spi_flash_oct_flash_init (noflash)
if SPI_FLASH_HPM_ON = y:
spi_flash_hpm_enable (noflash)
if ESP_SLEEP_SET_FLASH_DPD = y:
spi_flash_dpd_enable (noflash)
flash_ops: dpd_enter_func (noflash)
flash_ops: dpd_exit_func (noflash)
if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD = y:
flash_ops: esp_mspi_get_io (noflash)
flash_ops: s_mspi_io_num_default (noflash)
[mapping:mspi_timing_tuning_driver]
archive: libesp_mspi.a
entries:
if APP_BUILD_TYPE_PURE_RAM_APP = n:
mspi_timing_tuning (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY = y:
mspi_timing_by_mspi_delay (noflash)
mspi_timing_config (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y:
mspi_timing_by_dqs (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY = y:
mspi_timing_by_flash_delay (noflash)
if SOC_MEMSPI_TIMING_TUNING_BY_DQS = y || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY = y:
mspi_timing_config (noflash)

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -106,10 +106,10 @@ esp_err_t esp_mspi_register_isr(mspi_isr_t *isr)
if (!s_intr_handle) {
ret = esp_intr_alloc(mspi_hw_info.instances[MSPI_TIMING_LL_MSPI_ID_0].irq,
MSPI_ISR_FLAGS,
mspi_isr_handler,
NULL,
&s_intr_handle);
MSPI_ISR_FLAGS,
mspi_isr_handler,
NULL,
&s_intr_handle);
ESP_RETURN_ON_ERROR(ret, TAG, "Failed to allocate MSPI flash interrupt");

View File

@@ -346,7 +346,6 @@ static void s_do_tuning(uint8_t *reference_data, mspi_timing_config_t *config, b
}
#endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
/*------------------------------------------------------------------------------
* FLASH Timing Tuning
*----------------------------------------------------------------------------*/
@@ -395,7 +394,6 @@ void mspi_timing_flash_tuning(void)
}
#endif //MSPI_TIMING_FLASH_NEEDS_TUNING
/*------------------------------------------------------------------------------
* PSRAM Timing Tuning
*----------------------------------------------------------------------------*/
@@ -480,7 +478,6 @@ void mspi_timing_psram_tuning(void)
}
#endif //MSPI_TIMING_PSRAM_NEEDS_TUNING
/*------------------------------------------------------------------------------
* APIs to make SPI0 (and SPI1) FLASH work for high/low freq
*----------------------------------------------------------------------------*/
@@ -621,7 +618,6 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down)
#endif
}
/*------------------------------------------------------------------------------
* Early-init MSPI speed switch (see mspi_timing_tuning.h)
*----------------------------------------------------------------------------*/

View File

@@ -126,7 +126,6 @@ ESP_STATIC_ASSERT((MSPI_TIMING_CORE_CLOCK_MHZ == MSPI_TIMING_PSRAM_MODULE_CLOCK)
#define MSPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode)
#define MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(PSRAM, core_clock_mhz, module_clock_mhz, mode)
/**
* Timing Tuning Parameters
*/

View File

@@ -113,7 +113,6 @@ ESP_STATIC_ASSERT((MSPI_TIMING_CORE_CLOCK_MHZ == MSPI_TIMING_FLASH_MODULE_CLOCK)
ESP_STATIC_ASSERT((MSPI_TIMING_CORE_CLOCK_MHZ == MSPI_TIMING_PSRAM_MODULE_CLOCK) || (MSPI_TIMING_CORE_CLOCK_MHZ % (2 * MSPI_TIMING_PSRAM_MODULE_CLOCK) == 0), "PSRAM Mode configuration are not supported");
#endif
//------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------//
#define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \
(mspi_timing_config_t) { .tuning_config_table = MSPI_TIMING_##type##_CONFIG_TABLE_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \
@@ -125,7 +124,6 @@ ESP_STATIC_ASSERT((MSPI_TIMING_CORE_CLOCK_MHZ == MSPI_TIMING_PSRAM_MODULE_CLOCK)
#define MSPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode)
#define MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(PSRAM, core_clock_mhz, module_clock_mhz, mode)
/**
* Timing Tuning Parameters
*/

View File

@@ -27,7 +27,7 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe
assert(freqdiv > 0);
ESP_DRAM_LOGD(TAG, "psram_freq_mhz: %" PRIu32 " mhz, bus clock div: %" PRIu32, psram_freq_mhz, freqdiv);
PERIPH_RCC_ATOMIC() {
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_set_core_clock_div(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv);

View File

@@ -23,7 +23,7 @@
#include "hal/clk_tree_ll.h"
#include "esp_private/mspi_timing_config.h"
#include "esp_private/mspi_timing_by_mspi_delay.h"
#include "bootloader_flash.h"
#include "esp_private/spi_flash_os.h"
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/opi_flash.h"
#if CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR
@@ -116,46 +116,47 @@ static uint32_t spi_timing_config_get_dummy(void)
if (spi_flash_hpm_dummy_adjust()) { // HPM-DC is enabled
const spi_flash_hpm_dummy_conf_t *hpm_dummy = spi_flash_hpm_get_dummy();
switch (mode) {
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return hpm_dummy->qio_dummy - 1;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return hpm_dummy->qout_dummy - 1;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return hpm_dummy->dio_dummy - 1;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return hpm_dummy->dout_dummy - 1;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return hpm_dummy->fastrd_dummy - 1;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return hpm_dummy->qio_dummy - 1;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return hpm_dummy->qout_dummy - 1;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return hpm_dummy->dio_dummy - 1;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return hpm_dummy->dout_dummy - 1;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return hpm_dummy->fastrd_dummy - 1;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
}
} else
#endif
{ // HPM-DC is not enabled
{
// HPM-DC is not enabled
switch (mode) {
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return SPI1_R_QIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return SPI1_R_DIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return SPI1_R_QIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return SPI1_R_DIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
}
}
}
static void s_set_flash_extra_dummy(uint8_t spi_num, uint8_t extra_dummy)
{
if (bootloader_flash_is_octal_mode_enabled()) {
if (spi_flash_is_octal_mode_enabled()) {
mspi_timing_ll_set_octal_flash_extra_dummy(spi_num, extra_dummy);
return;
}
@@ -190,7 +191,7 @@ void mspi_timing_config_flash_set_tuning_regs(const void *configs, uint8_t id)
//-------------------------------------------FLASH Read/Write------------------------------------------//
void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
{
if (bootloader_flash_is_octal_mode_enabled()) {
if (spi_flash_is_octal_mode_enabled()) {
// note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
// but after we change the timing settings, we might not read correct idle status via RDSR.
// so, here we should use a read API that won't check idle status.
@@ -270,13 +271,13 @@ static void s_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
{
#if CONFIG_SPIRAM_MODE_OCT
esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
OPI_PSRAM_SYNC_WRITE, 16,
addr, 32,
OCT_PSRAM_WR_DUMMY_NUM,
buf, len * 8,
NULL, 0,
BIT(1),
false);
OPI_PSRAM_SYNC_WRITE, 16,
addr, 32,
OCT_PSRAM_WR_DUMMY_NUM,
buf, len * 8,
NULL, 0,
BIT(1),
false);
#elif CONFIG_SPIRAM_MODE_QUAD
psram_exec_cmd(1, 0,
QPI_PSRAM_WRITE, 8,
@@ -294,13 +295,13 @@ static void s_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
#if CONFIG_SPIRAM_MODE_OCT
mspi_timing_ll_clear_fifo(1);
esp_rom_opiflash_exec_cmd(1, ESP_ROM_SPIFLASH_OPI_DTR_MODE,
OPI_PSRAM_SYNC_READ, 16,
addr, 32,
OCT_PSRAM_RD_DUMMY_NUM,
NULL, 0,
buf, len * 8,
BIT(1),
false);
OPI_PSRAM_SYNC_READ, 16,
addr, 32,
OCT_PSRAM_RD_DUMMY_NUM,
NULL, 0,
buf, len * 8,
BIT(1),
false);
#elif CONFIG_SPIRAM_MODE_QUAD
psram_exec_cmd(1, 0,
QPI_PSRAM_FAST_READ, 8,
@@ -331,7 +332,7 @@ static void s_psram_execution(uint8_t *buf, uint32_t addr, uint32_t len, bool is
void mspi_timing_config_psram_prepare_reference_data(uint8_t *buf, uint32_t len)
{
assert((len == MSPI_TIMING_TEST_DATA_LEN) && (len % 4 == 0));
for (int i=0; i < len/4; i++) {
for (int i = 0; i < len / 4; i++) {
((uint32_t *)buf)[i] = 0xa5ff005a;
}
}
@@ -371,7 +372,7 @@ static bool get_working_pll_freq(const uint8_t *reference_data, bool is_flash, u
clk_ll_bbpll_set_frequency_for_mspi_tuning(xtal_freq, pll_mhz_tuning, ((pll_mhz_tuning / 4) - 4), 9);
//wait calibration done
while(!clk_ll_bbpll_calibration_is_done());
while (!clk_ll_bbpll_calibration_is_done());
//bbpll calibration stop
clk_ll_bbpll_calibration_stop();
@@ -406,7 +407,7 @@ static bool get_working_pll_freq(const uint8_t *reference_data, bool is_flash, u
//set pll
clk_ll_bbpll_set_config(previous_config.source_freq_mhz, xtal_freq);
//wait calibration done
while(!clk_ll_bbpll_calibration_is_done());
while (!clk_ll_bbpll_calibration_is_done());
//bbpll calibration stop
clk_ll_bbpll_calibration_stop();
@@ -535,7 +536,7 @@ static uint32_t s_select_best_tuning_config_str(const mspi_timing_config_t *conf
//STR best point scheme
uint32_t best_point;
if (consecutive_length <= 2|| consecutive_length >= 5) {
if (consecutive_length <= 2 || consecutive_length >= 5) {
//tuning is FAIL, select default point, and generate a warning
best_point = configs->default_config_id;
ESP_DRAM_LOGW(TAG, "tuning fail, best point is fallen back to index %"PRIu32"", best_point);
@@ -595,7 +596,6 @@ void mspi_timing_psram_set_best_tuning_config(const void *configs, uint8_t best_
s_psram_best_timing_tuning_config = ((const mspi_timing_config_t *)configs)->tuning_config_table[best_id];
}
/*-------------------------------------------------------------------------------------------------
* Best Timing Tuning Params Clear / Set
*-------------------------------------------------------------------------------------------------*/
@@ -637,7 +637,6 @@ void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi)
}
#endif //#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
/*-------------------------------------------------------------------------------------------------
* To let upper lay (spi_flash_timing_tuning.c) to know the necessary timing registers
*-------------------------------------------------------------------------------------------------*/
@@ -730,8 +729,12 @@ static esp_err_t temperature_sensor_get_celsius_filtered(int16_t *temp_filtered)
for (uint8_t idx = 0; idx < filter_window_len; idx++) {
temp_arr[idx] = temp_sensor_get_raw_value(NULL);
// record the index of the max and min temperature value
if (temp_arr[idx] > temp_arr[temp_max_idx]) temp_max_idx = idx;
if (temp_arr[idx] < temp_arr[temp_min_idx]) temp_min_idx = idx;
if (temp_arr[idx] > temp_arr[temp_max_idx]) {
temp_max_idx = idx;
}
if (temp_arr[idx] < temp_arr[temp_min_idx]) {
temp_min_idx = idx;
}
temp_sum += temp_arr[idx];
}
// remove the max and min temperature value

View File

@@ -83,7 +83,6 @@ extern "C" {
#define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 80)
#endif
/**
* @note Define A feasible core clock below: MSPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ
*/
@@ -138,7 +137,6 @@ extern "C" {
#define MSPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240
#endif //PSRAM 120M DTR
//------------------------------------------Determine the Core Clock-----------------------------------------------//
/**
* @note
@@ -177,7 +175,6 @@ ESP_STATIC_ASSERT(CHECK_POWER_OF_2(MSPI_TIMING_CORE_CLOCK_MHZ / MSPI_TIMING_FLAS
ESP_STATIC_ASSERT(CHECK_POWER_OF_2(MSPI_TIMING_CORE_CLOCK_MHZ / MSPI_TIMING_PSRAM_MODULE_CLOCK), "FLASH and PSRAM Mode configuration are not supported");
#endif
//------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------//
#define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \
(mspi_timing_config_t) { .tuning_config_table = MSPI_TIMING_##type##_CONFIG_TABLE_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \
@@ -189,8 +186,6 @@ ESP_STATIC_ASSERT(CHECK_POWER_OF_2(MSPI_TIMING_CORE_CLOCK_MHZ / MSPI_TIMING_PSRA
#define MSPI_TIMING_FLASH_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(FLASH, core_clock_mhz, module_clock_mhz, mode)
#define MSPI_TIMING_PSRAM_GET_TUNING_CONFIG(core_clock_mhz, module_clock_mhz, mode) _GET_TUNING_CONFIG(PSRAM, core_clock_mhz, module_clock_mhz, mode)
/**
* Timing Tuning Parameters
*/
@@ -244,7 +239,6 @@ ESP_STATIC_ASSERT(CHECK_POWER_OF_2(MSPI_TIMING_CORE_CLOCK_MHZ / MSPI_TIMING_PSRA
#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12
#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 2
//PSRAM: core clock 240M, module clock 120M, DTR mode
#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE {{0, 0, 0}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 1, 4}, {1, 0, 3}, {4, 0, 4}, {0, 0, 3}, {4, 1, 5}}
#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 14

View File

@@ -27,7 +27,7 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe
assert(freqdiv > 0);
ESP_DRAM_LOGD(TAG, "psram_freq_mhz: %" PRIu32 " mhz, bus clock div: %" PRIu32, psram_freq_mhz, freqdiv);
PERIPH_RCC_ATOMIC() {
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
psram_ctrlr_ll_set_core_clock_div(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv);

View File

@@ -28,7 +28,6 @@ extern "C" {
#define IS_DDR 1
#define IS_SDR (!IS_DDR)
/*-------------------------------------------------------------------------------------------------
* Timing Required APIs
*-------------------------------------------------------------------------------------------------*/

View File

@@ -22,7 +22,6 @@
extern "C" {
#endif
#if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#define IS_DDR 1
@@ -147,7 +146,6 @@ uint32_t mspi_timing_config_get_flash_fdummy_rin(void);
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#ifdef __cplusplus
}
#endif

View File

@@ -28,7 +28,6 @@ extern "C" {
#define IS_DDR 1
#define IS_SDR (!IS_DDR)
#if MSPI_TIMING_FLASH_NEEDS_TUNING || MSPI_TIMING_PSRAM_NEEDS_TUNING
/*-------------------------------------------------------------------------------------------------
* Timing Required APIs
@@ -109,7 +108,6 @@ void mspi_timing_config_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t l
*/
void mspi_timing_config_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len);
/*-------------------------------------------------------------------------------------------------
* Best Timing Tuning Params Selection
*-------------------------------------------------------------------------------------------------*/
@@ -157,7 +155,6 @@ uint32_t mspi_timing_psram_select_best_tuning_config(const void *configs, uint32
*/
void mspi_timing_psram_set_best_tuning_config(const void *configs, uint8_t best_id);
/*-------------------------------------------------------------------------------------------------
* Best Timing Tuning Params Clear / Set
*-------------------------------------------------------------------------------------------------*/
@@ -197,7 +194,6 @@ void mspi_timing_psram_config_clear_tuning_regs(bool control_both_mspi);
*/
void mspi_timing_psram_config_set_tuning_regs(bool control_both_mspi);
/*-------------------------------------------------------------------------------------------------
* APIs for coordination with ESP Flash driver
*-------------------------------------------------------------------------------------------------*/

View File

@@ -58,7 +58,6 @@ typedef struct {
} mspi_timing_config_t;
#endif //#if SOC_MEMSPI_TIMING_TUNING_BY_DQS || SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY
#if SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY
/**
* MSPI timing tuning registers.

View File

@@ -161,37 +161,37 @@ static uint32_t spi_timing_config_get_dummy(void)
if (spi_flash_hpm_dummy_adjust()) { // HPM-DC is enabled
const spi_flash_hpm_dummy_conf_t *hpm_dummy = spi_flash_hpm_get_dummy();
switch (mode) {
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return hpm_dummy->qio_dummy - 1;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return hpm_dummy->qout_dummy - 1;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return hpm_dummy->dio_dummy - 1;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return hpm_dummy->dout_dummy - 1;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return hpm_dummy->fastrd_dummy - 1;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return hpm_dummy->qio_dummy - 1;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return hpm_dummy->qout_dummy - 1;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return hpm_dummy->dio_dummy - 1;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return hpm_dummy->dout_dummy - 1;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return hpm_dummy->fastrd_dummy - 1;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
}
} else { // HPM-DC is not enabled
switch (mode) {
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return SPI1_R_QIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return SPI1_R_DIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
case MSPI_TIMING_LL_FLASH_QIO_MODE:
return SPI1_R_QIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_QUAD_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DIO_MODE:
return SPI1_R_DIO_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_DUAL_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_FAST_MODE:
return SPI1_R_FAST_DUMMY_CYCLELEN;
case MSPI_TIMING_LL_FLASH_SLOW_MODE:
return 0;
default:
abort();
}
}
}

View File

@@ -24,8 +24,8 @@
#include "hal/psram_ctrlr_ll.h"
#include "esp_private/mspi_timing_config.h"
#include "esp_private/mspi_timing_by_mspi_delay.h"
#include "esp_private/spi_flash_os.h"
#include "mspi_timing_tuning_configs.h"
#include "bootloader_flash.h"
#define QPI_PSRAM_FAST_READ 0XEB
#define QPI_PSRAM_WRITE 0X38
@@ -90,7 +90,7 @@ void mspi_timing_config_flash_read_data(uint8_t *buf, uint32_t addr, uint32_t le
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO && CONFIG_SPI_FLASH_HPM_ON
g_rom_spiflash_dummy_len_plus[1] = 4;
#endif
if (bootloader_flash_is_octal_mode_enabled()) {
if (spi_flash_is_octal_mode_enabled()) {
// note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state.
// but after we change the timing settings, we might not read correct idle status via RDSR.
// so, here we should use a read API that won't check idle status.
@@ -156,13 +156,13 @@ void mspi_timing_config_psram_set_tuning_regs(const void *configs, uint8_t id)
//-------------------------------------------PSRAM Read/Write------------------------------------------//
static void psram_exec_cmd(int mspi_id, psram_cmd_mode_t mode,
uint32_t cmd, int cmd_bit_len,
uint32_t addr, int addr_bit_len,
int dummy_bits,
uint8_t* mosi_data, int mosi_bit_len,
uint8_t* miso_data, int miso_bit_len,
uint32_t cs_mask,
bool is_write_erase_operation)
uint32_t cmd, int cmd_bit_len,
uint32_t addr, int addr_bit_len,
int dummy_bits,
uint8_t* mosi_data, int mosi_bit_len,
uint8_t* miso_data, int miso_bit_len,
uint32_t cs_mask,
bool is_write_erase_operation)
{
esp_rom_spiflash_read_mode_t rd_mode = (mode == PSRAM_HAL_CMD_QPI) ? ESP_ROM_SPIFLASH_QIO_MODE : ESP_ROM_SPIFLASH_SLOWRD_MODE;
@@ -194,15 +194,15 @@ static void s_psram_write_data(uint8_t *buf, uint32_t addr, uint32_t len)
uint8_t dummy_len = 0;
uint8_t addr_len = 24;
psram_cmd_mode_t spi_mode = PSRAM_HAL_CMD_QPI;
for (uint32_t idx= 0; idx < len / FIFO_SIZE_BYTE; idx++) {
for (uint32_t idx = 0; idx < len / FIFO_SIZE_BYTE; idx++) {
psram_exec_cmd(mspi_id, spi_mode,
cmd, cmd_len,
addr + idx * FIFO_SIZE_BYTE, addr_len,
dummy_len,
buf + idx * FIFO_SIZE_BYTE, FIFO_SIZE_BYTE * 8,
NULL, 0,
PSRAM_LL_CS_SEL,
false);
cmd, cmd_len,
addr + idx * FIFO_SIZE_BYTE, addr_len,
dummy_len,
buf + idx * FIFO_SIZE_BYTE, FIFO_SIZE_BYTE * 8,
NULL, 0,
PSRAM_LL_CS_SEL,
false);
}
}
@@ -219,15 +219,15 @@ static void s_psram_read_data(uint8_t *buf, uint32_t addr, uint32_t len)
uint8_t dummy_len = QPI_PSRAM_FAST_READ_DUMMY;
uint8_t addr_len = 24;
psram_cmd_mode_t spi_mode = PSRAM_HAL_CMD_QPI;
for (uint32_t idx = 0; idx < len/FIFO_SIZE_BYTE; idx++) {
for (uint32_t idx = 0; idx < len / FIFO_SIZE_BYTE; idx++) {
psram_exec_cmd(mspi_id, spi_mode,
cmd, cmd_len,
addr + idx*FIFO_SIZE_BYTE, addr_len,
dummy_len,
NULL, 0,
buf + idx*FIFO_SIZE_BYTE, FIFO_SIZE_BYTE * 8,
PSRAM_LL_CS_SEL,
false);
cmd, cmd_len,
addr + idx * FIFO_SIZE_BYTE, addr_len,
dummy_len,
NULL, 0,
buf + idx * FIFO_SIZE_BYTE, FIFO_SIZE_BYTE * 8,
PSRAM_LL_CS_SEL,
false);
}
}

View File

@@ -9,9 +9,9 @@
#include "esp_err.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_rom_sys.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash_chips/spi_flash_chip_generic.h"
#include "esp_private/spi_flash_os.h"
/*******************************************************************************
* Flash deep power-down mode.
@@ -46,6 +46,20 @@ __attribute__((unused)) const static char *DPD_TAG = "flash DPD";
* TODO: PM-623
*/
static spi_flash_dpd_funcs_t s_dpd_funcs = {
.enter_dpd = NULL,
.exit_dpd = NULL,
};
esp_err_t spi_flash_dpd_register_funcs(spi_flash_dpd_funcs_t *dpd_funcs)
{
if (dpd_funcs == NULL) {
return ESP_ERR_INVALID_ARG;
}
s_dpd_funcs = *dpd_funcs;
return ESP_OK;
}
uint32_t spi_flash_dpd_get_enter_duration(void)
{
#ifndef CONFIG_ESP_SLEEP_SPI_FLASH_ENTER_DPD_MODE_DELAY
@@ -64,7 +78,11 @@ uint32_t spi_flash_dpd_get_exit_duration(void)
static esp_err_t spi_flash_enter_dpd(bool wait_delay)
{
esp_err_t ret = spi_flash_hal_enter_dpd_mode(esp_flash_default_chip->host);
if (s_dpd_funcs.enter_dpd == NULL) {
ESP_EARLY_LOGE(DPD_TAG, "DPD enter function not registered");
return ESP_ERR_INVALID_STATE;
}
esp_err_t ret = s_dpd_funcs.enter_dpd();
if (wait_delay) {
esp_rom_delay_us(spi_flash_dpd_get_enter_duration());
}
@@ -74,7 +92,11 @@ static esp_err_t spi_flash_enter_dpd(bool wait_delay)
static esp_err_t spi_flash_exit_dpd(bool wait_delay)
{
esp_err_t ret = spi_flash_hal_exit_dpd_mode(esp_flash_default_chip->host);
if (s_dpd_funcs.exit_dpd == NULL) {
ESP_EARLY_LOGE(DPD_TAG, "DPD exit function not registered");
return ESP_ERR_INVALID_STATE;
}
esp_err_t ret = s_dpd_funcs.exit_dpd();
if (wait_delay) {
esp_rom_delay_us(spi_flash_dpd_get_exit_duration());
}

View File

@@ -10,13 +10,14 @@
#include "esp_log.h"
#include "esp_rom_sys.h"
#include "esp_rom_spiflash.h"
#include "esp_flash_chips/spi_flash_defs.h"
#include "spi_flash_defs.h"
#include "esp_flash_chips/spi_flash_override.h"
// TODO: These dependencies will be removed after remove bootloader_flash to G0.IDF-4609
#include "bootloader_flash_override.h"
#include "bootloader_flash_priv.h"
#include "esp_private/bootloader_flash_internal.h"
#define CMD_HPMEN 0xA3 /* Enable High Performance mode on flash */
/*******************************************************************************
* Flash high speed performance mode.
@@ -38,7 +39,7 @@
* It mean that the flash not running under frequency requires HPM. spi_flash_enable_high_performance_mode() still
* called because caller shouldn't take care of the frequency.
*
* - bootloader_flash_is_octal_mode_enabled() == true:
* - spi_flash_is_octal_mode_enabled() == true:
* This is possible when `CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT` selected
*
* Octal Flash for now all support 120M. No need to enable HPM. The file is compiled, but will not actually run
@@ -127,7 +128,7 @@ static void spi_flash_enable_high_performance_send_cmd(void)
*/
static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void)
{
if((bootloader_read_status_8b_rdsr3() & (1 << 4)) == 0) {
if ((bootloader_read_status_8b_rdsr3() & (1 << 4)) == 0) {
return ESP_FAIL;
}
return ESP_OK;
@@ -208,7 +209,7 @@ static void spi_flash_turn_high_performance_reconfig_dummy(void)
*/
static esp_err_t spi_flash_high_performance_check_dummy_sr(void)
{
if((bootloader_read_status_8b_rdsr3() & 0x03) == 0) {
if ((bootloader_read_status_8b_rdsr3() & 0x03) == 0) {
return ESP_FAIL;
}
return ESP_OK;
@@ -223,7 +224,6 @@ static void spi_flash_hpm_get_dummy_xmc(spi_flash_hpm_dummy_conf_t *dummy_conf)
dummy_conf->fastrd_dummy = SPI_FLASH_FASTRD_DUMMY_BITLEN;
}
/**
* @brief Probe the chip whether adjust dummy (bit3,4) to enable HPM mode. Take XMC as an example:
* Adjust dummy bits to enable HPM mode of the flash. If XMC works under 80MHz, the dummy bits
@@ -281,7 +281,7 @@ static void spi_flash_turn_high_performance_dummy_bit3_4(void)
*/
static esp_err_t spi_flash_high_performance_check_dummy_bit3_4(void)
{
if((bootloader_read_status_8b_rdsr3() & 0x18) == 0) {
if ((bootloader_read_status_8b_rdsr3() & 0x18) == 0) {
return ESP_FAIL;
}
return ESP_OK;

View File

@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* Stub for spi_flash_is_octal_mode_enabled() when building for non-OS contexts
* (bootloader, TEE, PURE_RAM_APP). Full flash_ops.c is not built there, but
* esp_hw_support may still reference this symbol; returning false is safe.
*/
#include <stdbool.h>
bool spi_flash_is_octal_mode_enabled(void)
{
return false;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -13,13 +13,15 @@
#include "esp_rom_spiflash.h"
#include "rom/spi_flash.h"
#include "esp_flash_chips/spi_flash_defs.h"
#include "esp_flash_chips/spi_flash_override.h"
#include "esp_private/spi_flash_os.h"
// TODO: These dependencies will be removed after remove bootloader_flash to G0.IDF-4609
#include "bootloader_flash_override.h"
#include "bootloader_flash_priv.h"
#include "esp_private/bootloader_flash_internal.h"
#define CMD_WRAP 0x77
#define CMD_BURST_RD 0xC0
/***********************************************************************************
* Flash wrap feature (also called burst read on some flash chips)
@@ -69,7 +71,7 @@ esp_err_t spi_flash_wrap_probe_c0(uint32_t flash_id)
*/
esp_err_t spi_flash_wrap_enable_c0(spi_flash_wrap_size_t wrap_size)
{
uint8_t wrap_code = (uint8_t) (__builtin_ctz(wrap_size) - 3);
uint8_t wrap_code = (uint8_t)(__builtin_ctz(wrap_size) - 3);
bootloader_flash_execute_command_common(CMD_BURST_RD, 0, 0, 0, 8, wrap_code, 0);
return ESP_OK;
}
@@ -87,7 +89,7 @@ esp_err_t spi_flash_wrap_enable_c0(spi_flash_wrap_size_t wrap_size)
*/
esp_err_t spi_flash_wrap_enable_77(spi_flash_wrap_size_t wrap_size)
{
uint8_t wrap_code = (uint8_t) (((__builtin_ctz(wrap_size) - 3) * 2) << 4);
uint8_t wrap_code = (uint8_t)(((__builtin_ctz(wrap_size) - 3) * 2) << 4);
// According to the special format, we need enable QIO_FWRITE for command 77h and clear it after this command is done.
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_FWRITE_QIO);
bootloader_flash_execute_command_common(CMD_WRAP, 0, 0, 6, 8, wrap_code, 0);

View File

@@ -0,0 +1,20 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/esp_mspi/test_apps/mspi:
depends_components:
- esp_mspi
- esp_hal_mspi
- spi_flash
- esp_psram
disable:
- if: IDF_TARGET not in ["esp32s3", "esp32p4", "esp32c61", "esp32c5", "esp32s31"]
- if: CONFIG_NAME in ["generic_timing_tuning_log_safe", "generic_timing_tuning_xip"] and IDF_TARGET in ["esp32s31"]
- if: CONFIG_NAME == "120sdr_120sdr" and IDF_TARGET in ["esp32s3", "esp32p4", "esp32s31"]
components/esp_mspi/test_apps/no_flash_delay:
depends_components:
- esp_mspi
- esp_hal_mspi
disable:
- if: IDF_TARGET not in ["esp32c3"]
reason: Testing on a single target is sufficient

View File

@@ -7,5 +7,5 @@ set(srcs
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity esp_timer spi_flash esp_partition esp_hal_mspi
PRIV_REQUIRES unity esp_timer spi_flash esp_partition esp_hal_mspi esp_mspi
WHOLE_ARCHIVE)

View File

@@ -0,0 +1,3 @@
dependencies:
test_utils:
path: ${IDF_PATH}/tools/test_apps/components/test_utils

View File

@@ -68,7 +68,6 @@ TEST_CASE("MSPI: Test_SPI0_PSRAM", "[mspi]")
}
#endif
//-----------------------------------------SPI1 FLASH TEST-----------------------------------------------//
#define SPI1_FLASH_TEST_LEN 512
#define SECTOR_LEN 4096
@@ -82,7 +81,7 @@ static const esp_partition_t *get_test_flash_partition(void)
{
/* This finds "flash_test" partition defined in partition_table_unit_test_app.csv */
const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
ESP_PARTITION_SUBTYPE_ANY, "flash_test");
ESP_PARTITION_SUBTYPE_ANY, "flash_test");
assert(result != NULL); /* means partition table set wrong */
return result;
}
@@ -119,7 +118,6 @@ TEST_CASE("MSPI: Test_SPI1_Flash", "[mspi]")
printf(DRAM_STR("----------SPI1 Flash Test Success----------\n\n"));
}
//-----------------------------------------SPI0 FLASH TEST-----------------------------------------------//
#define SPI0_FLASH_TEST_LEN 32
#define SPI0_FLASH_TEST_BUF {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \
@@ -145,7 +143,6 @@ TEST_CASE("MSPI: Test_SPI0_Flash", "[mspi]")
printf(DRAM_STR("----------SPI0 Flash Test Success----------\n\n"));
}
/*---------------------------------------------------------------
XIP + PSRAM Stack + Flash API
---------------------------------------------------------------*/

View File

@@ -8,7 +8,6 @@
#include "esp_timer.h"
#include "esp_private/mspi_timing_tuning.h"
static void sorted_array_insert(uint32_t *array, uint32_t *size, uint32_t item)
{
uint32_t pos;

Some files were not shown because too many files have changed in this diff Show More