Skip to content

Commit

Permalink
Merge branch 'feat/xip_psram_c5' into 'master'
Browse files Browse the repository at this point in the history
psram: xip_psram support on c5/c61, also fixed cache writeback/invalidate not work issue on c61

Closes IDF-8688, IDF-9292, and IDF-11008

See merge request espressif/esp-idf!33265
  • Loading branch information
Icarus113 committed Sep 6, 2024
2 parents c2b5339 + 5316a36 commit 5dff189
Show file tree
Hide file tree
Showing 23 changed files with 236 additions and 15 deletions.
2 changes: 1 addition & 1 deletion components/bootloader_support/src/bootloader_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ static void set_cache_and_start_app(
}
//we use the MMU_LL_END_DROM_ENTRY_ID mmu entry as a map page for app to find the boot partition
mmu_hal_map_region(0, MMU_TARGET_FLASH0, MMU_LL_END_DROM_ENTRY_VADDR, drom_addr_aligned, CONFIG_MMU_PAGE_SIZE, &actual_mapped_len);
ESP_EARLY_LOGV(TAG, "mapped one page of the rodata, from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, drom_load_addr_aligned, actual_mapped_len);
ESP_EARLY_LOGV(TAG, "mapped one page of the rodata, from paddr=0x%08" PRIx32 " and vaddr=0x%08" PRIx32 ", 0x%" PRIx32 " bytes are mapped", drom_addr_aligned, MMU_LL_END_DROM_ENTRY_VADDR, actual_mapped_len);
#endif

//-----------------------MAP IROM--------------------------
Expand Down
34 changes: 34 additions & 0 deletions components/esp_psram/esp32c5/Kconfig.spiram
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,39 @@ menu "SPI RAM config"
default 80 if SPIRAM_SPEED_80M
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_ESP32C5`

source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common" # insert non-chip-specific items here
endmenu
34 changes: 34 additions & 0 deletions components/esp_psram/esp32c61/Kconfig.spiram
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,39 @@ menu "SPI RAM config"
default 80 if SPIRAM_SPEED_80M
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
endmenu
2 changes: 1 addition & 1 deletion components/esp_psram/include/esp_private/mmu_psram_flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern "C" {
#if CONFIG_IDF_TARGET_ESP32
#define MMU_PAGE_SIZE 0x8000
#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 BYTES_TO_MMU_PAGE(bytes) ((bytes) / MMU_PAGE_SIZE)
#endif
Expand Down
6 changes: 4 additions & 2 deletions components/esp_psram/mmu_psram_flash_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
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);
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) {
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);
Expand All @@ -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);
*out_page = start_page;

ESP_EARLY_LOGI(TAG, ".text xip on psram");
return ESP_OK;
}
#endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
Expand All @@ -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;
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);
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) {
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);
Expand All @@ -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);
*out_page = start_page;

ESP_EARLY_LOGI(TAG, ".rodata xip on psram");
return ESP_OK;
}
#endif //#if CONFIG_SPIRAM_RODATA
Expand Down
2 changes: 2 additions & 0 deletions components/esp_psram/test_apps/psram/pytest_psram.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def test_psram_esp32p4(dut: Dut) -> None:
'config',
[
'esp32c5_release',
'esp32c5_advanced',
],
indirect=True,
)
Expand All @@ -107,6 +108,7 @@ def test_psram_esp32c5(dut: Dut) -> None:
'config',
[
'esp32c61_release',
'esp32c61_advanced',
],
indirect=True,
)
Expand Down
15 changes: 15 additions & 0 deletions components/esp_psram/test_apps/psram/sdkconfig.ci.esp32c5_advanced
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CONFIG_IDF_TARGET="esp32c5"

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"
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 4 additions & 0 deletions components/esp_rom/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ if(CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG OR CONFIG_ESP_ROM_HAS_CACHE_WRITEBAC
list(APPEND sources "patches/esp_rom_cache_esp32s2_esp32s3.c")
endif()

if(CONFIG_ESP_ROM_CACHE_WB_INVLD_LOW_RANGE)
list(APPEND sources "patches/esp_rom_cache_esp32c61.c")
endif()

if(CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG)
list(APPEND sources "patches/esp_rom_cache_writeback_esp32s3.S")
endif()
Expand Down
4 changes: 4 additions & 0 deletions components/esp_rom/esp32c61/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ config ESP_ROM_USB_OTG_NUM
config ESP_ROM_HAS_OUTPUT_PUTC_FUNC
bool
default y

config ESP_ROM_CACHE_WB_INVLD_LOW_RANGE
bool
default y
1 change: 1 addition & 0 deletions components/esp_rom/esp32c61/esp_rom_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@
#define ESP_ROM_HAS_SW_FLOAT (1) // ROM has libgcc software floating point emulation functions
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_HAS_OUTPUT_PUTC_FUNC (1) // ROM has esp_rom_output_putc (or ets_write_char_uart)
#define ESP_ROM_CACHE_WB_INVLD_LOW_RANGE (1) // ROM `Cache_WriteBack_Addr` and `Cache_Invalidate_Addr` can only access low vaddr parts
4 changes: 2 additions & 2 deletions components/esp_rom/esp32c61/ld/esp32c61.rom.ld
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ MMU_Set_Page_Mode = 0x40000624;
MMU_Get_Page_Mode = 0x40000628;
Cache_Sync_Items = 0x4000062c;
Cache_Op_Addr = 0x40000630;
Cache_Invalidate_Addr = 0x40000634;
/*Cache_Invalidate_Addr = 0x40000634; rom version API has issue that unable to access higher vaddr range, use IDF patch */
Cache_Clean_Addr = 0x40000638;
Cache_WriteBack_Addr = 0x4000063c;
/*Cache_WriteBack_Addr = 0x4000063c; rom version API has issue that unable to access higher vaddr range, use IDF patch */
Cache_WriteBack_Invalidate_Addr = 0x40000640;
Cache_Invalidate_All = 0x40000644;
Cache_Clean_All = 0x40000648;
Expand Down
2 changes: 2 additions & 0 deletions components/esp_rom/linker.lf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ entries:
esp_rom_cache_esp32s2_esp32s3 (noflash)
if ESP_ROM_HAS_CACHE_WRITEBACK_BUG = y:
esp_rom_cache_writeback_esp32s3 (noflash)
if ESP_ROM_CACHE_WB_INVLD_LOW_RANGE = y:
esp_rom_cache_esp32c61 (noflash)
if HEAP_TLSF_USE_ROM_IMPL = y && (ESP_ROM_TLSF_CHECK_PATCH = y || HEAP_TLSF_CHECK_PATCH = y):
esp_rom_tlsf (noflash)
if SOC_SYSTIMER_SUPPORTED = y:
Expand Down
97 changes: 97 additions & 0 deletions components/esp_rom/patches/esp_rom_cache_esp32c61.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdint.h>
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_rom_caps.h"
#include "soc/soc_caps.h"
#include "soc/cache_reg.h"
#include "soc/cache_struct.h"
#include "soc/ext_mem_defs.h"
#include "hal/assert.h"
#include "esp32c61/rom/cache.h"

#include "esp_rom_sys.h"

#define CACHE_MAX_SYNC_NUM ((CACHE_SYNC_SIZE + 1) >> 1)

/**
* @brief Sync Cache items
*
* @param type sync type
* @param addr address
* @param bytes bytes to be synced
*/
__attribute__((always_inline))
static inline void s_cache_sync_items(uint32_t type, uint32_t addr, uint32_t bytes)
{
REG_WRITE(CACHE_SYNC_ADDR_REG, addr);
REG_SET_FIELD(CACHE_SYNC_SIZE_REG, CACHE_SYNC_SIZE, bytes);
REG_SET_BIT(CACHE_SYNC_CTRL_REG, type);
while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE))
;
}

int Cache_Invalidate_Addr(uint32_t vaddr, uint32_t size)
{
uint32_t plus = 0;
uint32_t cache_line_size = 32;
uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM;
if (size == 0) {
HAL_ASSERT(false);
}
//aligned start address to cache line size
plus = vaddr & (cache_line_size - 1);
vaddr -= plus;
//make the length fit the start address
size += plus;
//aligned the length to cache line size(0->0)
size = (size + cache_line_size - 1) & ~(cache_line_size - 1);

while (size > 0) {
//aligned to cache_max_sync_size, (0->cache_max_sync_size)
uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr;
if (this_size > size) {
this_size = size;
}
s_cache_sync_items(CACHE_SYNC_INVALIDATE, vaddr, this_size);
vaddr += this_size;
size -= this_size;
}

return 0;
}

int Cache_WriteBack_Addr(uint32_t vaddr, uint32_t size)
{
uint32_t plus = 0;
uint32_t cache_line_size = 32;
uint32_t cache_max_sync_size = CACHE_MAX_SYNC_NUM;
if (size == 0) {
HAL_ASSERT(false);
}
//aligned start address to cache line size
plus = vaddr & (cache_line_size - 1);
vaddr -= plus;
//make the length fit the start address
size += plus;
//aligned the length to cache line size(0->0)
size = (size + cache_line_size - 1) & ~(cache_line_size - 1);

while (size > 0) {
//aligned to cache_max_sync_size, (0->cache_max_sync_size)
uint32_t this_size = ((vaddr + cache_max_sync_size) & ~(cache_max_sync_size - 1)) - vaddr;
if (this_size > size) {
this_size = size;
}
s_cache_sync_items(CACHE_SYNC_WRITEBACK, vaddr, this_size);
vaddr += this_size;
size -= this_size;
}

return 0;
}
3 changes: 3 additions & 0 deletions components/esp_system/port/image_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "unaligned segment length 0x%"PRIx32, data_len);
}

mmu_ll_set_entry_invalid(0, MMU_LL_END_DROM_ENTRY_ID);
s_current_read_mapping = UINT32_MAX;

return ESP_OK;
}

Expand Down
2 changes: 2 additions & 0 deletions components/hal/esp32c5/include/hal/mmu_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
extern "C" {
#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_ID (SOC_MMU_ENTRY_NUM - 1)

Expand Down
3 changes: 2 additions & 1 deletion components/hal/esp32c61/include/hal/mmu_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
extern "C" {
#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_ID (SOC_MMU_ENTRY_NUM - 1)

Expand Down Expand Up @@ -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)
{
(void)mmu_id;
(void)target;
uint32_t mmu_raw_value;
if (mmu_ll_cache_encryption_enabled()) {
mmu_val |= SOC_MMU_SENSITIVE;
Expand Down
4 changes: 2 additions & 2 deletions components/soc/esp32c5/include/soc/ext_mem_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extern "C" {
* valid bit + value bits
* valid bit is BIT(9), so value bits are 0x1ff
*/
#define SOC_MMU_VALID_VAL_MASK (SOC_MMU_ACCESS_SPIRAM-1)
#define SOC_MMU_VALID_VAL_MASK (SOC_MMU_ACCESS_SPIRAM - 1)
/**
* 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.:
Expand All @@ -72,7 +72,7 @@ extern "C" {
* This is the mask used for mapping. e.g.:
* 0x4200_0000 & SOC_MMU_VADDR_MASK
*/
#define SOC_MMU_VADDR_MASK ((SOC_MMU_PAGE_SIZE) * SOC_MMU_ENTRY_NUM - 1)
#define SOC_MMU_VADDR_MASK ((SOC_MMU_PAGE_SIZE) * SOC_MMU_ENTRY_NUM - 1)

#define SOC_MMU_DBUS_VADDR_BASE 0x42000000
#define SOC_MMU_IBUS_VADDR_BASE 0x42000000
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32c61/include/soc/ext_mem_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extern "C" {
* valid bit + value bits
* 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.
* `SOC_MMU_MAX_PADDR_PAGE_NUM * SOC_MMU_PAGE_SIZE` means the max paddr address supported by the MMU. e.g.:
Expand Down
Loading

0 comments on commit 5dff189

Please sign in to comment.