From 8842e5764f2e73b010eda14b1e31246c0cc85954 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 3 Sep 2024 14:08:15 +0800 Subject: [PATCH 1/3] feat(psram): xip psram c5 --- .../src/bootloader_utility.c | 2 +- components/esp_psram/esp32c5/Kconfig.spiram | 34 +++++++++++++++++++ .../esp_psram/test_apps/psram/pytest_psram.py | 1 + .../psram/sdkconfig.ci.esp32c5_advanced | 15 ++++++++ components/esp_system/port/image_process.c | 3 ++ components/hal/esp32c5/include/hal/mmu_ll.h | 2 ++ .../soc/esp32c5/include/soc/ext_mem_defs.h | 4 +-- .../flash_mmap/sdkconfig.ci.xip_psram_esp32c5 | 2 ++ 8 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c5_advanced create mode 100644 components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c5 diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 4e469b4018..30dd5049fc 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -875,7 +875,7 @@ static void set_cache_and_start_app( } //we use the MMU_LL_END_DROM_ENTRY_ID mmu entry as a map page for app to find the boot partition mmu_hal_map_region(0, MMU_TARGET_FLASH0, MMU_LL_END_DROM_ENTRY_VADDR, drom_addr_aligned, CONFIG_MMU_PAGE_SIZE, &actual_mapped_len); - ESP_EARLY_LOGV(TAG, "mapped one page of the rodata, from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, drom_load_addr_aligned, actual_mapped_len); + ESP_EARLY_LOGV(TAG, "mapped one page of the rodata, from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, MMU_LL_END_DROM_ENTRY_VADDR, actual_mapped_len); #endif //-----------------------MAP IROM-------------------------- diff --git a/components/esp_psram/esp32c5/Kconfig.spiram b/components/esp_psram/esp32c5/Kconfig.spiram index 725b456a3c..75e0ec8da9 100644 --- a/components/esp_psram/esp32c5/Kconfig.spiram +++ b/components/esp_psram/esp32c5/Kconfig.spiram @@ -44,5 +44,39 @@ menu "SPI RAM config" default 80 if SPIRAM_SPEED_80M default 40 if SPIRAM_SPEED_40M + config SPIRAM_FETCH_INSTRUCTIONS + bool + help + Enable this option allows moving application's instruction segment from the SPI Flash to PSRAM + + config SPIRAM_RODATA + bool + help + Enable this option allows moving application's rodata segment from the SPI Flash to + PSRAM + + config SPIRAM_XIP_FROM_PSRAM + bool "Enable Executable in place from (XiP) from PSRAM feature (READ HELP)" + default n + select SPIRAM_FETCH_INSTRUCTIONS + select SPIRAM_RODATA + select SPIRAM_FLASH_LOAD_TO_PSRAM + help + If enabled, firmware in flash including instructions and data will be moved into PSRAM on startup, + firmware code will execute directly from PSRAM. + + With this option enabled, code that requires execution during an MSPI1 Flash operation + does not have to be placed in IRAM. Therefore codes that need to be executing during Flash + operations can continue working normally. + + This feature is useful for high throughput peripheral involved applications to improve + the performance during MSPI1 flash operations. + + config SPIRAM_FLASH_LOAD_TO_PSRAM + bool + help + This is a helper indicating this condition: + `CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32C5` + source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here endmenu diff --git a/components/esp_psram/test_apps/psram/pytest_psram.py b/components/esp_psram/test_apps/psram/pytest_psram.py index 949aea2d4f..04dd2807b8 100644 --- a/components/esp_psram/test_apps/psram/pytest_psram.py +++ b/components/esp_psram/test_apps/psram/pytest_psram.py @@ -94,6 +94,7 @@ def test_psram_esp32p4(dut: Dut) -> None: 'config', [ 'esp32c5_release', + 'esp32c5_advanced', ], indirect=True, ) diff --git a/components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c5_advanced b/components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c5_advanced new file mode 100644 index 0000000000..cab65486e0 --- /dev/null +++ b/components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c5_advanced @@ -0,0 +1,15 @@ +CONFIG_IDF_TARGET="esp32c5" + +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_XIP_FROM_PSRAM=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/esp_system/port/image_process.c b/components/esp_system/port/image_process.c index 2f795bf765..9dec8b125b 100644 --- a/components/esp_system/port/image_process.c +++ b/components/esp_system/port/image_process.c @@ -176,6 +176,9 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "unaligned segment length 0x%"PRIx32, data_len); } + mmu_ll_set_entry_invalid(0, MMU_LL_END_DROM_ENTRY_ID); + s_current_read_mapping = UINT32_MAX; + return ESP_OK; } diff --git a/components/hal/esp32c5/include/hal/mmu_ll.h b/components/hal/esp32c5/include/hal/mmu_ll.h index 398d2bd7a1..39f3bd0db3 100644 --- a/components/hal/esp32c5/include/hal/mmu_ll.h +++ b/components/hal/esp32c5/include/hal/mmu_ll.h @@ -24,6 +24,8 @@ extern "C" { #endif +#define MMU_LL_FLASH_MMU_ID 0 +#define MMU_LL_PSRAM_MMU_ID 0 #define MMU_LL_END_DROM_ENTRY_VADDR (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_MMU_PAGE_SIZE) #define MMU_LL_END_DROM_ENTRY_ID (SOC_MMU_ENTRY_NUM - 1) diff --git a/components/soc/esp32c5/include/soc/ext_mem_defs.h b/components/soc/esp32c5/include/soc/ext_mem_defs.h index e694359f34..de680754ad 100644 --- a/components/soc/esp32c5/include/soc/ext_mem_defs.h +++ b/components/soc/esp32c5/include/soc/ext_mem_defs.h @@ -58,7 +58,7 @@ extern "C" { * valid bit + value bits * valid bit is BIT(9), so value bits are 0x1ff */ -#define SOC_MMU_VALID_VAL_MASK (SOC_MMU_ACCESS_SPIRAM-1) +#define SOC_MMU_VALID_VAL_MASK (SOC_MMU_ACCESS_SPIRAM - 1) /** * Max MMU available paddr page num. * `SOC_MMU_MAX_PADDR_PAGE_NUM * SOC_MMU_PAGE_SIZE` means the max paddr address supported by the MMU. e.g.: @@ -72,7 +72,7 @@ extern "C" { * This is the mask used for mapping. e.g.: * 0x4200_0000 & SOC_MMU_VADDR_MASK */ -#define SOC_MMU_VADDR_MASK ((SOC_MMU_PAGE_SIZE) * SOC_MMU_ENTRY_NUM - 1) +#define SOC_MMU_VADDR_MASK ((SOC_MMU_PAGE_SIZE) * SOC_MMU_ENTRY_NUM - 1) #define SOC_MMU_DBUS_VADDR_BASE 0x42000000 #define SOC_MMU_IBUS_VADDR_BASE 0x42000000 diff --git a/components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c5 b/components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c5 new file mode 100644 index 0000000000..9c3610a24b --- /dev/null +++ b/components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c5 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c5" +CONFIG_SPIRAM_XIP_FROM_PSRAM=y From fce2680e9171d0104bcd9f43a12dce643b61b394 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 3 Sep 2024 14:10:24 +0800 Subject: [PATCH 2/3] feat(psram): xip psram c61 --- components/esp_psram/esp32c61/Kconfig.spiram | 34 +++++++++++++++++++ .../include/esp_private/mmu_psram_flash.h | 2 +- components/esp_psram/mmu_psram_flash_v2.c | 6 ++-- .../esp_psram/test_apps/psram/pytest_psram.py | 1 + .../psram/sdkconfig.ci.esp32c61_advanced | 15 ++++++++ components/hal/esp32c61/include/hal/mmu_ll.h | 3 +- .../soc/esp32c61/include/soc/ext_mem_defs.h | 2 +- components/spi_flash/flash_mmap.c | 8 ++--- .../test_apps/flash_mmap/pytest_flash_mmap.py | 3 +- .../sdkconfig.ci.xip_psram_esp32c61 | 2 ++ 10 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c61_advanced create mode 100644 components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c61 diff --git a/components/esp_psram/esp32c61/Kconfig.spiram b/components/esp_psram/esp32c61/Kconfig.spiram index 725b456a3c..0ef577983f 100644 --- a/components/esp_psram/esp32c61/Kconfig.spiram +++ b/components/esp_psram/esp32c61/Kconfig.spiram @@ -44,5 +44,39 @@ menu "SPI RAM config" default 80 if SPIRAM_SPEED_80M default 40 if SPIRAM_SPEED_40M + config SPIRAM_FETCH_INSTRUCTIONS + bool + help + Enable this option allows moving application's instruction segment from the SPI Flash to PSRAM + + config SPIRAM_RODATA + bool + help + Enable this option allows moving application's rodata segment from the SPI Flash to + PSRAM + + config SPIRAM_XIP_FROM_PSRAM + bool "Enable Executable in place from (XiP) from PSRAM feature (READ HELP)" + default n + select SPIRAM_FETCH_INSTRUCTIONS + select SPIRAM_RODATA + select SPIRAM_FLASH_LOAD_TO_PSRAM + help + If enabled, firmware in flash including instructions and data will be moved into PSRAM on startup, + firmware code will execute directly from PSRAM. + + With this option enabled, code that requires execution during an MSPI1 Flash operation + does not have to be placed in IRAM. Therefore codes that need to be executing during Flash + operations can continue working normally. + + This feature is useful for high throughput peripheral involved applications to improve + the performance during MSPI1 flash operations. + + config SPIRAM_FLASH_LOAD_TO_PSRAM + bool + help + This is a helper indicating this condition: + `CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32C61` + source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here endmenu diff --git a/components/esp_psram/include/esp_private/mmu_psram_flash.h b/components/esp_psram/include/esp_private/mmu_psram_flash.h index 554ab77d16..e95845a0f4 100644 --- a/components/esp_psram/include/esp_private/mmu_psram_flash.h +++ b/components/esp_psram/include/esp_private/mmu_psram_flash.h @@ -30,7 +30,7 @@ extern "C" { #if CONFIG_IDF_TARGET_ESP32 #define MMU_PAGE_SIZE 0x8000 #else -#define MMU_PAGE_SIZE 0x10000 +#define MMU_PAGE_SIZE CONFIG_MMU_PAGE_SIZE #define MMU_PAGE_TO_BYTES(page_id) ((page_id) * MMU_PAGE_SIZE) #define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE) #endif diff --git a/components/esp_psram/mmu_psram_flash_v2.c b/components/esp_psram/mmu_psram_flash_v2.c index 0ae669c838..be78092322 100644 --- a/components/esp_psram/mmu_psram_flash_v2.c +++ b/components/esp_psram/mmu_psram_flash_v2.c @@ -85,7 +85,7 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size uint32_t flash_irom_paddr_start = 0; image_process_get_flash_segments_info(&flash_drom_paddr_start, &flash_irom_paddr_start); flash_irom_paddr_start = ALIGN_DOWN_BY(flash_irom_paddr_start, CONFIG_MMU_PAGE_SIZE); - ESP_EARLY_LOGI(TAG, "flash_irom_paddr_start: 0x%x", flash_irom_paddr_start); + ESP_EARLY_LOGV(TAG, "flash_irom_paddr_start: 0x%x", flash_irom_paddr_start); if ((MMU_PAGE_TO_BYTES(start_page) + irom_size) > psram_size) { ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %"PRId32" B, from %"PRId32" B to %"PRId32" B", irom_size, MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + irom_size); @@ -106,6 +106,7 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size start_page += BYTES_TO_MMU_PAGE(irom_size); *out_page = start_page; + ESP_EARLY_LOGI(TAG, ".text xip on psram"); return ESP_OK; } #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS @@ -120,7 +121,7 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si uint32_t flash_irom_paddr_start = 0; image_process_get_flash_segments_info(&flash_drom_paddr_start, &flash_irom_paddr_start); flash_drom_paddr_start = ALIGN_DOWN_BY(flash_drom_paddr_start, CONFIG_MMU_PAGE_SIZE); - ESP_EARLY_LOGI(TAG, "flash_drom_paddr_start: 0x%x", flash_drom_paddr_start); + ESP_EARLY_LOGV(TAG, "flash_drom_paddr_start: 0x%x", flash_drom_paddr_start); if ((MMU_PAGE_TO_BYTES(start_page) + drom_size) > psram_size) { ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash rodata, need %"PRId32" B, from %"PRId32" B to %"PRId32" B", drom_size, MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + drom_size); @@ -141,6 +142,7 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si start_page += BYTES_TO_MMU_PAGE(drom_size); *out_page = start_page; + ESP_EARLY_LOGI(TAG, ".rodata xip on psram"); return ESP_OK; } #endif //#if CONFIG_SPIRAM_RODATA diff --git a/components/esp_psram/test_apps/psram/pytest_psram.py b/components/esp_psram/test_apps/psram/pytest_psram.py index 04dd2807b8..e13d48e803 100644 --- a/components/esp_psram/test_apps/psram/pytest_psram.py +++ b/components/esp_psram/test_apps/psram/pytest_psram.py @@ -108,6 +108,7 @@ def test_psram_esp32c5(dut: Dut) -> None: 'config', [ 'esp32c61_release', + 'esp32c61_advanced', ], indirect=True, ) diff --git a/components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c61_advanced b/components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c61_advanced new file mode 100644 index 0000000000..aa1bcea9c7 --- /dev/null +++ b/components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c61_advanced @@ -0,0 +1,15 @@ +CONFIG_IDF_TARGET="esp32c61" + +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y + +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_XIP_FROM_PSRAM=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/components/hal/esp32c61/include/hal/mmu_ll.h b/components/hal/esp32c61/include/hal/mmu_ll.h index f944c3ecbc..b0e7c75309 100644 --- a/components/hal/esp32c61/include/hal/mmu_ll.h +++ b/components/hal/esp32c61/include/hal/mmu_ll.h @@ -20,6 +20,8 @@ extern "C" { #endif +#define MMU_LL_FLASH_MMU_ID 0 +#define MMU_LL_PSRAM_MMU_ID 0 #define MMU_LL_END_DROM_ENTRY_VADDR (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_MMU_PAGE_SIZE) #define MMU_LL_END_DROM_ENTRY_ID (SOC_MMU_ENTRY_NUM - 1) @@ -212,7 +214,6 @@ static inline uint32_t mmu_ll_format_paddr(uint32_t mmu_id, uint32_t paddr, mmu_ __attribute__((always_inline)) static inline void mmu_ll_write_entry(uint32_t mmu_id, uint32_t entry_id, uint32_t mmu_val, mmu_target_t target) { (void)mmu_id; - (void)target; uint32_t mmu_raw_value; if (mmu_ll_cache_encryption_enabled()) { mmu_val |= SOC_MMU_SENSITIVE; diff --git a/components/soc/esp32c61/include/soc/ext_mem_defs.h b/components/soc/esp32c61/include/soc/ext_mem_defs.h index 6dcda1059c..85ce7cf8d7 100644 --- a/components/soc/esp32c61/include/soc/ext_mem_defs.h +++ b/components/soc/esp32c61/include/soc/ext_mem_defs.h @@ -58,7 +58,7 @@ extern "C" { * valid bit + value bits * valid bit is BIT(9), so value bits are 0x1ff */ -#define SOC_MMU_VALID_VAL_MASK 0x3ff +#define SOC_MMU_VALID_VAL_MASK (SOC_MMU_ACCESS_SPIRAM - 1) /** * Max MMU available paddr page num. * `SOC_MMU_MAX_PADDR_PAGE_NUM * SOC_MMU_PAGE_SIZE` means the max paddr address supported by the MMU. e.g.: diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index bfc6b10179..28e3f40959 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -277,7 +277,7 @@ const void * spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memo mmu_target_t target = MMU_TARGET_FLASH0; __attribute__((unused)) uint32_t phys_page = phys_offs / CONFIG_MMU_PAGE_SIZE; -#if !SOC_MMU_PER_EXT_MEM_TARGET +#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) { target = MMU_TARGET_PSRAM0; @@ -291,7 +291,7 @@ const void * spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memo phys_offs -= rodata_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE; } #endif -#endif //#if !SOC_MMU_PER_EXT_MEM_TARGET +#endif //#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM mmu_vaddr_t type = (memory == SPI_FLASH_MMAP_DATA) ? MMU_VADDR_DATA : MMU_VADDR_INSTRUCTION; ret = esp_mmu_paddr_to_vaddr(phys_offs, target, type, &ptr); @@ -383,7 +383,7 @@ size_t spi_flash_cache2phys(const void *cached) int offset = 0; -#if !SOC_MMU_PER_EXT_MEM_TARGET //TODO: IDF-9049 +#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM #if CONFIG_SPIRAM_RODATA if ((uint32_t)cached >= (uint32_t)&_rodata_reserved_start && (uint32_t)cached <= (uint32_t)&_rodata_reserved_end) { offset = rodata_flash2spiram_offset(); @@ -394,7 +394,7 @@ size_t spi_flash_cache2phys(const void *cached) offset = instruction_flash2spiram_offset(); } #endif -#endif //#if !SOC_MMU_PER_EXT_MEM_TARGET +#endif //#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM return paddr + offset * CONFIG_MMU_PAGE_SIZE; } diff --git a/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py b/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py index 782d0091b2..65dc1c57c2 100644 --- a/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py +++ b/components/spi_flash/test_apps/flash_mmap/pytest_flash_mmap.py @@ -1,6 +1,5 @@ # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import pytest from pytest_embedded import Dut @@ -38,6 +37,8 @@ def test_flash_mmap_rom_impl(dut: Dut) -> None: XIP_CONFIGS = [ pytest.param('xip_psram_esp32s2', marks=[pytest.mark.esp32s2]), pytest.param('xip_psram_esp32s3', marks=[pytest.mark.esp32s3]), + pytest.param('xip_psram_esp32c5', marks=[pytest.mark.esp32c5]), + pytest.param('xip_psram_esp32c61', marks=[pytest.mark.esp32c61]), ] diff --git a/components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c61 b/components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c61 new file mode 100644 index 0000000000..656c4d8f2c --- /dev/null +++ b/components/spi_flash/test_apps/flash_mmap/sdkconfig.ci.xip_psram_esp32c61 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c61" +CONFIG_SPIRAM_XIP_FROM_PSRAM=y From 5316a36175079ae31e4ec3541c6be5cd3d5a65a3 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 3 Sep 2024 14:17:14 +0800 Subject: [PATCH 3/3] 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; +}