mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(psram): xip psram c61
This commit is contained in:
parent
8842e5764f
commit
fce2680e91
@ -44,5 +44,39 @@ menu "SPI RAM config"
|
|||||||
default 80 if SPIRAM_SPEED_80M
|
default 80 if SPIRAM_SPEED_80M
|
||||||
default 40 if SPIRAM_SPEED_40M
|
default 40 if SPIRAM_SPEED_40M
|
||||||
|
|
||||||
|
config SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Enable this option allows moving application's instruction segment from the SPI Flash to PSRAM
|
||||||
|
|
||||||
|
config SPIRAM_RODATA
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Enable this option allows moving application's rodata segment from the SPI Flash to
|
||||||
|
PSRAM
|
||||||
|
|
||||||
|
config SPIRAM_XIP_FROM_PSRAM
|
||||||
|
bool "Enable Executable in place from (XiP) from PSRAM feature (READ HELP)"
|
||||||
|
default n
|
||||||
|
select SPIRAM_FETCH_INSTRUCTIONS
|
||||||
|
select SPIRAM_RODATA
|
||||||
|
select SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||||
|
help
|
||||||
|
If enabled, firmware in flash including instructions and data will be moved into PSRAM on startup,
|
||||||
|
firmware code will execute directly from PSRAM.
|
||||||
|
|
||||||
|
With this option enabled, code that requires execution during an MSPI1 Flash operation
|
||||||
|
does not have to be placed in IRAM. Therefore codes that need to be executing during Flash
|
||||||
|
operations can continue working normally.
|
||||||
|
|
||||||
|
This feature is useful for high throughput peripheral involved applications to improve
|
||||||
|
the performance during MSPI1 flash operations.
|
||||||
|
|
||||||
|
config SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
This is a helper indicating this condition:
|
||||||
|
`CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_IDF_TARGET_ESP32C61`
|
||||||
|
|
||||||
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
|
source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -30,7 +30,7 @@ extern "C" {
|
|||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
#define MMU_PAGE_SIZE 0x8000
|
#define MMU_PAGE_SIZE 0x8000
|
||||||
#else
|
#else
|
||||||
#define MMU_PAGE_SIZE 0x10000
|
#define MMU_PAGE_SIZE CONFIG_MMU_PAGE_SIZE
|
||||||
#define MMU_PAGE_TO_BYTES(page_id) ((page_id) * MMU_PAGE_SIZE)
|
#define MMU_PAGE_TO_BYTES(page_id) ((page_id) * MMU_PAGE_SIZE)
|
||||||
#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
|
#define BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,7 +85,7 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size
|
|||||||
uint32_t flash_irom_paddr_start = 0;
|
uint32_t flash_irom_paddr_start = 0;
|
||||||
image_process_get_flash_segments_info(&flash_drom_paddr_start, &flash_irom_paddr_start);
|
image_process_get_flash_segments_info(&flash_drom_paddr_start, &flash_irom_paddr_start);
|
||||||
flash_irom_paddr_start = ALIGN_DOWN_BY(flash_irom_paddr_start, CONFIG_MMU_PAGE_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);
|
ESP_EARLY_LOGV(TAG, "flash_irom_paddr_start: 0x%x", flash_irom_paddr_start);
|
||||||
|
|
||||||
if ((MMU_PAGE_TO_BYTES(start_page) + irom_size) > psram_size) {
|
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);
|
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);
|
||||||
@ -106,6 +106,7 @@ esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size
|
|||||||
start_page += BYTES_TO_MMU_PAGE(irom_size);
|
start_page += BYTES_TO_MMU_PAGE(irom_size);
|
||||||
*out_page = start_page;
|
*out_page = start_page;
|
||||||
|
|
||||||
|
ESP_EARLY_LOGI(TAG, ".text xip on psram");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
@ -120,7 +121,7 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si
|
|||||||
uint32_t flash_irom_paddr_start = 0;
|
uint32_t flash_irom_paddr_start = 0;
|
||||||
image_process_get_flash_segments_info(&flash_drom_paddr_start, &flash_irom_paddr_start);
|
image_process_get_flash_segments_info(&flash_drom_paddr_start, &flash_irom_paddr_start);
|
||||||
flash_drom_paddr_start = ALIGN_DOWN_BY(flash_drom_paddr_start, CONFIG_MMU_PAGE_SIZE);
|
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);
|
ESP_EARLY_LOGV(TAG, "flash_drom_paddr_start: 0x%x", flash_drom_paddr_start);
|
||||||
|
|
||||||
if ((MMU_PAGE_TO_BYTES(start_page) + drom_size) > psram_size) {
|
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);
|
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);
|
||||||
@ -141,6 +142,7 @@ esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_si
|
|||||||
start_page += BYTES_TO_MMU_PAGE(drom_size);
|
start_page += BYTES_TO_MMU_PAGE(drom_size);
|
||||||
*out_page = start_page;
|
*out_page = start_page;
|
||||||
|
|
||||||
|
ESP_EARLY_LOGI(TAG, ".rodata xip on psram");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
#endif //#if CONFIG_SPIRAM_RODATA
|
#endif //#if CONFIG_SPIRAM_RODATA
|
||||||
|
@ -108,6 +108,7 @@ def test_psram_esp32c5(dut: Dut) -> None:
|
|||||||
'config',
|
'config',
|
||||||
[
|
[
|
||||||
'esp32c61_release',
|
'esp32c61_release',
|
||||||
|
'esp32c61_advanced',
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32c61"
|
||||||
|
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
|
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||||
|
|
||||||
|
CONFIG_SPIRAM=y
|
||||||
|
CONFIG_SPIRAM_SPEED_80M=y
|
||||||
|
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||||
|
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
|
||||||
|
CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y
|
||||||
|
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
@ -20,6 +20,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MMU_LL_FLASH_MMU_ID 0
|
||||||
|
#define MMU_LL_PSRAM_MMU_ID 0
|
||||||
#define MMU_LL_END_DROM_ENTRY_VADDR (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_MMU_PAGE_SIZE)
|
#define MMU_LL_END_DROM_ENTRY_VADDR (SOC_DRAM_FLASH_ADDRESS_HIGH - SOC_MMU_PAGE_SIZE)
|
||||||
#define MMU_LL_END_DROM_ENTRY_ID (SOC_MMU_ENTRY_NUM - 1)
|
#define MMU_LL_END_DROM_ENTRY_ID (SOC_MMU_ENTRY_NUM - 1)
|
||||||
|
|
||||||
@ -212,7 +214,6 @@ static inline uint32_t mmu_ll_format_paddr(uint32_t mmu_id, uint32_t paddr, mmu_
|
|||||||
__attribute__((always_inline)) static inline void mmu_ll_write_entry(uint32_t mmu_id, uint32_t entry_id, uint32_t mmu_val, mmu_target_t target)
|
__attribute__((always_inline)) static inline void mmu_ll_write_entry(uint32_t mmu_id, uint32_t entry_id, uint32_t mmu_val, mmu_target_t target)
|
||||||
{
|
{
|
||||||
(void)mmu_id;
|
(void)mmu_id;
|
||||||
(void)target;
|
|
||||||
uint32_t mmu_raw_value;
|
uint32_t mmu_raw_value;
|
||||||
if (mmu_ll_cache_encryption_enabled()) {
|
if (mmu_ll_cache_encryption_enabled()) {
|
||||||
mmu_val |= SOC_MMU_SENSITIVE;
|
mmu_val |= SOC_MMU_SENSITIVE;
|
||||||
|
@ -58,7 +58,7 @@ extern "C" {
|
|||||||
* valid bit + value bits
|
* valid bit + value bits
|
||||||
* valid bit is BIT(9), so value bits are 0x1ff
|
* valid bit is BIT(9), so value bits are 0x1ff
|
||||||
*/
|
*/
|
||||||
#define SOC_MMU_VALID_VAL_MASK 0x3ff
|
#define SOC_MMU_VALID_VAL_MASK (SOC_MMU_ACCESS_SPIRAM - 1)
|
||||||
/**
|
/**
|
||||||
* Max MMU available paddr page num.
|
* Max MMU available paddr page num.
|
||||||
* `SOC_MMU_MAX_PADDR_PAGE_NUM * SOC_MMU_PAGE_SIZE` means the max paddr address supported by the MMU. e.g.:
|
* `SOC_MMU_MAX_PADDR_PAGE_NUM * SOC_MMU_PAGE_SIZE` means the max paddr address supported by the MMU. e.g.:
|
||||||
|
@ -277,7 +277,7 @@ const void * spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memo
|
|||||||
mmu_target_t target = MMU_TARGET_FLASH0;
|
mmu_target_t target = MMU_TARGET_FLASH0;
|
||||||
|
|
||||||
__attribute__((unused)) uint32_t phys_page = phys_offs / CONFIG_MMU_PAGE_SIZE;
|
__attribute__((unused)) uint32_t phys_page = phys_offs / CONFIG_MMU_PAGE_SIZE;
|
||||||
#if !SOC_MMU_PER_EXT_MEM_TARGET
|
#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||||
if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) {
|
if (phys_page >= instruction_flash_start_page_get() && phys_page <= instruction_flash_end_page_get()) {
|
||||||
target = MMU_TARGET_PSRAM0;
|
target = MMU_TARGET_PSRAM0;
|
||||||
@ -291,7 +291,7 @@ const void * spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memo
|
|||||||
phys_offs -= rodata_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE;
|
phys_offs -= rodata_flash2spiram_offset() * CONFIG_MMU_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif //#if !SOC_MMU_PER_EXT_MEM_TARGET
|
#endif //#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||||
|
|
||||||
mmu_vaddr_t type = (memory == SPI_FLASH_MMAP_DATA) ? MMU_VADDR_DATA : MMU_VADDR_INSTRUCTION;
|
mmu_vaddr_t type = (memory == SPI_FLASH_MMAP_DATA) ? MMU_VADDR_DATA : MMU_VADDR_INSTRUCTION;
|
||||||
ret = esp_mmu_paddr_to_vaddr(phys_offs, target, type, &ptr);
|
ret = esp_mmu_paddr_to_vaddr(phys_offs, target, type, &ptr);
|
||||||
@ -383,7 +383,7 @@ size_t spi_flash_cache2phys(const void *cached)
|
|||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
#if !SOC_MMU_PER_EXT_MEM_TARGET //TODO: IDF-9049
|
#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||||
#if CONFIG_SPIRAM_RODATA
|
#if CONFIG_SPIRAM_RODATA
|
||||||
if ((uint32_t)cached >= (uint32_t)&_rodata_reserved_start && (uint32_t)cached <= (uint32_t)&_rodata_reserved_end) {
|
if ((uint32_t)cached >= (uint32_t)&_rodata_reserved_start && (uint32_t)cached <= (uint32_t)&_rodata_reserved_end) {
|
||||||
offset = rodata_flash2spiram_offset();
|
offset = rodata_flash2spiram_offset();
|
||||||
@ -394,7 +394,7 @@ size_t spi_flash_cache2phys(const void *cached)
|
|||||||
offset = instruction_flash2spiram_offset();
|
offset = instruction_flash2spiram_offset();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif //#if !SOC_MMU_PER_EXT_MEM_TARGET
|
#endif //#if !CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM
|
||||||
|
|
||||||
return paddr + offset * CONFIG_MMU_PAGE_SIZE;
|
return paddr + offset * CONFIG_MMU_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
@ -38,6 +37,8 @@ def test_flash_mmap_rom_impl(dut: Dut) -> None:
|
|||||||
XIP_CONFIGS = [
|
XIP_CONFIGS = [
|
||||||
pytest.param('xip_psram_esp32s2', marks=[pytest.mark.esp32s2]),
|
pytest.param('xip_psram_esp32s2', marks=[pytest.mark.esp32s2]),
|
||||||
pytest.param('xip_psram_esp32s3', marks=[pytest.mark.esp32s3]),
|
pytest.param('xip_psram_esp32s3', marks=[pytest.mark.esp32s3]),
|
||||||
|
pytest.param('xip_psram_esp32c5', marks=[pytest.mark.esp32c5]),
|
||||||
|
pytest.param('xip_psram_esp32c61', marks=[pytest.mark.esp32c61]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
CONFIG_IDF_TARGET="esp32c61"
|
||||||
|
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
Loading…
Reference in New Issue
Block a user