From 592d09f219103ed4d6ebe0d97c9beba097c6eb69 Mon Sep 17 00:00:00 2001 From: wanglei Date: Fri, 22 May 2026 13:24:30 +0800 Subject: [PATCH] fix(esp_rom): avoid critical issue in writeback v5.4 --- components/esp_rom/CMakeLists.txt | 8 +- .../esp_rom/esp32c5/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32c5/esp_rom_caps.h | 1 + components/esp_rom/esp32c5/ld/esp32c5.rom.ld | 10 +- .../esp_rom/esp32c61/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32c61/esp_rom_caps.h | 1 + .../esp32c61/include/esp32c61/rom/cache.h | 2 + .../esp_rom/esp32c61/ld/esp32c61.rom.ld | 8 +- .../esp_rom/esp32p4/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32p4/esp_rom_caps.h | 1 + .../esp32p4/include/esp32p4/rom/cache.h | 1 + .../esp_rom/esp32p4/ld/esp32p4.rom.eco5.ld | 10 +- components/esp_rom/esp32p4/ld/esp32p4.rom.ld | 10 +- components/esp_rom/linker.lf | 6 +- .../patches/esp_rom_cache_esp32c5_esp32c61.c | 240 ++++++++++++++++++ .../esp_rom/patches/esp_rom_cache_esp32c61.c | 97 ------- .../patches/esp_rom_cache_writeback_esp32p4.c | 137 ++++++++++ 17 files changed, 424 insertions(+), 120 deletions(-) create mode 100644 components/esp_rom/patches/esp_rom_cache_esp32c5_esp32c61.c delete mode 100644 components/esp_rom/patches/esp_rom_cache_esp32c61.c create mode 100644 components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index f77a86fa305..3ff4b62d438 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -67,8 +67,8 @@ if(CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG OR CONFIG_ESP_ROM_HAS_CACHE_WRITEBAC list(APPEND sources "patches/esp_rom_cache_esp32s2_esp32s3.c") endif() -if(CONFIG_ESP_ROM_CACHE_WB_INVLD_LOW_RANGE) - list(APPEND sources "patches/esp_rom_cache_esp32c61.c") +if(CONFIG_ESP_ROM_CACHE_WB_INVLD_LOW_RANGE OR CONFIG_ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP) + list(APPEND sources "patches/esp_rom_cache_esp32c5_esp32c61.c") endif() if(CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG) @@ -79,6 +79,10 @@ if(CONFIG_ESP_ROM_NO_USB_SERIAL_OUTPUT_API) list(APPEND sources "patches/esp_rom_usb_serial.c") endif() +if(CONFIG_ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP) + list(APPEND sources "patches/esp_rom_cache_writeback_esp32p4.c") +endif() + idf_component_register(SRCS ${sources} INCLUDE_DIRS ${include_dirs} PRIV_REQUIRES ${private_required_comp} diff --git a/components/esp_rom/esp32c5/Kconfig.soc_caps.in b/components/esp_rom/esp32c5/Kconfig.soc_caps.in index 284834c4744..ee11269b5dd 100644 --- a/components/esp_rom/esp32c5/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c5/Kconfig.soc_caps.in @@ -110,3 +110,7 @@ config ESP_ROM_CLIC_INT_THRESH_PATCH config ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP bool default y + +config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP + bool + default y diff --git a/components/esp_rom/esp32c5/esp_rom_caps.h b/components/esp_rom/esp32c5/esp_rom_caps.h index 637aefa3039..ae0b159b5b0 100644 --- a/components/esp_rom/esp32c5/esp_rom_caps.h +++ b/components/esp_rom/esp32c5/esp_rom_caps.h @@ -33,3 +33,4 @@ #define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart) #define ESP_ROM_CLIC_INT_THRESH_PATCH (1) // ROM version of esprv_intc_int_set_threshold incorrectly assumes lowest MINTTHRESH is 0x1F, should be 0xF #define ESP_ROM_SUPPORT_SECURE_BOOT_FAST_WAKEUP (1) // ROM supports the secure boot fast wakeup feature +#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.ld index 7f5148d682f..92a3087c80d 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -192,12 +192,12 @@ Cache_Sync_Items = 0x40000648; Cache_Op_Addr = 0x4000064c; Cache_Invalidate_Addr = 0x40000650; Cache_Clean_Addr = 0x40000654; -Cache_WriteBack_Addr = 0x40000658; -Cache_WriteBack_Invalidate_Addr = 0x4000065c; +PROVIDE( Cache_WriteBack_Addr = 0x40000658 ); +PROVIDE( Cache_WriteBack_Invalidate_Addr = 0x4000065c ); Cache_Invalidate_All = 0x40000660; Cache_Clean_All = 0x40000664; -Cache_WriteBack_All = 0x40000668; -Cache_WriteBack_Invalidate_All = 0x4000066c; +PROVIDE( Cache_WriteBack_All = 0x40000668 ); +PROVIDE( Cache_WriteBack_Invalidate_All = 0x4000066c ); Cache_Mask_All = 0x40000670; Cache_UnMask_Dram0 = 0x40000674; Cache_Suspend_Autoload = 0x40000678; diff --git a/components/esp_rom/esp32c61/Kconfig.soc_caps.in b/components/esp_rom/esp32c61/Kconfig.soc_caps.in index 32f80565693..566a6ac51ae 100644 --- a/components/esp_rom/esp32c61/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c61/Kconfig.soc_caps.in @@ -106,3 +106,7 @@ config ESP_ROM_HAS_OUTPUT_PUTC_FUNC config ESP_ROM_CACHE_WB_INVLD_LOW_RANGE bool default y + +config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP + bool + default y diff --git a/components/esp_rom/esp32c61/esp_rom_caps.h b/components/esp_rom/esp32c61/esp_rom_caps.h index 1d62f0f4629..f1ef43d450b 100644 --- a/components/esp_rom/esp32c61/esp_rom_caps.h +++ b/components/esp_rom/esp32c61/esp_rom_caps.h @@ -32,3 +32,4 @@ #define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage. #define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart) #define ESP_ROM_CACHE_WB_INVLD_LOW_RANGE (1) // ROM `Cache_WriteBack_Addr` and `Cache_Invalidate_Addr` can only access low vaddr parts +#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, no map parameter diff --git a/components/esp_rom/esp32c61/include/esp32c61/rom/cache.h b/components/esp_rom/esp32c61/include/esp32c61/rom/cache.h index 1e0f1baa0e9..2ba42350934 100644 --- a/components/esp_rom/esp32c61/include/esp32c61/rom/cache.h +++ b/components/esp_rom/esp32c61/include/esp32c61/rom/cache.h @@ -49,6 +49,8 @@ typedef enum { CACHE_SYNC_WRITEBACK_INVALIDATE = BIT(3), } cache_sync_t; +#define CACHE_MAP_FLASH_CACHE BIT(4) + typedef enum { CACHE_SIZE_HALF = 0, /*!< 8KB for icache and dcache */ CACHE_SIZE_FULL = 1, /*!< 16KB for icache and dcache */ diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld index 645b536924c..6e5bdc82c0c 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -195,11 +195,11 @@ Cache_Op_Addr = 0x40000630; /*Cache_Invalidate_Addr = 0x40000634; rom version API has issue that unable to access higher vaddr range, use IDF patch */ Cache_Clean_Addr = 0x40000638; /*Cache_WriteBack_Addr = 0x4000063c; rom version API has issue that unable to access higher vaddr range, use IDF patch */ -Cache_WriteBack_Invalidate_Addr = 0x40000640; +PROVIDE( Cache_WriteBack_Invalidate_Addr = 0x40000640 ); Cache_Invalidate_All = 0x40000644; Cache_Clean_All = 0x40000648; -Cache_WriteBack_All = 0x4000064c; -Cache_WriteBack_Invalidate_All = 0x40000650; +PROVIDE( Cache_WriteBack_All = 0x4000064c ); +PROVIDE( Cache_WriteBack_Invalidate_All = 0x40000650 ); Cache_Mask_All = 0x40000654; Cache_UnMask_Dram0 = 0x40000658; Cache_Suspend_Autoload = 0x4000065c; diff --git a/components/esp_rom/esp32p4/Kconfig.soc_caps.in b/components/esp_rom/esp32p4/Kconfig.soc_caps.in index 7e28eedc62e..465fa704af4 100644 --- a/components/esp_rom/esp32p4/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32p4/Kconfig.soc_caps.in @@ -82,3 +82,7 @@ config ESP_ROM_CLIC_INT_TYPE_PATCH config ESP_ROM_HAS_OUTPUT_PUTC_FUNC bool default y + +config ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP + bool + default y diff --git a/components/esp_rom/esp32p4/esp_rom_caps.h b/components/esp_rom/esp32p4/esp_rom_caps.h index dbcf8bd05eb..43cefe53ac4 100644 --- a/components/esp_rom/esp32p4/esp_rom_caps.h +++ b/components/esp_rom/esp32p4/esp_rom_caps.h @@ -26,3 +26,4 @@ #define ESP_ROM_HAS_VERSION (1) // ROM has version/eco information #define ESP_ROM_CLIC_INT_TYPE_PATCH (1) // ROM api esprv_intc_int_set_type configuring edge type interrupt is invalid TODO: IDF-13409 #define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart) +#define ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP (1) // ROM cache writeback related needs patch to avoid sync loss, need map parameter diff --git a/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h b/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h index 0c5ba82533b..8fbc22de785 100644 --- a/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h +++ b/components/esp_rom/esp32p4/include/esp32p4/rom/cache.h @@ -233,6 +233,7 @@ typedef enum { #define CACHE_MAP_L1_ICACHE_MASK (CACHE_MAP_L1_ICACHE_0 | CACHE_MAP_L1_ICACHE_1) #define CACHE_MAP_L1_CACHE_MASK (CACHE_MAP_L1_ICACHE_MASK | CACHE_MAP_L1_DCACHE) #define CACHE_MAP_MASK (CACHE_MAP_L1_ICACHE_MASK | CACHE_MAP_L1_DCACHE | CACHE_MAP_L2_CACHE) +#define CACHE_MAP_DCACHE_MASK (CACHE_MAP_L1_DCACHE | CACHE_MAP_L2_CACHE) struct cache_internal_stub_table { uint32_t (*l1_icache_line_size)(void); diff --git a/components/esp_rom/esp32p4/ld/esp32p4.rom.eco5.ld b/components/esp_rom/esp32p4/ld/esp32p4.rom.eco5.ld index a60e9d0b077..f1aae1cc64a 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4.rom.eco5.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4.rom.eco5.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -209,17 +209,17 @@ Cache_Invalidate_Addr = 0x4fc003e4; Cache_Invalidate_Addr_Gid = 0x4fc003e8; Cache_Clean_Addr = 0x4fc003ec; Cache_Clean_Addr_Gid = 0x4fc003f0; -Cache_WriteBack_Addr = 0x4fc003f4; +PROVIDE( Cache_WriteBack_Addr = 0x4fc003f4 ); Cache_WriteBack_Addr_Gid = 0x4fc003f8; -Cache_WriteBack_Invalidate_Addr = 0x4fc003fc; +PROVIDE( Cache_WriteBack_Invalidate_Addr = 0x4fc003fc ); Cache_WriteBack_Invalidate_Addr_Gid = 0x4fc00400; Cache_Invalidate_All = 0x4fc00404; Cache_Invalidate_All_Gid = 0x4fc00408; Cache_Clean_All = 0x4fc0040c; Cache_Clean_All_Gid = 0x4fc00410; -Cache_WriteBack_All = 0x4fc00414; +PROVIDE( Cache_WriteBack_All = 0x4fc00414 ); Cache_WriteBack_All_Gid = 0x4fc00418; -Cache_WriteBack_Invalidate_All = 0x4fc0041c; +PROVIDE( Cache_WriteBack_Invalidate_All = 0x4fc0041c ); Cache_WriteBack_Invalidate_All_Gid = 0x4fc00420; Cache_Mask_All = 0x4fc00424; Cache_Suspend_L1_CORE0_ICache_Autoload = 0x4fc00428; diff --git a/components/esp_rom/esp32p4/ld/esp32p4.rom.ld b/components/esp_rom/esp32p4/ld/esp32p4.rom.ld index b9950412e06..0a35cde1b5e 100644 --- a/components/esp_rom/esp32p4/ld/esp32p4.rom.ld +++ b/components/esp_rom/esp32p4/ld/esp32p4.rom.ld @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -187,17 +187,17 @@ Cache_Invalidate_Addr = 0x4fc003e4; Cache_Invalidate_Addr_Gid = 0x4fc003e8; Cache_Clean_Addr = 0x4fc003ec; Cache_Clean_Addr_Gid = 0x4fc003f0; -Cache_WriteBack_Addr = 0x4fc003f4; +PROVIDE( Cache_WriteBack_Addr = 0x4fc003f4 ); Cache_WriteBack_Addr_Gid = 0x4fc003f8; -Cache_WriteBack_Invalidate_Addr = 0x4fc003fc; +PROVIDE( Cache_WriteBack_Invalidate_Addr = 0x4fc003fc ); Cache_WriteBack_Invalidate_Addr_Gid = 0x4fc00400; Cache_Invalidate_All = 0x4fc00404; Cache_Invalidate_All_Gid = 0x4fc00408; Cache_Clean_All = 0x4fc0040c; Cache_Clean_All_Gid = 0x4fc00410; -Cache_WriteBack_All = 0x4fc00414; +PROVIDE( Cache_WriteBack_All = 0x4fc00414 ); Cache_WriteBack_All_Gid = 0x4fc00418; -Cache_WriteBack_Invalidate_All = 0x4fc0041c; +PROVIDE( Cache_WriteBack_Invalidate_All = 0x4fc0041c ); Cache_WriteBack_Invalidate_All_Gid = 0x4fc00420; Cache_Mask_All = 0x4fc00424; Cache_Suspend_L1_CORE0_ICache_Autoload = 0x4fc00428; diff --git a/components/esp_rom/linker.lf b/components/esp_rom/linker.lf index 10a76b3f0ee..db08d12157b 100644 --- a/components/esp_rom/linker.lf +++ b/components/esp_rom/linker.lf @@ -8,11 +8,13 @@ entries: esp_rom_cache_esp32s2_esp32s3 (noflash) if ESP_ROM_HAS_CACHE_WRITEBACK_BUG = y: esp_rom_cache_writeback_esp32s3 (noflash) - if ESP_ROM_CACHE_WB_INVLD_LOW_RANGE = y: - esp_rom_cache_esp32c61 (noflash) + if ESP_ROM_CACHE_WB_INVLD_LOW_RANGE = y || ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_NO_MAP = y: + esp_rom_cache_esp32c5_esp32c61 (noflash) if HEAP_TLSF_USE_ROM_IMPL = y && (ESP_ROM_TLSF_CHECK_PATCH = y || HEAP_TLSF_CHECK_PATCH = y): esp_rom_tlsf (noflash) if SOC_SYSTIMER_SUPPORTED = y: esp_rom_systimer (noflash) if HAL_WDT_USE_ROM_IMPL = y: esp_rom_wdt (noflash) + if ESP_ROM_CACHE_WRITEBACK_NEEDS_SYNC_TWICE_MAP = y: + esp_rom_cache_writeback_esp32p4 (noflash) diff --git a/components/esp_rom/patches/esp_rom_cache_esp32c5_esp32c61.c b/components/esp_rom/patches/esp_rom_cache_esp32c5_esp32c61.c new file mode 100644 index 00000000000..eb088ac17fc --- /dev/null +++ b/components/esp_rom/patches/esp_rom_cache_esp32c5_esp32c61.c @@ -0,0 +1,240 @@ +/* + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "esp_rom_caps.h" +#include "soc/soc_caps.h" +#include "soc/cache_reg.h" +#include "soc/cache_struct.h" +#include "soc/ext_mem_defs.h" +#include "hal/assert.h" +#if CONFIG_IDF_TARGET_ESP32C61 +#include "esp32c61/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/cache.h" +#else +#error "This patch is only applied to ESP32C5 or ESP32C61" +#endif + +#include "esp_rom_sys.h" + +/** + * For ESP32C61, we will patch: + * 1. writeback/invalidate not work with high address, https://jira.espressif.com:8443/browse/IDF-11008 + * 2. cache writeback skip, https://jira.espressif.com:8443/browse/DIG-829 + * + * For ESP32C5, we will only patch cache writeback skip issue + */ +#if CONFIG_IDF_TARGET_ESP32C61 + +#define CACHE_MAX_SYNC_NUM ((CACHE_SYNC_SIZE + 1) >> 1) + +/** + * @brief Sync Cache items + * + * @param type sync type + * @param addr address + * @param bytes bytes to be synced + */ +__attribute__((always_inline)) +static inline void s_cache_sync_items(uint32_t type, uint32_t addr, uint32_t bytes) +{ + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_SET_FIELD(CACHE_SYNC_SIZE_REG, CACHE_SYNC_SIZE, bytes); + REG_SET_BIT(CACHE_SYNC_CTRL_REG, type); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)) + ; +} + +__attribute__((always_inline)) +static inline void s_cache_sync_items_twice(uint32_t type, uint32_t addr, uint32_t bytes) +{ + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_SET_FIELD(CACHE_SYNC_SIZE_REG, CACHE_SYNC_SIZE, bytes); + REG_SET_BIT(CACHE_SYNC_CTRL_REG, type); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)) + ; + + REG_SET_BIT(CACHE_SYNC_CTRL_REG, type); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)) + ; +} + +int Cache_Invalidate_Addr(uint32_t vaddr, uint32_t size) +{ + uint32_t plus = 0; + uint32_t cache_line_size = 32; + uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM; + if (size == 0) { + HAL_ASSERT(false); + } + //aligned start address to cache line size + plus = vaddr & (cache_line_size - 1); + vaddr -= plus; + //make the length fit the start address + size += plus; + //aligned the length to cache line size(0->0) + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + while (size > 0) { + //aligned to cache_max_sync_size, (0->cache_max_sync_size) + uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr; + if (this_size > size) { + this_size = size; + } + s_cache_sync_items(CACHE_SYNC_INVALIDATE, vaddr, this_size); + vaddr += this_size; + size -= this_size; + } + + return 0; +} + +int Cache_WriteBack_Addr(uint32_t vaddr, uint32_t size) +{ + uint32_t plus = 0; + uint32_t cache_line_size = 32; + uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM; + if (size == 0) { + HAL_ASSERT(false); + } + //aligned start address to cache line size + plus = vaddr & (cache_line_size - 1); + vaddr -= plus; + //make the length fit the start address + size += plus; + //aligned the length to cache line size(0->0) + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + while (size > 0) { + //aligned to cache_max_sync_size, (0->cache_max_sync_size) + uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr; + if (this_size > size) { + this_size = size; + } + s_cache_sync_items_twice(CACHE_SYNC_WRITEBACK, vaddr, this_size); + vaddr += this_size; + size -= this_size; + } + + return 0; +} + +int Cache_WriteBack_Invalidate_Addr(uint32_t addr, uint32_t size) +{ + uint32_t plus = 0; + uint32_t cache_line_size = 32; + uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM; + if (size == 0) { + HAL_ASSERT(false); + } + //aligned start address to cache line size + plus = vaddr & (cache_line_size - 1); + vaddr -= plus; + //make the length fit the start address + size += plus; + //aligned the length to cache line size(0->0) + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + while (size > 0) { + //aligned to cache_max_sync_size, (0->cache_max_sync_size) + uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr; + if (this_size > size) { + this_size = size; + } + s_cache_sync_items_twice(CACHE_SYNC_WRITEBACK_INVALIDATE, vaddr, this_size); + vaddr += this_size; + size -= this_size; + } + + return 0; +} + +#ifndef BOOTLOADER_BUILD +void Cache_WriteBack_All(void) +{ + s_cache_sync_items_twice(CACHE_SYNC_WRITEBACK, 0, 0); +} +#endif + +void Cache_WriteBack_Invalidate_All(void) +{ + s_cache_sync_items_twice(CACHE_SYNC_WRITEBACK_INVALIDATE, 0, 0); +} + +#elif CONFIG_IDF_TARGET_ESP32C5 +int Cache_WriteBack_Addr(uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = MIN_CACHE_LINE_SIZE; + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +#ifndef BOOTLOADER_BUILD +void Cache_WriteBack_All(void) +{ + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); +} +#endif + +int Cache_WriteBack_Invalidate_Addr(uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = MIN_CACHE_LINE_SIZE; + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +void Cache_WriteBack_Invalidate_All(void) +{ + REG_WRITE(CACHE_SYNC_MAP_REG, CACHE_MAP_FLASH_CACHE); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); +} +#endif diff --git a/components/esp_rom/patches/esp_rom_cache_esp32c61.c b/components/esp_rom/patches/esp_rom_cache_esp32c61.c deleted file mode 100644 index 6fddfb75007..00000000000 --- a/components/esp_rom/patches/esp_rom_cache_esp32c61.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include "sdkconfig.h" -#include "esp_rom_caps.h" -#include "soc/soc_caps.h" -#include "soc/cache_reg.h" -#include "soc/cache_struct.h" -#include "soc/ext_mem_defs.h" -#include "hal/assert.h" -#include "esp32c61/rom/cache.h" - -#include "esp_rom_sys.h" - -#define CACHE_MAX_SYNC_NUM ((CACHE_SYNC_SIZE + 1) >> 1) - -/** - * @brief Sync Cache items - * - * @param type sync type - * @param addr address - * @param bytes bytes to be synced - */ -__attribute__((always_inline)) -static inline void s_cache_sync_items(uint32_t type, uint32_t addr, uint32_t bytes) -{ - REG_WRITE(CACHE_SYNC_ADDR_REG, addr); - REG_SET_FIELD(CACHE_SYNC_SIZE_REG, CACHE_SYNC_SIZE, bytes); - REG_SET_BIT(CACHE_SYNC_CTRL_REG, type); - while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)) - ; -} - -int Cache_Invalidate_Addr(uint32_t vaddr, uint32_t size) -{ - uint32_t plus = 0; - uint32_t cache_line_size = 32; - uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM; - if (size == 0) { - HAL_ASSERT(false); - } - //aligned start address to cache line size - plus = vaddr & (cache_line_size - 1); - vaddr -= plus; - //make the length fit the start address - size += plus; - //aligned the length to cache line size(0->0) - size = (size + cache_line_size - 1) & ~(cache_line_size - 1); - - while (size > 0) { - //aligned to cache_max_sync_size, (0->cache_max_sync_size) - uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr; - if (this_size > size) { - this_size = size; - } - s_cache_sync_items(CACHE_SYNC_INVALIDATE, vaddr, this_size); - vaddr += this_size; - size -= this_size; - } - - return 0; -} - -int Cache_WriteBack_Addr(uint32_t vaddr, uint32_t size) -{ - uint32_t plus = 0; - uint32_t cache_line_size = 32; - uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM; - if (size == 0) { - HAL_ASSERT(false); - } - //aligned start address to cache line size - plus = vaddr & (cache_line_size - 1); - vaddr -= plus; - //make the length fit the start address - size += plus; - //aligned the length to cache line size(0->0) - size = (size + cache_line_size - 1) & ~(cache_line_size - 1); - - while (size > 0) { - //aligned to cache_max_sync_size, (0->cache_max_sync_size) - uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr; - if (this_size > size) { - this_size = size; - } - s_cache_sync_items(CACHE_SYNC_WRITEBACK, vaddr, this_size); - vaddr += this_size; - size -= this_size; - } - - return 0; -} diff --git a/components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c b/components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c new file mode 100644 index 00000000000..4a5fe274f0b --- /dev/null +++ b/components/esp_rom/patches/esp_rom_cache_writeback_esp32p4.c @@ -0,0 +1,137 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "soc/cache_reg.h" +#include "rom/cache.h" +#include "esp_attr.h" +#include "esp_rom_sys.h" + +// esp32p4 needs map parameters in apis. +int Cache_WriteBack_Addr(uint32_t map, uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = 0; + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + /* esp32p4 will check l2 cache */ + if (map & CACHE_MAP_L1_DCACHE) { + cache_line_size = rom_cache_internal_table_ptr->l1_dcache_line_size(); + } + if (map & CACHE_MAP_L2_CACHE) { + cache_line_size = (cache_line_size > rom_cache_internal_table_ptr->l2_cache_line_size()) ? + cache_line_size : rom_cache_internal_table_ptr->l2_cache_line_size(); + } + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +#ifndef BOOTLOADER_BUILD +int Cache_WriteBack_All(uint32_t map) +{ + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} +#endif + +int Cache_WriteBack_Invalidate_Addr(uint32_t map, uint32_t addr, uint32_t size) +{ + uint32_t plus; + uint32_t cache_line_size = 0; + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + /* esp32p4 will check l2 cache */ + if (map & CACHE_MAP_L1_DCACHE) { + cache_line_size = rom_cache_internal_table_ptr->l1_dcache_line_size(); + } + if (map & CACHE_MAP_L2_CACHE) { + cache_line_size = (cache_line_size > rom_cache_internal_table_ptr->l2_cache_line_size()) ? + cache_line_size : rom_cache_internal_table_ptr->l2_cache_line_size(); + } + + plus = addr & (cache_line_size - 1); + addr -= plus; + size += plus; + size = (size + cache_line_size - 1) & ~(cache_line_size - 1); + + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, addr); + REG_WRITE(CACHE_SYNC_SIZE_REG, size); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +} + +int Cache_WriteBack_Invalidate_All(uint32_t map) +{ + /* writeback readonly cache is invalid */ + if (map & CACHE_MAP_L1_ICACHE_MASK) { + return ESP_ROM_ERR_INVALID_ARG; + } + + if ((map & CACHE_MAP_DCACHE_MASK) == 0) { + return ESP_ROM_ERR_INVALID_ARG; + } + + REG_WRITE(CACHE_SYNC_MAP_REG, map); + REG_WRITE(CACHE_SYNC_ADDR_REG, 0); + REG_WRITE(CACHE_SYNC_SIZE_REG, 0); + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + REG_WRITE(CACHE_SYNC_CTRL_REG, CACHE_WRITEBACK_INVALIDATE_ENA); + while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE)); + + return 0; +}