From 2cb93cd926097d3eb8cad620802ccfac5435ebd7 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Thu, 20 Feb 2025 16:18:20 +0530 Subject: [PATCH] feat(esp_psram): Add some helper APIs to get usable PSRAM memory size --- .../include/esp_private/mmu_psram_flash.h | 18 ++++++++- components/esp_psram/mmu_psram_flash.c | 35 ++++++++++++------ components/esp_psram/mmu_psram_flash_v2.c | 37 ++++++++++++------- 3 files changed, 64 insertions(+), 26 deletions(-) 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..e70205be53 100644 --- a/components/esp_psram/include/esp_private/mmu_psram_flash.h +++ b/components/esp_psram/include/esp_private/mmu_psram_flash.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,6 +39,14 @@ extern "C" { Part 1 APIs (See @Backgrounds on top of this file) -------------------------------------------------------------------------------*/ #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + +/** + * @brief Calculates the size of memory that would be used for copying flash texts into PSRAM (in bytes) + * + * @return size_t size of memory that would be used for copying flash texts into PSRAM (in bytes) + */ +size_t mmu_psram_get_text_segment_length(void); + /** * @brief Copy Flash texts to PSRAM * @@ -50,6 +58,14 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS #if CONFIG_SPIRAM_RODATA + +/** + * @brief Calculates the size of memory that would be used for copying flash rodata into PSRAM (in bytes) + * + * @return size_t size of memory that would be used for copying flash rodata into PSRAM (in bytes) + */ +size_t mmu_psram_get_rodata_segment_length(void); + /** * @brief Copy Flash rodata to PSRAM * diff --git a/components/esp_psram/mmu_psram_flash.c b/components/esp_psram/mmu_psram_flash.c index bb9288410a..faa0510307 100644 --- a/components/esp_psram/mmu_psram_flash.c +++ b/components/esp_psram/mmu_psram_flash.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,10 +44,8 @@ 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) +size_t mmu_psram_get_text_segment_length(void) { - uint32_t page_id = start_page; - uint32_t flash_pages = 0; #if CONFIG_IDF_TARGET_ESP32S2 flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS0, &page0_mapped); @@ -55,9 +53,17 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size #elif CONFIG_IDF_TARGET_ESP32S3 flash_pages += Cache_Count_Flash_Pages(CACHE_IBUS, &page0_mapped); #endif - if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) { + return MMU_PAGE_TO_BYTES(flash_pages); +} + +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; + + uint32_t flash_bytes = mmu_psram_get_text_segment_length(); + if ((flash_bytes + MMU_PAGE_TO_BYTES(page_id)) > psram_size) { ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %" PRIu32 " B, from %" PRIu32 " B to %" PRIu32 " B", - MMU_PAGE_TO_BYTES(flash_pages), MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(flash_pages + page_id)); + flash_bytes, MMU_PAGE_TO_BYTES(start_page), flash_bytes + MMU_PAGE_TO_BYTES(page_id)); return ESP_FAIL; } @@ -87,10 +93,8 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size #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) +size_t mmu_psram_get_rodata_segment_length(void) { - uint32_t page_id = start_page; - uint32_t flash_pages = 0; #if CONFIG_IDF_TARGET_ESP32S2 flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS2, &page0_mapped); @@ -100,8 +104,17 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si #elif CONFIG_IDF_TARGET_ESP32S3 flash_pages += Cache_Count_Flash_Pages(CACHE_DBUS, &page0_mapped); #endif - 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 %" PRIu32 " B.", MMU_PAGE_TO_BYTES(flash_pages + page_id)); + return MMU_PAGE_TO_BYTES(flash_pages); +} + +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; + + uint32_t flash_bytes = mmu_psram_get_rodata_segment_length(); + + if ((flash_bytes + MMU_PAGE_TO_BYTES(page_id)) > psram_size) { + ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, need to copy to %" PRIu32 " B.", flash_bytes + MMU_PAGE_TO_BYTES(page_id)); return ESP_FAIL; } diff --git a/components/esp_psram/mmu_psram_flash_v2.c b/components/esp_psram/mmu_psram_flash_v2.c index fe9a8407b2..c8d45ce112 100644 --- a/components/esp_psram/mmu_psram_flash_v2.c +++ b/components/esp_psram/mmu_psram_flash_v2.c @@ -84,10 +84,14 @@ static uint32_t s_do_load_from_flash(uint32_t flash_paddr_start, uint32_t size, #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS +size_t mmu_psram_get_text_segment_length(void) +{ + return ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, CONFIG_MMU_PAGE_SIZE) - ALIGN_DOWN_BY((uint32_t)&_instruction_reserved_start, CONFIG_MMU_PAGE_SIZE); +} + esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page) { - size_t irom_size = ALIGN_UP_BY((uint32_t)&_instruction_reserved_end, CONFIG_MMU_PAGE_SIZE) - ALIGN_DOWN_BY((uint32_t)&_instruction_reserved_start, CONFIG_MMU_PAGE_SIZE); - s_irom_size = irom_size; + s_irom_size = mmu_psram_get_text_segment_length(); uint32_t flash_drom_paddr_start = 0; uint32_t flash_irom_paddr_start = 0; @@ -95,8 +99,8 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size 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); - 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); + if ((MMU_PAGE_TO_BYTES(start_page) + s_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", s_irom_size, MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + s_irom_size); return ESP_ERR_NO_MEM; } @@ -106,22 +110,27 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size ESP_EARLY_LOGV(TAG, "flash_irom_paddr_start: 0x%"PRIx32", MMU_PAGE_TO_BYTES(start_page): 0x%"PRIx32", s_irom_paddr_offset: 0x%"PRIx32", s_irom_vaddr_start: 0x%"PRIx32, flash_irom_paddr_start, MMU_PAGE_TO_BYTES(start_page), s_irom_paddr_offset, s_irom_vaddr_start); uint32_t mapped_size = 0; - mapped_size = s_do_load_from_flash(flash_irom_paddr_start, irom_size, irom_load_addr_aligned, MMU_PAGE_TO_BYTES(start_page)); - cache_hal_writeback_addr(irom_load_addr_aligned, irom_size); + mapped_size = s_do_load_from_flash(flash_irom_paddr_start, s_irom_size, irom_load_addr_aligned, MMU_PAGE_TO_BYTES(start_page)); + cache_hal_writeback_addr(irom_load_addr_aligned, s_irom_size); ESP_EARLY_LOGV(TAG, "after mapping text, starting from paddr=0x%08"PRIx32" and vaddr=0x%08"PRIx32", 0x%"PRIx32" bytes are mapped", MMU_PAGE_TO_BYTES(start_page), irom_load_addr_aligned, mapped_size); - *out_page = BYTES_TO_MMU_PAGE(irom_size); + *out_page = BYTES_TO_MMU_PAGE(s_irom_size); return ESP_OK; } #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS #if CONFIG_SPIRAM_RODATA + +size_t mmu_psram_get_rodata_segment_length(void) +{ + return ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, CONFIG_MMU_PAGE_SIZE) - ALIGN_DOWN_BY((uint32_t)&_rodata_reserved_start, CONFIG_MMU_PAGE_SIZE); +} + esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page) { - size_t drom_size = ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, CONFIG_MMU_PAGE_SIZE) - ALIGN_DOWN_BY((uint32_t)&_rodata_reserved_start, CONFIG_MMU_PAGE_SIZE); - s_drom_size = drom_size; + s_drom_size = mmu_psram_get_rodata_segment_length(); uint32_t flash_drom_paddr_start = 0; uint32_t flash_irom_paddr_start = 0; @@ -129,8 +138,8 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si 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); - 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); + if ((MMU_PAGE_TO_BYTES(start_page) + s_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", s_drom_size, MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + s_drom_size); return ESP_ERR_NO_MEM; } @@ -140,12 +149,12 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si ESP_EARLY_LOGV(TAG, "flash_drom_paddr_start: 0x%"PRIx32", MMU_PAGE_TO_BYTES(start_page): 0x%"PRIx32", s_drom_paddr_offset: 0x%"PRIx32", s_drom_vaddr_start: 0x%"PRIx32, flash_drom_paddr_start, MMU_PAGE_TO_BYTES(start_page), s_drom_paddr_offset, s_drom_vaddr_start); uint32_t mapped_size = 0; - mapped_size = s_do_load_from_flash(flash_drom_paddr_start, drom_size, drom_load_addr_aligned, MMU_PAGE_TO_BYTES(start_page)); - cache_hal_writeback_addr(drom_load_addr_aligned, drom_size); + mapped_size = s_do_load_from_flash(flash_drom_paddr_start, s_drom_size, drom_load_addr_aligned, MMU_PAGE_TO_BYTES(start_page)); + cache_hal_writeback_addr(drom_load_addr_aligned, s_drom_size); ESP_EARLY_LOGV(TAG, "after mapping rodata, starting from paddr=0x%08"PRIx32" and vaddr=0x%08"PRIx32", 0x%"PRIx32" bytes are mapped", MMU_PAGE_TO_BYTES(start_page), drom_load_addr_aligned, mapped_size); - *out_page = BYTES_TO_MMU_PAGE(drom_size); + *out_page = BYTES_TO_MMU_PAGE(s_drom_size); return ESP_OK; }