feat(xip_psram): support xip psram feature on esp32p4

This commit is contained in:
Armando
2024-05-29 10:02:44 +08:00
parent f9b58b0c73
commit 48e06fafea
52 changed files with 970 additions and 163 deletions
+73 -25
View File
@@ -5,7 +5,7 @@
*/
/*----------------------------------------------------------------------------------------------------
* Abstraction layer for PSRAM. PSRAM device related registers and MMU/Cache related code shouls be
* Abstraction layer for PSRAM. PSRAM device related registers and MMU/Cache related code should be
* abstracted to lower layers.
*
* When we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
@@ -20,6 +20,7 @@
#include "hal/mmu_hal.h"
#include "hal/mmu_ll.h"
#include "hal/cache_ll.h"
#include "soc/soc_caps.h"
#include "esp_private/esp_psram_io.h"
#include "esp_private/esp_psram_extram.h"
#include "esp_private/mmu_psram_flash.h"
@@ -43,6 +44,12 @@
#define PSRAM_MEM_8BIT_ALIGNED 0
#define PSRAM_MEM_32BIT_ALIGNED 1
#if CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
#define PSRAM_EARLY_LOGI ESP_DRAM_LOGI
#else
#define PSRAM_EARLY_LOGI ESP_EARLY_LOGI
#endif
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
extern uint8_t _ext_ram_bss_start;
extern uint8_t _ext_ram_bss_end;
@@ -80,7 +87,7 @@ typedef struct {
} psram_ctx_t;
static psram_ctx_t s_psram_ctx;
static const char* TAG = "esp_psram";
static const DRAM_ATTR char TAG[] = "esp_psram";
ESP_SYSTEM_INIT_FN(init_psram, CORE, BIT(0), 103)
{
@@ -120,7 +127,7 @@ static void IRAM_ATTR s_mapping(int v_start, int size)
}
#endif //CONFIG_IDF_TARGET_ESP32
esp_err_t esp_psram_init(void)
static esp_err_t s_psram_chip_init(uint32_t *out_available_size)
{
if (s_psram_ctx.is_initialised) {
return ESP_ERR_INVALID_STATE;
@@ -140,8 +147,8 @@ esp_err_t esp_psram_init(void)
ret = esp_psram_impl_get_physical_size(&psram_physical_size);
assert(ret == ESP_OK);
ESP_EARLY_LOGI(TAG, "Found %" PRIu32 "MB PSRAM device", psram_physical_size / (1024 * 1024));
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
PSRAM_EARLY_LOGI(TAG, "Found %" PRIu32 "MB PSRAM device", psram_physical_size / (1024 * 1024));
PSRAM_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in normal (1-core) mode.");
@@ -154,7 +161,16 @@ esp_err_t esp_psram_init(void)
ret = esp_psram_impl_get_available_size(&psram_available_size);
assert(ret == ESP_OK);
__attribute__((unused)) uint32_t total_available_size = psram_available_size;
*out_available_size = psram_available_size;
return ESP_OK;
}
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
static void s_xip_psram_placement(uint32_t *psram_available_size, uint32_t *out_start_page)
{
__attribute__((unused)) uint32_t total_available_size = *psram_available_size;
uint32_t available_size = *psram_available_size;
/**
* `start_page` is the psram physical address in MMU page size.
* MMU page size on ESP32S2 is 64KB
@@ -162,22 +178,9 @@ esp_err_t esp_psram_init(void)
*
* Here we plan to copy FLASH instructions to psram physical address 0, which is the No.0 page.
*/
__attribute__((unused)) uint32_t start_page = 0;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
uint32_t start_page = 0;
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 %" PRIu32 ", start_page is %" PRIu32 ", psram_available_size is %" PRIu32 " B", used_page, start_page, psram_available_size);
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
esp_err_t ret = ESP_FAIL;
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
#if CONFIG_SPIRAM_RODATA
@@ -187,10 +190,30 @@ esp_err_t esp_psram_init(void)
abort();
}
start_page += used_page;
psram_available_size -= MMU_PAGE_TO_BYTES(used_page);
ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %" PRIu32 ", start_page is %" PRIu32 ", psram_available_size is %" PRIu32 " B", used_page, start_page, psram_available_size);
available_size -= MMU_PAGE_TO_BYTES(used_page);
ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %d, start_page is %d, available_size is %d B", used_page, start_page, available_size);
#endif //#if CONFIG_SPIRAM_RODATA
//------------------------------------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;
available_size -= MMU_PAGE_TO_BYTES(used_page);
ESP_EARLY_LOGV(TAG, "after copy .text, used page is %" PRIu32 ", start_page is %" PRIu32 ", psram_available_size is %" PRIu32 " B", used_page, start_page, psram_available_size);
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
*psram_available_size = available_size;
*out_start_page = start_page;
}
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
static void s_psram_mapping(uint32_t psram_available_size, uint32_t start_page)
{
esp_err_t ret = ESP_FAIL;
//----------------------------------Map the PSRAM physical range to MMU-----------------------------//
/**
* @note 2
@@ -213,7 +236,7 @@ esp_err_t esp_psram_init(void)
s_mapping((int)v_start_8bit_aligned, size_to_map);
#else
uint32_t actual_mapped_len = 0;
#if MMU_LL_MMU_PER_TARGET
#if SOC_MMU_PER_EXT_MEM_TARGET
mmu_hal_map_region(1, MMU_TARGET_PSRAM0, (intptr_t)v_start_8bit_aligned, MMU_PAGE_TO_BYTES(start_page), size_to_map, &actual_mapped_len);
#else
mmu_hal_map_region(0, MMU_TARGET_PSRAM0, (intptr_t)v_start_8bit_aligned, MMU_PAGE_TO_BYTES(start_page), size_to_map, &actual_mapped_len);
@@ -280,7 +303,7 @@ esp_err_t esp_psram_init(void)
}
/*------------------------------------------------------------------------------
* After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESSS ANYMORE!
* After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESS ANYMORE!
*----------------------------------------------------------------------------*/
//------------------------------------Configure .bss in PSRAM-------------------------------------//
@@ -302,6 +325,31 @@ esp_err_t esp_psram_init(void)
#if CONFIG_IDF_TARGET_ESP32
s_psram_ctx.regions_to_heap[PSRAM_MEM_8BIT_ALIGNED].size -= esp_himem_reserved_area_size() - 1;
#endif
}
esp_err_t esp_psram_init(void)
{
esp_err_t ret = ESP_FAIL;
uint32_t psram_available_size = 0;
ret = s_psram_chip_init(&psram_available_size);
if (ret != ESP_OK) {
return ret;
}
/**
* `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.
*/
__attribute__((unused)) uint32_t start_page = 0;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
s_xip_psram_placement(&psram_available_size, &start_page);
#endif
s_psram_mapping(psram_available_size, start_page);
//will be removed, TODO: IDF-6944
#if CONFIG_IDF_TARGET_ESP32