mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(xip_psram): support xip psram feature on esp32p4
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user