From 532b4332460ef7a01061628ce83e61bef1ade934 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Fri, 21 Aug 2026 11:16:07 +0800 Subject: [PATCH] fix(build_system): cleaned up esp_psram dependencies Also moved mspi_mb functionality to esp_hw_support together with other mspi functionality --- components/esp_driver_dma/CMakeLists.txt | 4 -- components/esp_driver_dma/src/esp_dma_utils.c | 2 +- components/esp_driver_spi/CMakeLists.txt | 2 +- .../esp_driver_spi/src/gpspi/spi_common.c | 2 +- .../test_apps/master/main/CMakeLists.txt | 3 +- .../test_apps/slave/main/CMakeLists.txt | 3 +- components/esp_driver_uart/CMakeLists.txt | 2 +- components/esp_driver_uart/src/uhci.c | 6 ++- components/esp_hw_support/CMakeLists.txt | 4 +- .../include/esp_private/mspi_mem_barrier.h | 37 +++++++++++++++ .../mspi/mspi_mem_barrier/mspi_mem_barrier.c | 47 +++++++++++++++++++ .../include/esp_private/esp_psram_mspi.h | 14 ------ components/esp_psram/system_layer/esp_psram.c | 1 + .../esp_psram/system_layer/esp_psram_mspi.c | 32 ------------- components/esp_system/CMakeLists.txt | 10 +++- .../test_apps/flash_wl/main/CMakeLists.txt | 2 +- .../test_apps/sdcard/main/CMakeLists.txt | 2 +- .../spiffs/test_apps/main/CMakeLists.txt | 2 +- components/vfs/test_apps/main/CMakeLists.txt | 2 +- .../simple_sniffer/main/CMakeLists.txt | 2 +- 20 files changed, 115 insertions(+), 64 deletions(-) create mode 100644 components/esp_hw_support/mspi/mspi_mem_barrier/include/esp_private/mspi_mem_barrier.h create mode 100644 components/esp_hw_support/mspi/mspi_mem_barrier/mspi_mem_barrier.c diff --git a/components/esp_driver_dma/CMakeLists.txt b/components/esp_driver_dma/CMakeLists.txt index e3a273635ab..3717cc556fc 100644 --- a/components/esp_driver_dma/CMakeLists.txt +++ b/components/esp_driver_dma/CMakeLists.txt @@ -53,7 +53,3 @@ idf_component_register(SRCS ${srcs} PRIV_REQUIRES esp_mm efuse LDFRAGMENTS "linker.lf" ) - -if(CONFIG_SPIRAM) - idf_component_optional_requires(PRIVATE esp_psram) -endif() diff --git a/components/esp_driver_dma/src/esp_dma_utils.c b/components/esp_driver_dma/src/esp_dma_utils.c index d1ebf4e2c29..6c8b983d619 100644 --- a/components/esp_driver_dma/src/esp_dma_utils.c +++ b/components/esp_driver_dma/src/esp_dma_utils.c @@ -21,7 +21,7 @@ #include "hal/cache_ll.h" #include "esp_cache.h" #if CONFIG_SPIRAM -#include "esp_private/esp_psram_mspi.h" +#include "esp_private/mspi_mem_barrier.h" #endif ESP_LOG_ATTR_TAG(TAG, "dma_utils"); diff --git a/components/esp_driver_spi/CMakeLists.txt b/components/esp_driver_spi/CMakeLists.txt index bad6e382d60..f4a6f3df23b 100644 --- a/components/esp_driver_spi/CMakeLists.txt +++ b/components/esp_driver_spi/CMakeLists.txt @@ -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 esp_psram + PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio spi_flash LDFRAGMENTS "linker.lf" ) diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 40becc45c09..f4b7ea637c5 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -36,7 +36,7 @@ #include "soc/dport_reg.h" #endif #if CONFIG_SPIRAM -#include "esp_private/esp_psram_mspi.h" +#include "esp_private/mspi_mem_barrier.h" #endif #if CONFIG_SPI_MASTER_ISR_IN_IRAM || CONFIG_SPI_SLAVE_ISR_IN_IRAM diff --git a/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt b/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt index 1617e4ac6d0..e376320c828 100644 --- a/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/master/main/CMakeLists.txt @@ -21,6 +21,7 @@ endif() # the component can be registered as WHOLE_ARCHIVE idf_component_register( SRCS ${srcs} - PRIV_REQUIRES esp_driver_spi spi_flash esp_timer esp_driver_gpio esp_mm esp_driver_uart + # esp_psram is required for CONFIG_SPIRAM, used by the release configs + PRIV_REQUIRES esp_driver_spi spi_flash esp_timer esp_driver_gpio esp_mm esp_driver_uart esp_psram WHOLE_ARCHIVE ) diff --git a/components/esp_driver_spi/test_apps/slave/main/CMakeLists.txt b/components/esp_driver_spi/test_apps/slave/main/CMakeLists.txt index 1d2292e4f93..aaca16eead7 100644 --- a/components/esp_driver_spi/test_apps/slave/main/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/slave/main/CMakeLists.txt @@ -10,6 +10,7 @@ set(srcs # the component can be registered as WHOLE_ARCHIVE idf_component_register( SRCS ${srcs} - PRIV_REQUIRES esp_driver_spi spi_flash esp_driver_gpio + # esp_psram is required for CONFIG_SPIRAM, used by the release configs + PRIV_REQUIRES esp_driver_spi spi_flash esp_driver_gpio esp_psram WHOLE_ARCHIVE ) diff --git a/components/esp_driver_uart/CMakeLists.txt b/components/esp_driver_uart/CMakeLists.txt index dea801491c9..59a6485f02b 100644 --- a/components/esp_driver_uart/CMakeLists.txt +++ b/components/esp_driver_uart/CMakeLists.txt @@ -35,7 +35,7 @@ endif() if(${target} STREQUAL "linux") set(priv_requires esp_ringbuf) else() - set(priv_requires esp_pm esp_driver_gpio esp_driver_dma esp_ringbuf esp_mm esp_psram) + set(priv_requires esp_pm esp_driver_gpio esp_driver_dma esp_ringbuf esp_mm) endif() idf_component_register( diff --git a/components/esp_driver_uart/src/uhci.c b/components/esp_driver_uart/src/uhci.c index 0f6442344bb..1c4e6c61f0a 100644 --- a/components/esp_driver_uart/src/uhci.c +++ b/components/esp_driver_uart/src/uhci.c @@ -32,7 +32,9 @@ #include "esp_private/gdma.h" #include "esp_private/esp_dma_utils.h" #include "esp_private/gdma_link.h" -#include "esp_private/esp_psram_mspi.h" +#if CONFIG_SPIRAM +#include "esp_private/mspi_mem_barrier.h" +#endif #include "uhci_private.h" #include "esp_memory_utils.h" #include "esp_cache.h" @@ -142,9 +144,11 @@ static bool uhci_gdma_rx_callback_done(gdma_channel_handle_t dma_chan, gdma_even .flags.totally_received = frame_end, }; +#if CONFIG_SPIRAM if (esp_ptr_external_ram(evt_data.data)) { esp_psram_mspi_mb(); } +#endif // DMA just finished writing the node's buffer. Because the descriptor link is circular, // the same buffer region gets overwritten on every loop. On targets where the buffer is diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index fb96b522ace..73805cead4e 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -17,6 +17,7 @@ set(public_include_dirs "include" "include/soc" "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") if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/include/soc/${target}") @@ -73,7 +74,8 @@ if(NOT non_os_build) "port/${target}/esp_clk_tree.c" "spi_bus_lock.c" "heap_align_hw.c" - "clk_utils.c") + "clk_utils.c" + "mspi/mspi_mem_barrier/mspi_mem_barrier.c") if(CONFIG_SOC_USB_OTG_SUPPORTED) list(APPEND srcs "usb_phy/usb_phy.c") endif() diff --git a/components/esp_hw_support/mspi/mspi_mem_barrier/include/esp_private/mspi_mem_barrier.h b/components/esp_hw_support/mspi/mspi_mem_barrier/include/esp_private/mspi_mem_barrier.h new file mode 100644 index 00000000000..a1db45a6f1e --- /dev/null +++ b/components/esp_hw_support/mspi/mspi_mem_barrier/include/esp_private/mspi_mem_barrier.h @@ -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 diff --git a/components/esp_hw_support/mspi/mspi_mem_barrier/mspi_mem_barrier.c b/components/esp_hw_support/mspi/mspi_mem_barrier/mspi_mem_barrier.c new file mode 100644 index 00000000000..3e1860b2168 --- /dev/null +++ b/components/esp_hw_support/mspi/mspi_mem_barrier/mspi_mem_barrier.c @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#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 +} diff --git a/components/esp_psram/include/esp_private/esp_psram_mspi.h b/components/esp_psram/include/esp_private/esp_psram_mspi.h index c907bac12d7..ec5e8d7d0f4 100644 --- a/components/esp_psram/include/esp_private/esp_psram_mspi.h +++ b/components/esp_psram/include/esp_private/esp_psram_mspi.h @@ -15,8 +15,6 @@ extern "C" { #endif -#define ESP_PSRAM_MSPI_MB_WORKAROUND ((CONFIG_IDF_TARGET_ESP32C5 && CONFIG_ESP32C5_REV_MIN_FULL < 102) || (CONFIG_IDF_TARGET_ESP32C61 && CONFIG_ESP32C61_REV_MIN_FULL < 101)) - /** * @brief Register MSPI PSRAM interrupt * @@ -37,18 +35,6 @@ esp_err_t esp_psram_mspi_register_isr(void); */ esp_err_t esp_psram_mspi_unregister_isr(void); -/** - * @brief Initialize PSRAM MSPI memory barrier - * - * @return ESP_OK on success, otherwise an error code - */ -esp_err_t esp_psram_mspi_mb_init(void); - -/** - * @brief PSRAM MSPI memory barrier - */ -void esp_psram_mspi_mb(void); - #ifdef __cplusplus } #endif diff --git a/components/esp_psram/system_layer/esp_psram.c b/components/esp_psram/system_layer/esp_psram.c index 52b03d1c315..bdef3d5e15f 100644 --- a/components/esp_psram/system_layer/esp_psram.c +++ b/components/esp_psram/system_layer/esp_psram.c @@ -31,6 +31,7 @@ #include "esp_private/esp_mmu_map_private.h" #include "esp_private/esp_psram_impl.h" #include "esp_private/esp_psram_mspi.h" +#include "esp_private/mspi_mem_barrier.h" #include "esp_private/startup_internal.h" #if SOC_SPIRAM_XIP_SUPPORTED #include "esp_private/mmu_psram_flash.h" diff --git a/components/esp_psram/system_layer/esp_psram_mspi.c b/components/esp_psram/system_layer/esp_psram_mspi.c index 0fdedc217a1..25676dc4f83 100644 --- a/components/esp_psram/system_layer/esp_psram_mspi.c +++ b/components/esp_psram/system_layer/esp_psram_mspi.c @@ -13,8 +13,6 @@ #include "esp_log.h" #include "esp_check.h" #include "esp_intr_alloc.h" -#include "esp_cache.h" -#include "esp_heap_caps.h" #include "hal/mspi_ll.h" #include "hal/mspi_periph.h" #include "esp_private/mspi_intr.h" @@ -136,33 +134,3 @@ esp_err_t esp_psram_mspi_unregister_isr(void) } #endif //#if PSRAM_CTRLR_LL_INTR_EVENT_SUPPORTED #endif //#if CONFIG_SPIRAM - -#if ESP_PSRAM_MSPI_MB_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 ESP_PSRAM_MSPI_MB_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 ESP_PSRAM_MSPI_MB_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 -} diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index e0824a29aef..1626078a251 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -195,7 +195,15 @@ endif() if(NOT BOOTLOADER_BUILD) if(CONFIG_SPIRAM) - idf_component_optional_requires(PRIVATE esp_psram) + if(IDF_BUILD_V2) + # esp_psram is not required by any component unconditionally, so nothing else + # brings it into the build. Include it here, so that PSRAM support (and its + # startup hook) is part of any build which enables CONFIG_SPIRAM. + idf_component_include(esp_psram) + target_link_libraries(${COMPONENT_TARGET} PRIVATE idf::esp_psram) + else() + idf_component_optional_requires(PRIVATE esp_psram) + endif() endif() endif() diff --git a/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt b/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt index f6501bda48f..11c6dfdcec9 100644 --- a/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt +++ b/components/fatfs/test_apps/flash_wl/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "test_fatfs_flash_wl.c" "test_fatfs_small_partition.c" INCLUDE_DIRS "." - PRIV_REQUIRES unity spi_flash fatfs vfs test_fatfs_common + PRIV_REQUIRES unity spi_flash fatfs vfs test_fatfs_common esp_psram WHOLE_ARCHIVE) diff --git a/components/fatfs/test_apps/sdcard/main/CMakeLists.txt b/components/fatfs/test_apps/sdcard/main/CMakeLists.txt index f6bd337523a..831034a7c52 100644 --- a/components/fatfs/test_apps/sdcard/main/CMakeLists.txt +++ b/components/fatfs/test_apps/sdcard/main/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register(SRCS "test_fatfs_sdcard_main.c" "test_fatfs_sdspi.c" INCLUDE_DIRS "." - PRIV_REQUIRES unity fatfs vfs sdmmc test_fatfs_common esp_timer + PRIV_REQUIRES unity fatfs vfs sdmmc test_fatfs_common esp_timer esp_psram WHOLE_ARCHIVE) if(CONFIG_SOC_SDMMC_HOST_SUPPORTED) diff --git a/components/spiffs/test_apps/main/CMakeLists.txt b/components/spiffs/test_apps/main/CMakeLists.txt index e01b34ebe7f..e98b5b5f417 100644 --- a/components/spiffs/test_apps/main/CMakeLists.txt +++ b/components/spiffs/test_apps/main/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRCS test_spiffs.c PRIV_INCLUDE_DIRS . - PRIV_REQUIRES spiffs unity vfs + PRIV_REQUIRES spiffs unity vfs esp_psram WHOLE_ARCHIVE ) diff --git a/components/vfs/test_apps/main/CMakeLists.txt b/components/vfs/test_apps/main/CMakeLists.txt index 5f1f58399c8..18d2ee98635 100644 --- a/components/vfs/test_apps/main/CMakeLists.txt +++ b/components/vfs/test_apps/main/CMakeLists.txt @@ -9,6 +9,6 @@ set(src "test_app_main.c" "test_vfs_access.c" idf_component_register(SRCS ${src} PRIV_INCLUDE_DIRS . ../include PRIV_REQUIRES test_utils vfs fatfs spiffs unity lwip wear_levelling cmock - esp_driver_gptimer esp_driver_uart + esp_driver_gptimer esp_driver_uart esp_psram WHOLE_ARCHIVE ) diff --git a/examples/network/simple_sniffer/main/CMakeLists.txt b/examples/network/simple_sniffer/main/CMakeLists.txt index ad9166bc609..a9178f8bff3 100644 --- a/examples/network/simple_sniffer/main/CMakeLists.txt +++ b/examples/network/simple_sniffer/main/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRCS "simple_sniffer_example_main.c" "cmd_sniffer.c" "cmd_pcap.c" - PRIV_REQUIRES console esp_wifi fatfs esp_eth app_trace nvs_flash + PRIV_REQUIRES console esp_wifi fatfs esp_eth app_trace nvs_flash esp_psram INCLUDE_DIRS ".")