From 5316a36175079ae31e4ec3541c6be5cd3d5a65a3 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 3 Sep 2024 14:17:14 +0800 Subject: [PATCH] fix(cache): fixed cache writeback/invalidate cannot reach higher vaddr parts --- components/esp_rom/CMakeLists.txt | 4 + .../esp_rom/esp32c61/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32c61/esp_rom_caps.h | 1 + .../esp_rom/esp32c61/ld/esp32c61.rom.ld | 4 +- components/esp_rom/linker.lf | 2 + .../esp_rom/patches/esp_rom_cache_esp32c61.c | 97 +++++++++++++++++++ 6 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 components/esp_rom/patches/esp_rom_cache_esp32c61.c diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 7286480a6e..ad857ddcd3 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -67,6 +67,10 @@ 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") +endif() + if(CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG) list(APPEND sources "patches/esp_rom_cache_writeback_esp32s3.S") endif() diff --git a/components/esp_rom/esp32c61/Kconfig.soc_caps.in b/components/esp_rom/esp32c61/Kconfig.soc_caps.in index cbcc1c7e6c..32f8056569 100644 --- a/components/esp_rom/esp32c61/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c61/Kconfig.soc_caps.in @@ -102,3 +102,7 @@ config ESP_ROM_USB_OTG_NUM config ESP_ROM_HAS_OUTPUT_PUTC_FUNC bool default y + +config ESP_ROM_CACHE_WB_INVLD_LOW_RANGE + bool + default y diff --git a/components/esp_rom/esp32c61/esp_rom_caps.h b/components/esp_rom/esp32c61/esp_rom_caps.h index f22baf6281..1d62f0f462 100644 --- a/components/esp_rom/esp32c61/esp_rom_caps.h +++ b/components/esp_rom/esp32c61/esp_rom_caps.h @@ -31,3 +31,4 @@ #define ESP_ROM_HAS_SW_FLOAT (1) // ROM has libgcc software floating point emulation functions #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 diff --git a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld index fae956570c..7ef283388d 100644 --- a/components/esp_rom/esp32c61/ld/esp32c61.rom.ld +++ b/components/esp_rom/esp32c61/ld/esp32c61.rom.ld @@ -192,9 +192,9 @@ MMU_Set_Page_Mode = 0x40000624; MMU_Get_Page_Mode = 0x40000628; Cache_Sync_Items = 0x4000062c; Cache_Op_Addr = 0x40000630; -Cache_Invalidate_Addr = 0x40000634; +/*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; +/*Cache_WriteBack_Addr = 0x4000063c; rom version API has issue that unable to access higher vaddr range, use IDF patch */ Cache_WriteBack_Invalidate_Addr = 0x40000640; Cache_Invalidate_All = 0x40000644; Cache_Clean_All = 0x40000648; diff --git a/components/esp_rom/linker.lf b/components/esp_rom/linker.lf index 712048ab71..10a76b3f0e 100644 --- a/components/esp_rom/linker.lf +++ b/components/esp_rom/linker.lf @@ -8,6 +8,8 @@ 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 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: diff --git a/components/esp_rom/patches/esp_rom_cache_esp32c61.c b/components/esp_rom/patches/esp_rom_cache_esp32c61.c new file mode 100644 index 0000000000..6fddfb7500 --- /dev/null +++ b/components/esp_rom/patches/esp_rom_cache_esp32c61.c @@ -0,0 +1,97 @@ +/* + * 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; +}