feat(esp_psram): Add some helper APIs to get usable PSRAM memory size

This commit is contained in:
harshal.patil
2025-02-20 16:18:20 +05:30
parent 21bd94f116
commit 2cb93cd926
3 changed files with 64 additions and 26 deletions

View File

@ -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
*

View File

@ -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;
}

View File

@ -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;
}