forked from espressif/esp-idf
psram: support s3 copy flash to psram
This commit is contained in:
@@ -17,9 +17,6 @@ extern "C" {
|
|||||||
esp_err_t mmu_map_psram(uint32_t start_paddr, uint32_t map_length, uint32_t *out_start_vaddr);
|
esp_err_t mmu_map_psram(uint32_t start_paddr, uint32_t map_length, uint32_t *out_start_vaddr);
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
extern int _instruction_reserved_start;
|
|
||||||
extern int _instruction_reserved_end;
|
|
||||||
|
|
||||||
esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
|
esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,9 +42,6 @@ int instruction_flash2spiram_offset(void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
#if CONFIG_SPIRAM_RODATA
|
||||||
extern int _rodata_reserved_start;
|
|
||||||
extern int _rodata_reserved_end;
|
|
||||||
|
|
||||||
esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
|
esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the start page number of the instruction in SPI flash
|
||||||
|
*
|
||||||
|
* @return start page number
|
||||||
|
*/
|
||||||
|
uint32_t instruction_flash_start_page_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the end page number of the instruction in SPI flash
|
||||||
|
*
|
||||||
|
* @return end page number
|
||||||
|
*/
|
||||||
|
uint32_t instruction_flash_end_page_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the offset of instruction from SPI flash to SPI RAM
|
||||||
|
*
|
||||||
|
* @return instruction offset
|
||||||
|
*/
|
||||||
|
int instruction_flash2spiram_offset(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_RODATA
|
||||||
|
esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the start page number of the rodata in SPI flash
|
||||||
|
*
|
||||||
|
* @return start page number
|
||||||
|
*/
|
||||||
|
uint32_t rodata_flash_start_page_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the end page number of the rodata in SPI flash
|
||||||
|
*
|
||||||
|
* @return end page number
|
||||||
|
*/
|
||||||
|
uint32_t rodata_flash_end_page_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the offset number of rodata from SPI flash to SPI RAM
|
||||||
|
*
|
||||||
|
* @return rodata offset
|
||||||
|
*/
|
||||||
|
int rodata_flash2spiram_offset(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -76,53 +76,6 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size);
|
|||||||
*/
|
*/
|
||||||
bool esp_spiram_is_initialized(void);
|
bool esp_spiram_is_initialized(void);
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
|
||||||
|
|
||||||
extern int _instruction_reserved_start, _instruction_reserved_end;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the start page number of the instruction in SPI flash
|
|
||||||
*
|
|
||||||
* @return start page number
|
|
||||||
*/
|
|
||||||
uint32_t instruction_flash_start_page_get(void);
|
|
||||||
/**
|
|
||||||
* @brief Get the end page number of the instruction in SPI flash
|
|
||||||
*
|
|
||||||
* @return end page number
|
|
||||||
*/
|
|
||||||
uint32_t instruction_flash_end_page_get(void);
|
|
||||||
/**
|
|
||||||
* @brief Get the offset of instruction from SPI flash to SPI RAM
|
|
||||||
*
|
|
||||||
* @return instruction offset
|
|
||||||
*/
|
|
||||||
int instruction_flash2spiram_offset(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
|
||||||
|
|
||||||
extern int _rodata_reserved_start, _rodata_reserved_end;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the start page number of the rodata in SPI flash
|
|
||||||
*
|
|
||||||
* @return start page number
|
|
||||||
*/
|
|
||||||
uint32_t rodata_flash_start_page_get(void);
|
|
||||||
/**
|
|
||||||
* @brief Get the end page number of the rodata in SPI flash
|
|
||||||
*
|
|
||||||
* @return end page number
|
|
||||||
*/
|
|
||||||
uint32_t rodata_flash_end_page_get(void);
|
|
||||||
/**
|
|
||||||
* @brief Get the offset number of rodata from SPI flash to SPI RAM
|
|
||||||
*
|
|
||||||
* @return rodata offset
|
|
||||||
*/
|
|
||||||
int rodata_flash2spiram_offset(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,9 @@ entries:
|
|||||||
spiram_psram (noflash)
|
spiram_psram (noflash)
|
||||||
if SPIRAM_MODE_OCT = y:
|
if SPIRAM_MODE_OCT = y:
|
||||||
opiram_psram (noflash)
|
opiram_psram (noflash)
|
||||||
if IDF_TARGET_ESP32S2 = y && SPIRAM:
|
if SPIRAM:
|
||||||
mmu_psram (noflash)
|
if IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y:
|
||||||
|
mmu_psram (noflash)
|
||||||
if PERIPH_CTRL_FUNC_IN_IRAM = y:
|
if PERIPH_CTRL_FUNC_IN_IRAM = y:
|
||||||
periph_ctrl: periph_module_reset (noflash)
|
periph_ctrl: periph_module_reset (noflash)
|
||||||
periph_ctrl: wifi_module_enable (noflash)
|
periph_ctrl: wifi_module_enable (noflash)
|
||||||
|
@@ -20,6 +20,9 @@ const static char *TAG = "mmu_psram";
|
|||||||
|
|
||||||
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
|
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
extern int _instruction_reserved_start;
|
||||||
|
extern int _instruction_reserved_end;
|
||||||
|
|
||||||
static uint32_t instruction_in_spiram;
|
static uint32_t instruction_in_spiram;
|
||||||
static uint32_t instr_start_page;
|
static uint32_t instr_start_page;
|
||||||
static uint32_t instr_end_page;
|
static uint32_t instr_end_page;
|
||||||
@@ -34,6 +37,9 @@ uint32_t instruction_flash_end_page_get(void);
|
|||||||
|
|
||||||
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
|
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
|
||||||
#if CONFIG_SPIRAM_RODATA
|
#if CONFIG_SPIRAM_RODATA
|
||||||
|
extern int _rodata_reserved_start;
|
||||||
|
extern int _rodata_reserved_end;
|
||||||
|
|
||||||
static uint32_t rodata_in_spiram;
|
static uint32_t rodata_in_spiram;
|
||||||
static int rodata_flash2spiram_offs;
|
static int rodata_flash2spiram_offs;
|
||||||
static uint32_t rodata_start_page;
|
static uint32_t rodata_start_page;
|
||||||
|
@@ -18,7 +18,7 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
"esp_crypto_lock.c")
|
"esp_crypto_lock.c")
|
||||||
|
|
||||||
if(CONFIG_SPIRAM)
|
if(CONFIG_SPIRAM)
|
||||||
list(APPEND srcs "spiram.c")
|
list(APPEND srcs "spiram.c" "mmu_psram.c")
|
||||||
|
|
||||||
if(CONFIG_SPIRAM_MODE_QUAD)
|
if(CONFIG_SPIRAM_MODE_QUAD)
|
||||||
list(APPEND srcs "spiram_psram.c")
|
list(APPEND srcs "spiram_psram.c")
|
||||||
|
276
components/esp_hw_support/port/esp32s3/mmu_psram.c
Normal file
276
components/esp_hw_support/port/esp32s3/mmu_psram.c
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_private/mmu_psram.h"
|
||||||
|
#include "esp32s3/rom/cache.h"
|
||||||
|
#include "esp32s3/rom/ets_sys.h"
|
||||||
|
#include "soc/ext_mem_defs.h"
|
||||||
|
#include "soc/extmem_reg.h"
|
||||||
|
|
||||||
|
#define MMU_PAGE_SIZE 0x10000
|
||||||
|
#define MMU_PAGE_TO_BYTES(page_id) ((page_id) * MMU_PAGE_SIZE)
|
||||||
|
#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
|
||||||
|
|
||||||
|
const static char *TAG = "mmu_psram";
|
||||||
|
|
||||||
|
//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
|
||||||
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
extern int _instruction_reserved_start;
|
||||||
|
extern int _instruction_reserved_end;
|
||||||
|
|
||||||
|
static uint32_t instruction_in_spiram;
|
||||||
|
static uint32_t instr_start_page;
|
||||||
|
static uint32_t instr_end_page;
|
||||||
|
static int instr_flash2spiram_offs;
|
||||||
|
|
||||||
|
uint32_t esp_spiram_instruction_access_enabled(void);
|
||||||
|
int instruction_flash2spiram_offset(void);
|
||||||
|
uint32_t instruction_flash_start_page_get(void);
|
||||||
|
uint32_t instruction_flash_end_page_get(void);
|
||||||
|
#endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
|
||||||
|
#if CONFIG_SPIRAM_RODATA
|
||||||
|
extern int _rodata_reserved_start;
|
||||||
|
extern int _rodata_reserved_end;
|
||||||
|
|
||||||
|
static uint32_t rodata_in_spiram;
|
||||||
|
static int rodata_flash2spiram_offs;
|
||||||
|
static uint32_t rodata_start_page;
|
||||||
|
static uint32_t rodata_end_page;
|
||||||
|
|
||||||
|
uint32_t esp_spiram_rodata_access_enabled(void);
|
||||||
|
int rodata_flash2spiram_offset(void);
|
||||||
|
uint32_t rodata_flash_start_page_get(void);
|
||||||
|
uint32_t rodata_flash_end_page_get(void);
|
||||||
|
#endif //#if CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
||||||
|
//TODO IDF-4387
|
||||||
|
static uint32_t page0_mapped = 0;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uint32_t page_id = start_page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO IDF-4387
|
||||||
|
* `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
|
||||||
|
* FOR NOW, leave these logics just as it used to be.
|
||||||
|
*/
|
||||||
|
uint32_t flash_pages = 0;
|
||||||
|
flash_pages += Cache_Count_Flash_Pages(CACHE_IBUS, &page0_mapped);
|
||||||
|
if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %d B, from %d B to %d B",
|
||||||
|
MMU_PAGE_TO_BYTES(flash_pages), MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(flash_pages + page_id));
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Enable DBUS, which is used for copying FLASH .text to PSRAM
|
||||||
|
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - (uint32_t)&_instruction_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||||
|
// uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
|
||||||
|
|
||||||
|
// instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset];
|
||||||
|
// instr_start_page &= MMU_VALID_VAL_MASK;
|
||||||
|
// instr_end_page = instr_start_page + instr_page_cnt - 1;
|
||||||
|
// instr_flash2spiram_offs = instr_start_page - page_id;
|
||||||
|
// ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", instr_start_page, page_id, instr_flash2spiram_offs);
|
||||||
|
|
||||||
|
ets_printf(DRAM_STR("_instruction_reserved_end addr is %x\n"), (uint32_t)&_instruction_reserved_start);
|
||||||
|
uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||||
|
|
||||||
|
instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START);
|
||||||
|
instr_start_page &= MMU_VALID_VAL_MASK;
|
||||||
|
instr_end_page = instr_start_page + instr_page_cnt - 1;
|
||||||
|
instr_flash2spiram_offs = instr_start_page - page_id;
|
||||||
|
ESP_EARLY_LOGE(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", instr_start_page, page_id, instr_flash2spiram_offs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
// page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
// instruction_in_spiram = 1;
|
||||||
|
// ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id);
|
||||||
|
// ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
|
||||||
|
|
||||||
|
page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
instruction_in_spiram = 1;
|
||||||
|
ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id);
|
||||||
|
ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable DRAM0_BUS.
|
||||||
|
* .text (instructions) are mapped in `Cache_Flash_To_SPIRAM_Copy` to both `PRO_CACHE_IBUS0` and `PRO_CACHE_IBUS1`.
|
||||||
|
*
|
||||||
|
* For now, this bus (DRAM0) is only used for copying, so can be disabled. If it is used later, other code
|
||||||
|
* should be responsible for enabling it.
|
||||||
|
*/
|
||||||
|
REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
||||||
|
#endif
|
||||||
|
*out_page = page_id - start_page;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
uint32_t page_id = start_page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO IDF-4387
|
||||||
|
* `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
|
||||||
|
* FOR NOW, leave these logics just as it used to be.
|
||||||
|
*/
|
||||||
|
uint32_t flash_pages = 0;
|
||||||
|
flash_pages += Cache_Count_Flash_Pages(CACHE_DBUS, &page0_mapped);
|
||||||
|
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 %d B.", MMU_PAGE_TO_BYTES(flash_pages + page_id));
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Enable DBUS, which is used for copying FLASH .text to PSRAM
|
||||||
|
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - (uint32_t)&_rodata_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||||
|
// uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
|
||||||
|
|
||||||
|
// rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset];
|
||||||
|
// rodata_start_page &= MMU_VALID_VAL_MASK;
|
||||||
|
// rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
|
||||||
|
// rodata_flash2spiram_offs = rodata_start_page - page_id;
|
||||||
|
// ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", rodata_start_page, page_id, rodata_flash2spiram_offs);
|
||||||
|
|
||||||
|
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||||
|
rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
|
||||||
|
rodata_start_page &= MMU_VALID_VAL_MASK;
|
||||||
|
rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
|
||||||
|
rodata_flash2spiram_offs = rodata_start_page - page_id;
|
||||||
|
ESP_EARLY_LOGE(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", rodata_start_page, page_id, rodata_flash2spiram_offs);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
// page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
// page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
// page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
// rodata_in_spiram = 1;
|
||||||
|
// ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id);
|
||||||
|
// ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
|
||||||
|
|
||||||
|
|
||||||
|
page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_DBUS, DRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page);
|
||||||
|
rodata_in_spiram = 1;
|
||||||
|
ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id);
|
||||||
|
ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable DRAM0_BUS.
|
||||||
|
* .text (instructions) are mapped in `Cache_Flash_To_SPIRAM_Copy` to both `PRO_CACHE_IBUS0` and `PRO_CACHE_IBUS1`.
|
||||||
|
*
|
||||||
|
* For now, this bus (DRAM0) is only used for copying, so can be disabled. If it is used later, other code
|
||||||
|
* should be responsible for enabling it.
|
||||||
|
*/
|
||||||
|
REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
||||||
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
|
REG_SET_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*out_page = page_id - start_page;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif //#if CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
uint32_t esp_spiram_instruction_access_enabled(void)
|
||||||
|
{
|
||||||
|
return instruction_in_spiram;
|
||||||
|
}
|
||||||
|
|
||||||
|
int instruction_flash2spiram_offset(void)
|
||||||
|
{
|
||||||
|
return instr_flash2spiram_offs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t instruction_flash_start_page_get(void)
|
||||||
|
{
|
||||||
|
return instr_start_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t instruction_flash_end_page_get(void)
|
||||||
|
{
|
||||||
|
return instr_end_page;
|
||||||
|
}
|
||||||
|
#endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_RODATA
|
||||||
|
uint32_t esp_spiram_rodata_access_enabled(void)
|
||||||
|
{
|
||||||
|
return rodata_in_spiram;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rodata_flash2spiram_offset(void)
|
||||||
|
{
|
||||||
|
return rodata_flash2spiram_offs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rodata_flash_start_page_get(void)
|
||||||
|
{
|
||||||
|
return rodata_start_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rodata_flash_end_page_get(void)
|
||||||
|
{
|
||||||
|
return rodata_end_page;
|
||||||
|
}
|
||||||
|
#endif //#if CONFIG_SPIRAM_RODATA
|
@@ -24,12 +24,14 @@
|
|||||||
#include "spiram_psram.h"
|
#include "spiram_psram.h"
|
||||||
#include "hal/mmu_hal.h"
|
#include "hal/mmu_hal.h"
|
||||||
#include "hal/cache_ll.h"
|
#include "hal/cache_ll.h"
|
||||||
|
#include "esp_private/mmu_psram.h"
|
||||||
|
|
||||||
|
|
||||||
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
||||||
#define MMU_PAGE_SIZE (0x10000)
|
#define MMU_PAGE_SIZE (0x10000)
|
||||||
|
|
||||||
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||||
|
#define MMU_PAGE_TO_BYTES(page_id) ((page_id) << 16)
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SPEED_40M
|
#if CONFIG_SPIRAM_SPEED_40M
|
||||||
#define PSRAM_SPEED PSRAM_CACHE_S40M
|
#define PSRAM_SPEED PSRAM_CACHE_S40M
|
||||||
@@ -83,12 +85,51 @@ esp_err_t esp_spiram_init(void)
|
|||||||
ESP_EARLY_LOGI(TAG, "Found %dMB SPI RAM device", psram_physical_size / (1024 * 1024));
|
ESP_EARLY_LOGI(TAG, "Found %dMB SPI RAM device", psram_physical_size / (1024 * 1024));
|
||||||
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
|
ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
|
||||||
|
|
||||||
|
uint32_t psram_available_size = 0;
|
||||||
|
ret = psram_get_available_size(&psram_available_size);
|
||||||
|
assert(ret == ESP_OK);
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((unused)) uint32_t total_available_size = psram_available_size;
|
||||||
/**
|
/**
|
||||||
* TODO IDF-4318
|
* `start_page` is the psram physical address in MMU page size.
|
||||||
* Add these feature here:
|
* MMU page size on ESP32S2 is 64KB
|
||||||
* - Copy Flash text into PSRAM
|
* e.g.: psram physical address 16 is in page 0
|
||||||
* - Copy Flash rodata into PSRAM
|
*
|
||||||
|
* Here we plan to copy FLASH instructions to psram physical address 0, which is the No.0 page.
|
||||||
*/
|
*/
|
||||||
|
uint32_t start_page = 0;
|
||||||
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
||||||
|
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 %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size);
|
||||||
|
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
|
||||||
|
//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
|
||||||
|
#if CONFIG_SPIRAM_RODATA
|
||||||
|
ret = mmu_config_psram_rodata_segment(start_page, total_available_size, &used_page);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_EARLY_LOGE(TAG, "No enough psram memory for rodata!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
start_page += used_page;
|
||||||
|
psram_available_size -= MMU_PAGE_TO_BYTES(used_page);
|
||||||
|
ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size);
|
||||||
|
#endif //#if CONFIG_SPIRAM_RODATA
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------Map the PSRAM physical range to MMU-----------------------------//
|
//----------------------------------Map the PSRAM physical range to MMU-----------------------------//
|
||||||
uint32_t vaddr_start = 0;
|
uint32_t vaddr_start = 0;
|
||||||
extern uint32_t _rodata_reserved_end;
|
extern uint32_t _rodata_reserved_end;
|
||||||
@@ -96,10 +137,6 @@ esp_err_t esp_spiram_init(void)
|
|||||||
vaddr_start = rodata_end_aligned;
|
vaddr_start = rodata_end_aligned;
|
||||||
ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned);
|
ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned);
|
||||||
|
|
||||||
uint32_t psram_available_size = 0;
|
|
||||||
ret = psram_get_available_size(&psram_available_size);
|
|
||||||
assert(ret == ESP_OK);
|
|
||||||
|
|
||||||
if (vaddr_start + psram_available_size > DRAM0_CACHE_ADDRESS_HIGH) {
|
if (vaddr_start + psram_available_size > DRAM0_CACHE_ADDRESS_HIGH) {
|
||||||
//Decide these logics when there's a real PSRAM with larger size
|
//Decide these logics when there's a real PSRAM with larger size
|
||||||
ESP_EARLY_LOGE(TAG, "Virtual address not enough for PSRAM!");
|
ESP_EARLY_LOGE(TAG, "Virtual address not enough for PSRAM!");
|
||||||
@@ -108,7 +145,7 @@ esp_err_t esp_spiram_init(void)
|
|||||||
|
|
||||||
//On ESP32S3, MMU is shared for both of the cores. Note this when porting `spiram.c`
|
//On ESP32S3, MMU is shared for both of the cores. Note this when porting `spiram.c`
|
||||||
uint32_t actual_mapped_len = 0;
|
uint32_t actual_mapped_len = 0;
|
||||||
mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, 0, psram_available_size, &actual_mapped_len);
|
mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, MMU_PAGE_TO_BYTES(start_page), psram_available_size, &actual_mapped_len);
|
||||||
ESP_EARLY_LOGV(TAG, "actual_mapped_len is 0x%x bytes", actual_mapped_len);
|
ESP_EARLY_LOGV(TAG, "actual_mapped_len is 0x%x bytes", actual_mapped_len);
|
||||||
|
|
||||||
cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, vaddr_start, actual_mapped_len);
|
cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, vaddr_start, actual_mapped_len);
|
||||||
@@ -204,108 +241,6 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size)
|
|||||||
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size);
|
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO IDF-4318
|
|
||||||
// static uint32_t pages_for_flash = 0;
|
|
||||||
static uint32_t instruction_in_spiram = 0;
|
|
||||||
static uint32_t rodata_in_spiram = 0;
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
|
||||||
static int instr_flash2spiram_offs = 0;
|
|
||||||
static uint32_t instr_start_page = 0;
|
|
||||||
static uint32_t instr_end_page = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
|
||||||
static int rodata_flash2spiram_offs = 0;
|
|
||||||
static uint32_t rodata_start_page = 0;
|
|
||||||
static uint32_t rodata_end_page = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
|
||||||
// Helper macro to make a MMU entry invalid
|
|
||||||
#define INVALID_PHY_PAGE 0xffff
|
|
||||||
static uint32_t page0_mapped = 0;
|
|
||||||
static uint32_t page0_page = INVALID_PHY_PAGE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t esp_spiram_instruction_access_enabled(void)
|
|
||||||
{
|
|
||||||
return instruction_in_spiram;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t esp_spiram_rodata_access_enabled(void)
|
|
||||||
{
|
|
||||||
return rodata_in_spiram;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
|
||||||
esp_err_t esp_spiram_enable_instruction_access(void)
|
|
||||||
{
|
|
||||||
//TODO IDF-4318, `pages_for_flash` will be overwritten, however it influences the psram size to be added to the heap allocator.
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
|
||||||
esp_err_t esp_spiram_enable_rodata_access(void)
|
|
||||||
{
|
|
||||||
//TODO IDF-4318, `pages_for_flash` will be overwritten, however it influences the psram size to be added to the heap allocator.
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
|
||||||
void instruction_flash_page_info_init(void)
|
|
||||||
{
|
|
||||||
uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
|
||||||
|
|
||||||
instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START);
|
|
||||||
instr_start_page &= MMU_VALID_VAL_MASK;
|
|
||||||
instr_end_page = instr_start_page + instr_page_cnt - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t IRAM_ATTR instruction_flash_start_page_get(void)
|
|
||||||
{
|
|
||||||
return instr_start_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t IRAM_ATTR instruction_flash_end_page_get(void)
|
|
||||||
{
|
|
||||||
return instr_end_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IRAM_ATTR instruction_flash2spiram_offset(void)
|
|
||||||
{
|
|
||||||
return instr_flash2spiram_offs;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
|
||||||
void rodata_flash_page_info_init(void)
|
|
||||||
{
|
|
||||||
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
|
||||||
|
|
||||||
rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
|
|
||||||
rodata_start_page &= MMU_VALID_VAL_MASK;
|
|
||||||
rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t IRAM_ATTR rodata_flash_start_page_get(void)
|
|
||||||
{
|
|
||||||
return rodata_start_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t IRAM_ATTR rodata_flash_end_page_get(void)
|
|
||||||
{
|
|
||||||
return rodata_end_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IRAM_ATTR rodata_flash2spiram_offset(void)
|
|
||||||
{
|
|
||||||
return rodata_flash2spiram_offs;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
|
Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
|
||||||
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
|
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "esp32s3/rtc.h"
|
#include "esp32s3/rtc.h"
|
||||||
#include "esp32s3/rom/cache.h"
|
#include "esp32s3/rom/cache.h"
|
||||||
#include "esp32s3/spiram.h"
|
#include "esp32s3/spiram.h"
|
||||||
|
#include "esp_private/mmu_psram.h"
|
||||||
#include "esp_memprot.h"
|
#include "esp_memprot.h"
|
||||||
#include "soc/assist_debug_reg.h"
|
#include "soc/assist_debug_reg.h"
|
||||||
#include "soc/system_reg.h"
|
#include "soc/system_reg.h"
|
||||||
@@ -444,26 +445,8 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||||||
#endif //CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382
|
#endif //CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382
|
||||||
#endif //CONFIG_SPIRAM_MEMTEST
|
#endif //CONFIG_SPIRAM_MEMTEST
|
||||||
|
|
||||||
//TODO: IDF-4382
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32S3
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
|
||||||
extern void instruction_flash_page_info_init(void);
|
|
||||||
instruction_flash_page_info_init();
|
|
||||||
#endif
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
|
||||||
extern void rodata_flash_page_info_init(void);
|
|
||||||
rodata_flash_page_info_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
|
||||||
extern void esp_spiram_enable_instruction_access(void);
|
|
||||||
esp_spiram_enable_instruction_access();
|
|
||||||
#endif
|
|
||||||
#if CONFIG_SPIRAM_RODATA
|
|
||||||
extern void esp_spiram_enable_rodata_access(void);
|
|
||||||
esp_spiram_enable_rodata_access();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int s_instr_flash2spiram_off = 0;
|
int s_instr_flash2spiram_off = 0;
|
||||||
int s_rodata_flash2spiram_off = 0;
|
int s_rodata_flash2spiram_off = 0;
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "soc/extmem_reg.h"
|
#include "soc/extmem_reg.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/cache.h"
|
#include "esp32s3/rom/cache.h"
|
||||||
|
#include "esp_private/mmu_psram.h"
|
||||||
#include "esp32s3/spiram.h"
|
#include "esp32s3/spiram.h"
|
||||||
#include "soc/extmem_reg.h"
|
#include "soc/extmem_reg.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
@@ -52,6 +53,16 @@
|
|||||||
#define PAGES_LIMIT ((SOC_MMU_IROM0_PAGES_END > SOC_MMU_DROM0_PAGES_END) ? SOC_MMU_IROM0_PAGES_END:SOC_MMU_DROM0_PAGES_END)
|
#define PAGES_LIMIT ((SOC_MMU_IROM0_PAGES_END > SOC_MMU_DROM0_PAGES_END) ? SOC_MMU_IROM0_PAGES_END:SOC_MMU_DROM0_PAGES_END)
|
||||||
#define INVALID_PHY_PAGE(page_size) ((page_size) - 1)
|
#define INVALID_PHY_PAGE(page_size) ((page_size) - 1)
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
extern int _instruction_reserved_start;
|
||||||
|
extern int _instruction_reserved_end;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_SPIRAM_RODATA
|
||||||
|
extern int _rodata_reserved_start;
|
||||||
|
extern int _rodata_reserved_end;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
#if !CONFIG_SPI_FLASH_ROM_IMPL
|
||||||
|
|
||||||
typedef struct mmap_entry_{
|
typedef struct mmap_entry_{
|
||||||
|
Reference in New Issue
Block a user