mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
refactor(mspi): move esp_mspi_align and mspi_mem_barrier to esp_mspi
This commit is contained in:
@@ -9,9 +9,13 @@ if(${target} STREQUAL "linux")
|
||||
endif()
|
||||
|
||||
if(non_os_build OR CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
|
||||
set(priv_requires bootloader_support soc esp_hal_gpio)
|
||||
# efuse is required by esp_mspi_align.c to query the flash encryption state
|
||||
set(priv_requires bootloader_support soc esp_hal_gpio efuse)
|
||||
set(requires hal esp_hal_mspi)
|
||||
set(srcs "spi_flash_wrap.c" "spi_flash_os_tee_stub.c")
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "esp_mspi_align/esp_mspi_align.c")
|
||||
endif()
|
||||
if(ESP_TEE_BUILD)
|
||||
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
|
||||
list(APPEND srcs "mspi_timing_tuning/mspi_timing_tuning.c")
|
||||
@@ -27,10 +31,13 @@ if(non_os_build OR CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(priv_requires bootloader_support soc esp_hal_gpio esp_mm)
|
||||
# efuse is required by esp_mspi_align.c to query the flash encryption state
|
||||
set(priv_requires bootloader_support soc esp_hal_gpio esp_mm efuse)
|
||||
set(requires hal esp_hal_mspi)
|
||||
|
||||
set(srcs "flash_brownout_hook.c" "cache_utils.c" "flash_ops.c" "spi_flash_wrap.c")
|
||||
set(srcs "flash_brownout_hook.c" "cache_utils.c" "flash_ops.c" "spi_flash_wrap.c"
|
||||
"esp_mspi_align/esp_mspi_align.c"
|
||||
"mspi_mem_barrier/mspi_mem_barrier.c")
|
||||
|
||||
# MSPI0 Octal flash init
|
||||
if(CONFIG_SOC_SPI_MEM_SUPPORT_FLASH_OPI_MODE)
|
||||
@@ -69,13 +76,18 @@ endif()
|
||||
set(include_dirs include
|
||||
"mspi_timing_tuning/include"
|
||||
"mspi_timing_tuning/tuning_scheme_impl/include"
|
||||
"mspi_intr/include")
|
||||
"mspi_intr/include"
|
||||
"esp_mspi_align/include"
|
||||
"mspi_mem_barrier/include")
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}")
|
||||
list(APPEND include_dirs "${target}")
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
|
||||
list(APPEND include_dirs "${target}/include")
|
||||
endif()
|
||||
|
||||
set(ldfragments linker.lf)
|
||||
set(ldfragments "")
|
||||
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
|
||||
list(APPEND ldfragments linker.lf)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
REQUIRES ${requires}
|
||||
@@ -90,7 +102,7 @@ if(NOT non_os_build AND NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)
|
||||
# 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
|
||||
# Force linking init_flash_dpd 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()
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/esp_mspi_align.h"
|
||||
#if CONFIG_SPIRAM
|
||||
#include "esp_psram.h"
|
||||
#endif /* CONFIG_SPIRAM */
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#define MSPI_FLASH_ENC_ALIGNMENT SOC_MEMSPI_ENCRYPTION_ALIGNMENT
|
||||
#define MSPI_PSRAM_ECC_ALIGNMENT SOC_MEMSPI_ENCRYPTION_ALIGNMENT
|
||||
|
||||
size_t esp_mspi_get_alignment(const void *ptr)
|
||||
{
|
||||
size_t alignment = 1;
|
||||
bool generic_query = ptr == NULL;
|
||||
bool __attribute__((unused)) is_psram = esp_ptr_external_ram(ptr);
|
||||
bool is_drom = esp_ptr_in_drom(ptr);
|
||||
bool is_psram_enc = false;
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
is_psram_enc = is_psram && !esp_psram_ptr_is_no_enc(ptr);
|
||||
#endif /* CONFIG_SPIRAM */
|
||||
|
||||
if ((generic_query || is_drom || is_psram_enc) && esp_efuse_is_flash_encryption_enabled()) {
|
||||
alignment = MAX(alignment, MSPI_FLASH_ENC_ALIGNMENT);
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_ECC_ENABLE
|
||||
if (generic_query || is_psram) {
|
||||
alignment = MAX(alignment, MSPI_PSRAM_ECC_ALIGNMENT);
|
||||
}
|
||||
#endif
|
||||
|
||||
return alignment;
|
||||
}
|
||||
|
||||
bool esp_mspi_buffer_alignment_satisfied(const void *ptr, size_t size)
|
||||
{
|
||||
// Zero-length is not a valid MSPI transfer, so it never satisfies the check.
|
||||
if (ptr == NULL || size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t alignment = esp_mspi_get_alignment(ptr);
|
||||
if (alignment <= 1) {
|
||||
return true;
|
||||
}
|
||||
uintptr_t addr = (uintptr_t)ptr;
|
||||
return ((addr & (alignment - 1)) == 0) && ((size & (alignment - 1)) == 0);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get MSPI alignment requirement for an address
|
||||
*
|
||||
* The address is used so future targets can apply different alignment rules to
|
||||
* different MSPI-backed regions. Pass NULL when only the generic external-memory
|
||||
* requirement is needed and no concrete address is available yet.
|
||||
*
|
||||
* @param ptr Buffer pointer in the region to be accessed, or NULL for generic query
|
||||
* @return Required alignment in bytes, or 1 when no extra MSPI alignment is needed
|
||||
*/
|
||||
size_t esp_mspi_get_alignment(const void *ptr);
|
||||
|
||||
/**
|
||||
* @brief Check whether a buffer satisfies MSPI strict alignment requirements
|
||||
*
|
||||
* Returns false when @p ptr is NULL or @p size is 0 (not a valid transfer).
|
||||
* When strict alignment is not required, returns true for any non-empty buffer.
|
||||
* When required, both @p ptr and @p size must be aligned to the rule returned by
|
||||
* @ref esp_mspi_get_alignment for that address.
|
||||
*
|
||||
* @param ptr Buffer pointer
|
||||
* @param size Transfer size in bytes
|
||||
* @return true if alignment requirements are satisfied
|
||||
*/
|
||||
bool esp_mspi_buffer_alignment_satisfied(const void *ptr, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,38 +1,42 @@
|
||||
[mapping:esp_mspi]
|
||||
archive: libesp_mspi.a
|
||||
entries:
|
||||
if APP_BUILD_TYPE_PURE_RAM_APP = n:
|
||||
flash_brownout_hook (noflash)
|
||||
flash_brownout_hook (noflash)
|
||||
|
||||
if SPI_FLASH_PLACE_FUNCTIONS_IN_IRAM = y:
|
||||
spi_flash_wrap (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 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 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 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)
|
||||
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:esp_mspi_align]
|
||||
archive: libesp_mspi.a
|
||||
entries:
|
||||
esp_mspi_align:esp_mspi_get_alignment (noflash)
|
||||
esp_mspi_align:esp_mspi_buffer_alignment_satisfied (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)
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the MSPI memory barrier workaround
|
||||
*
|
||||
* On targets affected by the MSPI memory barrier hardware issue, this allocates the
|
||||
* dummy cacheline used by @ref esp_psram_mspi_mb to force a cache writeback/fence. On
|
||||
* other targets this is a no-op.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise an error code
|
||||
*/
|
||||
esp_err_t esp_psram_mspi_mb_init(void);
|
||||
|
||||
/**
|
||||
* @brief MSPI memory barrier
|
||||
*
|
||||
* Some targets need this workaround after a DMA transfer into PSRAM to make sure the
|
||||
* data is visible to the CPU. This is a no-op on targets that don't need the workaround.
|
||||
*/
|
||||
void esp_psram_mspi_mb(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_cache.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_private/mspi_mem_barrier.h"
|
||||
|
||||
#define MSPI_MEM_BARRIER_WORKAROUND ((CONFIG_IDF_TARGET_ESP32C5 && CONFIG_ESP32C5_REV_MIN_FULL < 102) || (CONFIG_IDF_TARGET_ESP32C61 && CONFIG_ESP32C61_REV_MIN_FULL < 101))
|
||||
|
||||
__attribute__((unused)) ESP_LOG_ATTR_TAG_DRAM(TAG, "mspi_mem_barrier");
|
||||
|
||||
#if MSPI_MEM_BARRIER_WORKAROUND
|
||||
static void *s_psram_mb_dummy_cacheline; //dummy cacheline for cache memory barrier
|
||||
#endif
|
||||
|
||||
esp_err_t esp_psram_mspi_mb_init(void)
|
||||
{
|
||||
#if MSPI_MEM_BARRIER_WORKAROUND
|
||||
s_psram_mb_dummy_cacheline = heap_caps_calloc(1, CONFIG_CACHE_L1_CACHE_LINE_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED);
|
||||
if (!s_psram_mb_dummy_cacheline) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to allocate dummy cacheline for PSRAM memory barrier!");
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_psram_mspi_mb(void)
|
||||
{
|
||||
#if MSPI_MEM_BARRIER_WORKAROUND
|
||||
if (s_psram_mb_dummy_cacheline) {
|
||||
uint32_t *p = (uint32_t *)s_psram_mb_dummy_cacheline;
|
||||
*p = (*p + 1) % UINT32_MAX;
|
||||
__attribute__((unused)) esp_err_t ret = ESP_FAIL;
|
||||
ret = esp_cache_msync(s_psram_mb_dummy_cacheline, sizeof(uint32_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); //malloc is aligned, no need to writeback all
|
||||
assert(ret == ESP_OK);
|
||||
asm volatile("fence");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user