diff --git a/components/esp32s2/cpu_start.c b/components/esp32s2/cpu_start.c index 2b9488e35b..24a7230870 100644 --- a/components/esp32s2/cpu_start.c +++ b/components/esp32s2/cpu_start.c @@ -199,6 +199,15 @@ void IRAM_ATTR call_start_cpu0(void) } #endif +#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(); diff --git a/components/esp32s2/include/esp32s2/spiram.h b/components/esp32s2/include/esp32s2/spiram.h index d7320c1af5..ff6bfc52d9 100644 --- a/components/esp32s2/include/esp32s2/spiram.h +++ b/components/esp32s2/include/esp32s2/spiram.h @@ -91,6 +91,54 @@ void esp_spiram_writeback_cache(void); */ esp_err_t esp_spiram_reserve_dma_pool(size_t size); +#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 } #endif diff --git a/components/esp32s2/ld/esp32s2.project.ld.in b/components/esp32s2/ld/esp32s2.project.ld.in index ba76cef9c5..59985e8226 100644 --- a/components/esp32s2/ld/esp32s2.project.ld.in +++ b/components/esp32s2/ld/esp32s2.project.ld.in @@ -251,6 +251,7 @@ SECTIONS /* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */ .flash.rodata : ALIGN(0x10) { + _rodata_reserved_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */ @@ -308,12 +309,14 @@ SECTIONS *(.tbss) *(.tbss.*) _thread_local_end = ABSOLUTE(.); + _rodata_reserved_end = ABSOLUTE(.); . = ALIGN(4); } >default_rodata_seg .flash.text : { _stext = .; + _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); mapping[flash_text] @@ -324,6 +327,7 @@ SECTIONS *(.fini) *(.gnu.version) _text_end = ABSOLUTE(.); + _instruction_reserved_end = ABSOLUTE(.); _etext = .; /* Similar to _iram_start, this symbol goes here so it is diff --git a/components/esp32s2/spiram.c b/components/esp32s2/spiram.c index b7bc751cad..89a6367c5e 100644 --- a/components/esp32s2/spiram.c +++ b/components/esp32s2/spiram.c @@ -161,6 +161,18 @@ static uint32_t page0_page = INVALID_PHY_PAGE; static uint32_t instrcution_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 + uint32_t esp_spiram_instruction_access_enabled(void) { return instrcution_in_spiram; @@ -171,6 +183,7 @@ 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) { uint32_t pages_in_flash = 0; @@ -181,12 +194,19 @@ esp_err_t esp_spiram_enable_instruction_access(void) return ESP_FAIL; } ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM"); + uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; + uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START + instr_mmu_offset*sizeof(uint32_t)); + mmu_value &= MMU_ADDRESS_MASK; + instr_flash2spiram_offs = mmu_value - pages_for_flash; + ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, pages_for_flash, &page0_page); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, pages_for_flash, &page0_page); instrcution_in_spiram = 1; return ESP_OK; } +#endif +#if CONFIG_SPIRAM_RODATA esp_err_t esp_spiram_enable_rodata_access(void) { uint32_t pages_in_flash = 0; @@ -201,6 +221,11 @@ esp_err_t esp_spiram_enable_rodata_access(void) } ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM"); + uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; + uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START + rodata_mmu_offset*sizeof(uint32_t)); + mmu_value &= MMU_ADDRESS_MASK; + rodata_flash2spiram_offs = mmu_value - pages_for_flash; + ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, rodata_flash2spiram_offs); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, pages_for_flash, &page0_page); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, pages_for_flash, &page0_page); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, pages_for_flash, &page0_page); @@ -208,6 +233,61 @@ esp_err_t esp_spiram_enable_rodata_access(void) rodata_in_spiram = 1; return ESP_OK; } +#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; + uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; + + instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START + instr_mmu_offset*sizeof(uint32_t)); + instr_start_page &= MMU_ADDRESS_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 - SOC_DROM_LOW + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE; + uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; + + rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START + rodata_mmu_offset*sizeof(uint32_t)); + rodata_start_page &= MMU_ADDRESS_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 esp_err_t esp_spiram_init(void) { diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c index 1d8a3fb570..0c27c81d8c 100644 --- a/components/spi_flash/cache_utils.c +++ b/components/spi_flash/cache_utils.c @@ -467,11 +467,11 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable uint32_t instruction_use_spiram = 0; uint32_t rodata_use_spiram = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS - extern uint32_t esp_spiram_instruction_access_enabled(); + extern uint32_t esp_spiram_instruction_access_enabled(void); instruction_use_spiram = esp_spiram_instruction_access_enabled(); #endif #if CONFIG_SPIRAM_RODATA - extern uint32_t esp_spiram_rodata_access_enabled(); + extern uint32_t esp_spiram_rodata_access_enabled(void); rodata_use_spiram = esp_spiram_rodata_access_enabled(); #endif diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index 54055d7747..6789d4211a 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -378,15 +378,26 @@ uint32_t spi_flash_cache2phys(const void *cached) { intptr_t c = (intptr_t)cached; size_t cache_page; + int offset = 0; if (c >= VADDR1_START_ADDR && c < VADDR1_FIRST_USABLE_ADDR) { /* IRAM address, doesn't map to flash */ return SPI_FLASH_CACHE2PHYS_FAIL; } else if (c < VADDR1_FIRST_USABLE_ADDR) { /* expect cache is in DROM */ cache_page = (c - VADDR0_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + DROM0_PAGES_START; +#if CONFIG_SPIRAM_RODATA + if (c >= (uint32_t)&_rodata_reserved_start && c <= (uint32_t)&_rodata_reserved_end) { + offset = rodata_flash2spiram_offset(); + } +#endif } else { /* expect cache is in IROM */ cache_page = (c - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START; +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + if (c >= (uint32_t)&_instruction_reserved_start && c <= (uint32_t)&_instruction_reserved_end) { + offset = instruction_flash2spiram_offset(); + } +#endif } if (cache_page >= PAGES_LIMIT) { @@ -398,7 +409,7 @@ uint32_t spi_flash_cache2phys(const void *cached) /* page is not mapped */ return SPI_FLASH_CACHE2PHYS_FAIL; } - uint32_t phys_offs = (phys_page & MMU_ADDR_MASK)* SPI_FLASH_MMU_PAGE_SIZE; + uint32_t phys_offs = ((phys_page & MMU_ADDR_MASK) + offset) * SPI_FLASH_MMU_PAGE_SIZE; return phys_offs | (c & (SPI_FLASH_MMU_PAGE_SIZE-1)); } @@ -422,7 +433,24 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me spi_flash_disable_interrupts_caches_and_other_cpu(); DPORT_INTERRUPT_DISABLE(); for (int i = start; i < end; i++) { - if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) { + uint32_t mmu_value = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]); +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) { + if (mmu_value & MMU_ACCESS_SPIRAM) { + mmu_value += instruction_flash2spiram_offset(); + mmu_value = (mmu_value & MMU_ADDR_MASK) | MMU_ACCESS_FLASH; + } + } +#endif +#if CONFIG_SPIRAM_RODATA + if (phys_page >= rodata_flash_start_page_get() && phys_page <= rodata_flash_start_page_get()) { + if (mmu_value & MMU_ACCESS_SPIRAM) { + mmu_value += rodata_flash2spiram_offset(); + mmu_value = (mmu_value & MMU_ADDR_MASK) | MMU_ACCESS_FLASH; + } + } +#endif + if (mmu_value == PAGE_IN_FLASH(phys_page)) { i -= page_delta; intptr_t cache_page = base + (SPI_FLASH_MMU_PAGE_SIZE * i); DPORT_INTERRUPT_RESTORE(); diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index 0432d6a0a1..ba088a3979 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -539,7 +539,7 @@ UT_034: UT_035: extends: .unit_test_s2_template - parallel: 34 + parallel: 36 tags: - ESP32S2_IDF - UT_T1_1 diff --git a/tools/unit-test-app/configs/spi_flash_config_1_s2 b/tools/unit-test-app/configs/spi_flash_config_1_s2 new file mode 100644 index 0000000000..df3df47e54 --- /dev/null +++ b/tools/unit-test-app/configs/spi_flash_config_1_s2 @@ -0,0 +1,5 @@ +TEST_COMPONENTS=spi_flash +CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=n +CONFIG_IDF_TARGET="esp32s2" diff --git a/tools/unit-test-app/configs/spi_flash_config_2_s2 b/tools/unit-test-app/configs/spi_flash_config_2_s2 new file mode 100644 index 0000000000..dff40d8377 --- /dev/null +++ b/tools/unit-test-app/configs/spi_flash_config_2_s2 @@ -0,0 +1,5 @@ +TEST_COMPONENTS=spi_flash +CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y +CONFIG_SPIRAM_RODATA=y +CONFIG_IDF_TARGET="esp32s2" diff --git a/tools/unit-test-app/configs/spi_flash_config_3_s2 b/tools/unit-test-app/configs/spi_flash_config_3_s2 new file mode 100644 index 0000000000..7d79b240f0 --- /dev/null +++ b/tools/unit-test-app/configs/spi_flash_config_3_s2 @@ -0,0 +1,5 @@ +TEST_COMPONENTS=spi_flash +CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=n +CONFIG_SPIRAM_RODATA=y +CONFIG_IDF_TARGET="esp32s2"