Skip to content

Commit f58c78b

Browse files
committed
fix(esp_psram): Fix loading PSRAM XIP segments after PMP split has been configured
1 parent ab229a3 commit f58c78b

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

components/esp_psram/xip_impl/mmu_psram_flash_v2.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ static int s_drom_paddr_offset;
5454
static uint32_t s_do_load_from_flash(uint32_t flash_paddr_start, uint32_t size, uint32_t target_vaddr_start, uint32_t target_paddr_start)
5555
{
5656
uint32_t flash_end_page_vaddr = SOC_DRAM_FLASH_ADDRESS_HIGH - CONFIG_MMU_PAGE_SIZE;
57+
uint32_t psram_vaddr_start;
58+
59+
#if !CONFIG_SPIRAM_BOOT_INIT
60+
// Once PMP sets up the IROM/DROM split, the target_vaddr_start would not be configured to write (W) access. Thus, performing s_do_load_from_flash() post the PMP split
61+
// is configured, copying the flash contents to the PSRAM would generate a store access fault.
62+
// Thus, we need to choose a different PSRAM virtual address (that would have the PMP write (W) access) to map and copy the flash contents into the PSRAM.
63+
// Choosing the second last PSRAM page instead of the last one, to avoid overlap with flash_end_page_vaddr for targets that share the same flash and psram virtual space.
64+
uint32_t psram_second_last_page_vaddr = SOC_DRAM_PSRAM_ADDRESS_HIGH - 2 * CONFIG_MMU_PAGE_SIZE;
65+
assert((psram_second_last_page_vaddr % CONFIG_MMU_PAGE_SIZE) == 0);
66+
#endif
67+
5768
ESP_EARLY_LOGV(TAG, "flash_paddr_start: 0x%"PRIx32", flash_end_page_vaddr: 0x%"PRIx32", size: 0x%"PRIx32", target_vaddr_start: 0x%"PRIx32, flash_paddr_start, flash_end_page_vaddr, size, target_vaddr_start);
5869
assert((flash_paddr_start % CONFIG_MMU_PAGE_SIZE) == 0);
5970
assert((flash_end_page_vaddr % CONFIG_MMU_PAGE_SIZE) == 0);
@@ -62,15 +73,28 @@ static uint32_t s_do_load_from_flash(uint32_t flash_paddr_start, uint32_t size,
6273
uint32_t mapped_size = 0;
6374
while (mapped_size < size) {
6475
uint32_t actual_mapped_len = 0;
65-
mmu_hal_map_region(MMU_LL_PSRAM_MMU_ID, MMU_TARGET_PSRAM0, target_vaddr_start, target_paddr_start + mapped_size, CONFIG_MMU_PAGE_SIZE, &actual_mapped_len);
76+
#if !CONFIG_SPIRAM_BOOT_INIT
77+
psram_vaddr_start = psram_second_last_page_vaddr;
78+
#else
79+
psram_vaddr_start = target_vaddr_start;
80+
#endif /* !CONFIG_SPIRAM_BOOT_INIT*/
81+
82+
mmu_hal_map_region(MMU_LL_PSRAM_MMU_ID, MMU_TARGET_PSRAM0, psram_vaddr_start, target_paddr_start + mapped_size, CONFIG_MMU_PAGE_SIZE, &actual_mapped_len);
6683
assert(actual_mapped_len == CONFIG_MMU_PAGE_SIZE);
6784

6885
mmu_hal_map_region(MMU_LL_FLASH_MMU_ID, MMU_TARGET_FLASH0, flash_end_page_vaddr, flash_paddr_start + mapped_size, CONFIG_MMU_PAGE_SIZE, &actual_mapped_len);
6986
assert(actual_mapped_len == CONFIG_MMU_PAGE_SIZE);
7087

71-
cache_hal_invalidate_addr(target_vaddr_start, CONFIG_MMU_PAGE_SIZE);
88+
cache_hal_invalidate_addr(psram_vaddr_start, CONFIG_MMU_PAGE_SIZE);
7289
cache_hal_invalidate_addr(flash_end_page_vaddr, CONFIG_MMU_PAGE_SIZE);
73-
memcpy((void *)target_vaddr_start, (void *)flash_end_page_vaddr, CONFIG_MMU_PAGE_SIZE);
90+
memcpy((void *)psram_vaddr_start, (void *)flash_end_page_vaddr, CONFIG_MMU_PAGE_SIZE);
91+
92+
#if !CONFIG_SPIRAM_BOOT_INIT
93+
cache_hal_writeback_addr(psram_vaddr_start, CONFIG_MMU_PAGE_SIZE);
94+
mmu_hal_map_region(MMU_LL_PSRAM_MMU_ID, MMU_TARGET_PSRAM0, target_vaddr_start, target_paddr_start + mapped_size, CONFIG_MMU_PAGE_SIZE, &actual_mapped_len);
95+
assert(actual_mapped_len == CONFIG_MMU_PAGE_SIZE);
96+
cache_hal_invalidate_addr(target_vaddr_start, CONFIG_MMU_PAGE_SIZE);
97+
#endif /* !CONFIG_SPIRAM_BOOT_INIT */
7498

7599
ESP_EARLY_LOGV(TAG, "target_vaddr_start: 0x%"PRIx32, target_vaddr_start);
76100
mapped_size += CONFIG_MMU_PAGE_SIZE;

0 commit comments

Comments
 (0)