From 44f771c713498c7a67060020fbc0b726926f8acd Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 9 May 2022 16:44:02 +0800 Subject: [PATCH] psram: support s3 copy flash to psram --- .../soc/esp32s2/esp_private/mmu_psram.h | 6 - .../soc/esp32s3/esp_private/mmu_psram.h | 71 +++++ .../include/soc/esp32s3/spiram.h | 47 --- components/esp_hw_support/linker.lf | 5 +- .../esp_hw_support/port/esp32s2/mmu_psram.c | 6 + .../port/esp32s3/CMakeLists.txt | 2 +- .../esp_hw_support/port/esp32s3/mmu_psram.c | 276 ++++++++++++++++++ .../esp_hw_support/port/esp32s3/spiram.c | 157 +++------- components/esp_system/port/cpu_start.c | 21 +- components/spi_flash/flash_mmap.c | 11 + 10 files changed, 416 insertions(+), 186 deletions(-) create mode 100644 components/esp_hw_support/include/soc/esp32s3/esp_private/mmu_psram.h create mode 100644 components/esp_hw_support/port/esp32s3/mmu_psram.c diff --git a/components/esp_hw_support/include/soc/esp32s2/esp_private/mmu_psram.h b/components/esp_hw_support/include/soc/esp32s2/esp_private/mmu_psram.h index cb76435697..f49f85f0db 100644 --- a/components/esp_hw_support/include/soc/esp32s2/esp_private/mmu_psram.h +++ b/components/esp_hw_support/include/soc/esp32s2/esp_private/mmu_psram.h @@ -17,9 +17,6 @@ extern "C" { esp_err_t mmu_map_psram(uint32_t start_paddr, uint32_t map_length, uint32_t *out_start_vaddr); #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS -extern int _instruction_reserved_start; -extern int _instruction_reserved_end; - esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page); /** @@ -45,9 +42,6 @@ int instruction_flash2spiram_offset(void); #endif #if CONFIG_SPIRAM_RODATA -extern int _rodata_reserved_start; -extern int _rodata_reserved_end; - esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page); /** diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_private/mmu_psram.h b/components/esp_hw_support/include/soc/esp32s3/esp_private/mmu_psram.h new file mode 100644 index 0000000000..73ce159a0f --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32s3/esp_private/mmu_psram.h @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" +#include "sdkconfig.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + +esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page); + +/** + * @brief Get the start page number of the instruction in SPI flash + * + * @return start page number + */ +uint32_t instruction_flash_start_page_get(void); + +/** + * @brief Get the end page number of the instruction in SPI flash + * + * @return end page number + */ +uint32_t instruction_flash_end_page_get(void); + +/** + * @brief Get the offset of instruction from SPI flash to SPI RAM + * + * @return instruction offset + */ +int instruction_flash2spiram_offset(void); +#endif + +#if CONFIG_SPIRAM_RODATA +esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page); + +/** + * @brief Get the start page number of the rodata in SPI flash + * + * @return start page number + */ +uint32_t rodata_flash_start_page_get(void); + +/** + * @brief Get the end page number of the rodata in SPI flash + * + * @return end page number + */ +uint32_t rodata_flash_end_page_get(void); + +/** + * @brief Get the offset number of rodata from SPI flash to SPI RAM + * + * @return rodata offset + */ +int rodata_flash2spiram_offset(void); +#endif + + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/soc/esp32s3/spiram.h b/components/esp_hw_support/include/soc/esp32s3/spiram.h index d9dacce89b..4ecfe90f5f 100644 --- a/components/esp_hw_support/include/soc/esp32s3/spiram.h +++ b/components/esp_hw_support/include/soc/esp32s3/spiram.h @@ -76,53 +76,6 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size); */ bool esp_spiram_is_initialized(void); -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS - -extern int _instruction_reserved_start, _instruction_reserved_end; - -/** - * @brief Get the start page number of the instruction in SPI flash - * - * @return start page number - */ -uint32_t instruction_flash_start_page_get(void); -/** - * @brief Get the end page number of the instruction in SPI flash - * - * @return end page number - */ -uint32_t instruction_flash_end_page_get(void); -/** - * @brief Get the offset of instruction from SPI flash to SPI RAM - * - * @return instruction offset - */ -int instruction_flash2spiram_offset(void); -#endif - -#if CONFIG_SPIRAM_RODATA - -extern int _rodata_reserved_start, _rodata_reserved_end; - -/** - * @brief Get the start page number of the rodata in SPI flash - * - * @return start page number - */ -uint32_t rodata_flash_start_page_get(void); -/** - * @brief Get the end page number of the rodata in SPI flash - * - * @return end page number - */ -uint32_t rodata_flash_end_page_get(void); -/** - * @brief Get the offset number of rodata from SPI flash to SPI RAM - * - * @return rodata offset - */ -int rodata_flash2spiram_offset(void); -#endif #ifdef __cplusplus } diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 7f625fd4f4..03d85e8741 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -15,8 +15,9 @@ entries: spiram_psram (noflash) if SPIRAM_MODE_OCT = y: opiram_psram (noflash) - if IDF_TARGET_ESP32S2 = y && SPIRAM: - mmu_psram (noflash) + if SPIRAM: + if IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y: + mmu_psram (noflash) if PERIPH_CTRL_FUNC_IN_IRAM = y: periph_ctrl: periph_module_reset (noflash) periph_ctrl: wifi_module_enable (noflash) diff --git a/components/esp_hw_support/port/esp32s2/mmu_psram.c b/components/esp_hw_support/port/esp32s2/mmu_psram.c index 62485fda95..59a3994595 100644 --- a/components/esp_hw_support/port/esp32s2/mmu_psram.c +++ b/components/esp_hw_support/port/esp32s2/mmu_psram.c @@ -20,6 +20,9 @@ const static char *TAG = "mmu_psram"; //------------------------------------Copy Flash .text to PSRAM-------------------------------------// #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS +extern int _instruction_reserved_start; +extern int _instruction_reserved_end; + static uint32_t instruction_in_spiram; static uint32_t instr_start_page; static uint32_t instr_end_page; @@ -34,6 +37,9 @@ uint32_t instruction_flash_end_page_get(void); //------------------------------------Copy Flash .rodata to PSRAM-------------------------------------// #if CONFIG_SPIRAM_RODATA +extern int _rodata_reserved_start; +extern int _rodata_reserved_end; + static uint32_t rodata_in_spiram; static int rodata_flash2spiram_offs; static uint32_t rodata_start_page; diff --git a/components/esp_hw_support/port/esp32s3/CMakeLists.txt b/components/esp_hw_support/port/esp32s3/CMakeLists.txt index 226230e00c..311a3e20e5 100644 --- a/components/esp_hw_support/port/esp32s3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32s3/CMakeLists.txt @@ -18,7 +18,7 @@ if(NOT BOOTLOADER_BUILD) "esp_crypto_lock.c") if(CONFIG_SPIRAM) - list(APPEND srcs "spiram.c") + list(APPEND srcs "spiram.c" "mmu_psram.c") if(CONFIG_SPIRAM_MODE_QUAD) list(APPEND srcs "spiram_psram.c") diff --git a/components/esp_hw_support/port/esp32s3/mmu_psram.c b/components/esp_hw_support/port/esp32s3/mmu_psram.c new file mode 100644 index 0000000000..bbf9ca4549 --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/mmu_psram.c @@ -0,0 +1,276 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_private/mmu_psram.h" +#include "esp32s3/rom/cache.h" +#include "esp32s3/rom/ets_sys.h" +#include "soc/ext_mem_defs.h" +#include "soc/extmem_reg.h" + +#define MMU_PAGE_SIZE 0x10000 +#define MMU_PAGE_TO_BYTES(page_id) ((page_id) * MMU_PAGE_SIZE) +#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE) + +const static char *TAG = "mmu_psram"; + +//------------------------------------Copy Flash .text to PSRAM-------------------------------------// +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS +extern int _instruction_reserved_start; +extern int _instruction_reserved_end; + +static uint32_t instruction_in_spiram; +static uint32_t instr_start_page; +static uint32_t instr_end_page; +static int instr_flash2spiram_offs; + +uint32_t esp_spiram_instruction_access_enabled(void); +int instruction_flash2spiram_offset(void); +uint32_t instruction_flash_start_page_get(void); +uint32_t instruction_flash_end_page_get(void); +#endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS + + +//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------// +#if CONFIG_SPIRAM_RODATA +extern int _rodata_reserved_start; +extern int _rodata_reserved_end; + +static uint32_t rodata_in_spiram; +static int rodata_flash2spiram_offs; +static uint32_t rodata_start_page; +static uint32_t rodata_end_page; + +uint32_t esp_spiram_rodata_access_enabled(void); +int rodata_flash2spiram_offset(void); +uint32_t rodata_flash_start_page_get(void); +uint32_t rodata_flash_end_page_get(void); +#endif //#if CONFIG_SPIRAM_RODATA + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA +//TODO IDF-4387 +static uint32_t page0_mapped = 0; +static uint32_t page0_page = INVALID_PHY_PAGE; +#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA + + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS +esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page) +{ + uint32_t page_id = start_page; + + /** + * TODO IDF-4387 + * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this. + * FOR NOW, leave these logics just as it used to be. + */ + uint32_t flash_pages = 0; + flash_pages += Cache_Count_Flash_Pages(CACHE_IBUS, &page0_mapped); + if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) { + ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %d B, from %d B to %d B", + MMU_PAGE_TO_BYTES(flash_pages), MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(flash_pages + page_id)); + return ESP_FAIL; + } + + //Enable DBUS, which is used for copying FLASH .text to PSRAM + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS); +#if !CONFIG_FREERTOS_UNICORE + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS); +#endif + + // uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - (uint32_t)&_instruction_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; + // uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE; + + // instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset]; + // instr_start_page &= MMU_VALID_VAL_MASK; + // instr_end_page = instr_start_page + instr_page_cnt - 1; + // instr_flash2spiram_offs = instr_start_page - page_id; + // ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", instr_start_page, page_id, instr_flash2spiram_offs); + + ets_printf(DRAM_STR("_instruction_reserved_end addr is %x\n"), (uint32_t)&_instruction_reserved_start); + uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; + + instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START); + instr_start_page &= MMU_VALID_VAL_MASK; + instr_end_page = instr_start_page + instr_page_cnt - 1; + instr_flash2spiram_offs = instr_start_page - page_id; + ESP_EARLY_LOGE(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", instr_start_page, page_id, instr_flash2spiram_offs); + + + + + + + + + // page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, page_id, &page0_page); + // page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, page_id, &page0_page); + // instruction_in_spiram = 1; + // ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id); + // ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM"); + + page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page); + instruction_in_spiram = 1; + ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id); + ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM"); + + + + + + /** + * Disable DRAM0_BUS. + * .text (instructions) are mapped in `Cache_Flash_To_SPIRAM_Copy` to both `PRO_CACHE_IBUS0` and `PRO_CACHE_IBUS1`. + * + * For now, this bus (DRAM0) is only used for copying, so can be disabled. If it is used later, other code + * should be responsible for enabling it. + */ + REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS); +#if !CONFIG_FREERTOS_UNICORE + REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS); +#endif + *out_page = page_id - start_page; + + return ESP_OK; +} +#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + + + +#if CONFIG_SPIRAM_RODATA +esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page) +{ + uint32_t page_id = start_page; + + /** + * TODO IDF-4387 + * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this. + * FOR NOW, leave these logics just as it used to be. + */ + uint32_t flash_pages = 0; + flash_pages += Cache_Count_Flash_Pages(CACHE_DBUS, &page0_mapped); + if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) { + ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, need to copy to %d B.", MMU_PAGE_TO_BYTES(flash_pages + page_id)); + return ESP_FAIL; + } + + //Enable DBUS, which is used for copying FLASH .text to PSRAM + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS); +#if !CONFIG_FREERTOS_UNICORE + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS); +#endif + + + + + + + // uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - (uint32_t)&_rodata_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; + // uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE; + + // rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset]; + // rodata_start_page &= MMU_VALID_VAL_MASK; + // rodata_end_page = rodata_start_page + rodata_page_cnt - 1; + // rodata_flash2spiram_offs = rodata_start_page - page_id; + // ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", rodata_start_page, page_id, rodata_flash2spiram_offs); + + uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; + rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START); + rodata_start_page &= MMU_VALID_VAL_MASK; + rodata_end_page = rodata_start_page + rodata_page_cnt - 1; + rodata_flash2spiram_offs = rodata_start_page - page_id; + ESP_EARLY_LOGE(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", rodata_start_page, page_id, rodata_flash2spiram_offs); + + + + + + + + + + + + + // page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, page_id, &page0_page); + // page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, page_id, &page0_page); + // page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, page_id, &page0_page); + // page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, page_id, &page0_page); + // rodata_in_spiram = 1; + // ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id); + // ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM"); + + + page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_DBUS, DRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page); + rodata_in_spiram = 1; + ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id); + ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM"); + + /** + * Disable DRAM0_BUS. + * .text (instructions) are mapped in `Cache_Flash_To_SPIRAM_Copy` to both `PRO_CACHE_IBUS0` and `PRO_CACHE_IBUS1`. + * + * For now, this bus (DRAM0) is only used for copying, so can be disabled. If it is used later, other code + * should be responsible for enabling it. + */ + REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS); +#if !CONFIG_FREERTOS_UNICORE + REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS); +#endif + + *out_page = page_id - start_page; + + return ESP_OK; +} +#endif //#if CONFIG_SPIRAM_RODATA + + + + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS +uint32_t esp_spiram_instruction_access_enabled(void) +{ + return instruction_in_spiram; +} + +int instruction_flash2spiram_offset(void) +{ + return instr_flash2spiram_offs; +} + +uint32_t instruction_flash_start_page_get(void) +{ + return instr_start_page; +} + +uint32_t instruction_flash_end_page_get(void) +{ + return instr_end_page; +} +#endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS + +#if CONFIG_SPIRAM_RODATA +uint32_t esp_spiram_rodata_access_enabled(void) +{ + return rodata_in_spiram; +} + +int rodata_flash2spiram_offset(void) +{ + return rodata_flash2spiram_offs; +} + +uint32_t rodata_flash_start_page_get(void) +{ + return rodata_start_page; +} + +uint32_t rodata_flash_end_page_get(void) +{ + return rodata_end_page; +} +#endif //#if CONFIG_SPIRAM_RODATA diff --git a/components/esp_hw_support/port/esp32s3/spiram.c b/components/esp_hw_support/port/esp32s3/spiram.c index 6b6d08bd9b..1bacb0a368 100644 --- a/components/esp_hw_support/port/esp32s3/spiram.c +++ b/components/esp_hw_support/port/esp32s3/spiram.c @@ -24,12 +24,14 @@ #include "spiram_psram.h" #include "hal/mmu_hal.h" #include "hal/cache_ll.h" +#include "esp_private/mmu_psram.h" #define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL #define MMU_PAGE_SIZE (0x10000) #define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#define MMU_PAGE_TO_BYTES(page_id) ((page_id) << 16) #if CONFIG_SPIRAM_SPEED_40M #define PSRAM_SPEED PSRAM_CACHE_S40M @@ -83,12 +85,51 @@ esp_err_t esp_spiram_init(void) ESP_EARLY_LOGI(TAG, "Found %dMB SPI RAM device", psram_physical_size / (1024 * 1024)); ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED); + uint32_t psram_available_size = 0; + ret = psram_get_available_size(&psram_available_size); + assert(ret == ESP_OK); + + + __attribute__((unused)) uint32_t total_available_size = psram_available_size; /** - * TODO IDF-4318 - * Add these feature here: - * - Copy Flash text into PSRAM - * - Copy Flash rodata into PSRAM + * `start_page` is the psram physical address in MMU page size. + * MMU page size on ESP32S2 is 64KB + * e.g.: psram physical address 16 is in page 0 + * + * Here we plan to copy FLASH instructions to psram physical address 0, which is the No.0 page. */ + uint32_t start_page = 0; +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA + uint32_t used_page = 0; +#endif + + //------------------------------------Copy Flash .text to PSRAM-------------------------------------// +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + ret = mmu_config_psram_text_segment(start_page, total_available_size, &used_page); + if (ret != ESP_OK) { + ESP_EARLY_LOGE(TAG, "No enough psram memory for instructon!"); + abort(); + } + start_page += used_page; + psram_available_size -= MMU_PAGE_TO_BYTES(used_page); + ESP_EARLY_LOGV(TAG, "after copy .text, used page is %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size); +#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + + //------------------------------------Copy Flash .rodata to PSRAM-------------------------------------// +#if CONFIG_SPIRAM_RODATA + ret = mmu_config_psram_rodata_segment(start_page, total_available_size, &used_page); + if (ret != ESP_OK) { + ESP_EARLY_LOGE(TAG, "No enough psram memory for rodata!"); + abort(); + } + start_page += used_page; + psram_available_size -= MMU_PAGE_TO_BYTES(used_page); + ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size); +#endif //#if CONFIG_SPIRAM_RODATA + + + + //----------------------------------Map the PSRAM physical range to MMU-----------------------------// uint32_t vaddr_start = 0; extern uint32_t _rodata_reserved_end; @@ -96,10 +137,6 @@ esp_err_t esp_spiram_init(void) vaddr_start = rodata_end_aligned; ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned); - uint32_t psram_available_size = 0; - ret = psram_get_available_size(&psram_available_size); - assert(ret == ESP_OK); - if (vaddr_start + psram_available_size > DRAM0_CACHE_ADDRESS_HIGH) { //Decide these logics when there's a real PSRAM with larger size ESP_EARLY_LOGE(TAG, "Virtual address not enough for PSRAM!"); @@ -108,7 +145,7 @@ esp_err_t esp_spiram_init(void) //On ESP32S3, MMU is shared for both of the cores. Note this when porting `spiram.c` uint32_t actual_mapped_len = 0; - mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, 0, psram_available_size, &actual_mapped_len); + mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, MMU_PAGE_TO_BYTES(start_page), psram_available_size, &actual_mapped_len); ESP_EARLY_LOGV(TAG, "actual_mapped_len is 0x%x bytes", actual_mapped_len); cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, vaddr_start, actual_mapped_len); @@ -204,108 +241,6 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size) return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size); } -//TODO IDF-4318 -// static uint32_t pages_for_flash = 0; -static uint32_t instruction_in_spiram = 0; -static uint32_t rodata_in_spiram = 0; - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS -static int instr_flash2spiram_offs = 0; -static uint32_t instr_start_page = 0; -static uint32_t instr_end_page = 0; -#endif - -#if CONFIG_SPIRAM_RODATA -static int rodata_flash2spiram_offs = 0; -static uint32_t rodata_start_page = 0; -static uint32_t rodata_end_page = 0; -#endif - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA -// Helper macro to make a MMU entry invalid -#define INVALID_PHY_PAGE 0xffff -static uint32_t page0_mapped = 0; -static uint32_t page0_page = INVALID_PHY_PAGE; -#endif - -uint32_t esp_spiram_instruction_access_enabled(void) -{ - return instruction_in_spiram; -} - -uint32_t esp_spiram_rodata_access_enabled(void) -{ - return rodata_in_spiram; -} - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS -esp_err_t esp_spiram_enable_instruction_access(void) -{ - //TODO IDF-4318, `pages_for_flash` will be overwritten, however it influences the psram size to be added to the heap allocator. - abort(); -} -#endif - -#if CONFIG_SPIRAM_RODATA -esp_err_t esp_spiram_enable_rodata_access(void) -{ - //TODO IDF-4318, `pages_for_flash` will be overwritten, however it influences the psram size to be added to the heap allocator. - abort(); -} -#endif - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS -void instruction_flash_page_info_init(void) -{ - uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; - - instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START); - instr_start_page &= MMU_VALID_VAL_MASK; - instr_end_page = instr_start_page + instr_page_cnt - 1; -} - -uint32_t IRAM_ATTR instruction_flash_start_page_get(void) -{ - return instr_start_page; -} - -uint32_t IRAM_ATTR instruction_flash_end_page_get(void) -{ - return instr_end_page; -} - -int IRAM_ATTR instruction_flash2spiram_offset(void) -{ - return instr_flash2spiram_offs; -} -#endif - -#if CONFIG_SPIRAM_RODATA -void rodata_flash_page_info_init(void) -{ - uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE; - - rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START); - rodata_start_page &= MMU_VALID_VAL_MASK; - rodata_end_page = rodata_start_page + rodata_page_cnt - 1; -} - -uint32_t IRAM_ATTR rodata_flash_start_page_get(void) -{ - return rodata_start_page; -} - -uint32_t IRAM_ATTR rodata_flash_end_page_get(void) -{ - return rodata_end_page; -} - -int IRAM_ATTR rodata_flash2spiram_offset(void) -{ - return rodata_flash2spiram_offs; -} -#endif - /* Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first, otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this. diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 6b5e529a3a..e3e33bdb2f 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -37,6 +37,7 @@ #include "esp32s3/rtc.h" #include "esp32s3/rom/cache.h" #include "esp32s3/spiram.h" +#include "esp_private/mmu_psram.h" #include "esp_memprot.h" #include "soc/assist_debug_reg.h" #include "soc/system_reg.h" @@ -444,26 +445,8 @@ void IRAM_ATTR call_start_cpu0(void) #endif //CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382 #endif //CONFIG_SPIRAM_MEMTEST - //TODO: IDF-4382 + #if CONFIG_IDF_TARGET_ESP32S3 -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS - extern void instruction_flash_page_info_init(void); - instruction_flash_page_info_init(); -#endif -#if CONFIG_SPIRAM_RODATA - extern void rodata_flash_page_info_init(void); - rodata_flash_page_info_init(); -#endif - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS - extern void esp_spiram_enable_instruction_access(void); - esp_spiram_enable_instruction_access(); -#endif -#if CONFIG_SPIRAM_RODATA - extern void esp_spiram_enable_rodata_access(void); - esp_spiram_enable_rodata_access(); -#endif - int s_instr_flash2spiram_off = 0; int s_rodata_flash2spiram_off = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index 4dd2f508b3..12e8b38c0b 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -31,6 +31,7 @@ #include "soc/extmem_reg.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/cache.h" +#include "esp_private/mmu_psram.h" #include "esp32s3/spiram.h" #include "soc/extmem_reg.h" #elif CONFIG_IDF_TARGET_ESP32C3 @@ -52,6 +53,16 @@ #define PAGES_LIMIT ((SOC_MMU_IROM0_PAGES_END > SOC_MMU_DROM0_PAGES_END) ? SOC_MMU_IROM0_PAGES_END:SOC_MMU_DROM0_PAGES_END) #define INVALID_PHY_PAGE(page_size) ((page_size) - 1) +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS +extern int _instruction_reserved_start; +extern int _instruction_reserved_end; +#endif + +#if CONFIG_SPIRAM_RODATA +extern int _rodata_reserved_start; +extern int _rodata_reserved_end; +#endif + #if !CONFIG_SPI_FLASH_ROM_IMPL typedef struct mmap_entry_{