Skip to content

Commit

Permalink
soc: espressif: esp32s3: AMP flash support
Browse files Browse the repository at this point in the history
Rework memory layout and add a flash support.

Signed-off-by: Marek Matej <[email protected]>
  • Loading branch information
Marek Matej committed Jan 27, 2025
1 parent 87a1596 commit da8bd65
Show file tree
Hide file tree
Showing 9 changed files with 641 additions and 173 deletions.
11 changes: 11 additions & 0 deletions soc/espressif/common/include/hw_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@
#ifndef _SOC_ESPRESSIF_COMMON_HW_INIT_H_
#define _SOC_ESPRESSIF_COMMON_HW_INIT_H_

struct rom_segments {
unsigned irom_map_addr; /* Mapped address (VMA) for IROM region */

Check warning on line 11 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

soc/espressif/common/include/hw_init.h:11 please, no spaces at the start of a line

Check warning on line 11 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

UNSPECIFIED_INT

soc/espressif/common/include/hw_init.h:11 Prefer 'unsigned int' to bare use of 'unsigned'
unsigned irom_flash_offset; /* Flash offset (LMA) for IROM region */

Check warning on line 12 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

soc/espressif/common/include/hw_init.h:12 please, no spaces at the start of a line

Check warning on line 12 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

UNSPECIFIED_INT

soc/espressif/common/include/hw_init.h:12 Prefer 'unsigned int' to bare use of 'unsigned'
unsigned irom_size; /* Size of IROM region */

Check warning on line 13 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

soc/espressif/common/include/hw_init.h:13 please, no spaces at the start of a line

Check warning on line 13 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

UNSPECIFIED_INT

soc/espressif/common/include/hw_init.h:13 Prefer 'unsigned int' to bare use of 'unsigned'
unsigned drom_map_addr; /* Mapped address (VMA) for DROM region */

Check warning on line 14 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

soc/espressif/common/include/hw_init.h:14 please, no spaces at the start of a line

Check warning on line 14 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

UNSPECIFIED_INT

soc/espressif/common/include/hw_init.h:14 Prefer 'unsigned int' to bare use of 'unsigned'
unsigned drom_flash_offset; /* Flash offset (LMA) for DROM region */

Check warning on line 15 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LEADING_SPACE

soc/espressif/common/include/hw_init.h:15 please, no spaces at the start of a line

Check warning on line 15 in soc/espressif/common/include/hw_init.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

UNSPECIFIED_INT

soc/espressif/common/include/hw_init.h:15 Prefer 'unsigned int' to bare use of 'unsigned'
unsigned drom_size; /* Size of DROM region */
};

void map_rom_segments(int core, struct rom_segments *map);

int hardware_init(void);

#endif /* _SOC_ESPRESSIF_COMMON_HW_INIT_H_ */
108 changes: 59 additions & 49 deletions soc/espressif/common/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@

#define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used))

#if !defined(CONFIG_SOC_ESP32_APPCPU) && !defined(CONFIG_SOC_ESP32S3_APPCPU)
#define PART_OFFSET FIXED_PARTITION_OFFSET(slot0_partition)
#else
#define PART_OFFSET FIXED_PARTITION_OFFSET(slot0_appcpu_partition)
#endif

void __start(void);
static HDR_ATTR void (*_entry_point)(void) = &__start;

Expand All @@ -76,18 +82,15 @@ extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr;
extern uint32_t _image_drom_start, _image_drom_size, _image_drom_vaddr;

#ifndef CONFIG_MCUBOOT
static uint32_t _app_irom_start =
(FIXED_PARTITION_OFFSET(slot0_partition) + (uint32_t)&_image_irom_start);
static uint32_t _app_irom_size = (uint32_t)&_image_irom_size;

static uint32_t _app_drom_start =
(FIXED_PARTITION_OFFSET(slot0_partition) + (uint32_t)&_image_drom_start);
static uint32_t _app_drom_size = (uint32_t)&_image_drom_size;

#endif

static uint32_t _app_irom_vaddr = ((uint32_t)&_image_irom_vaddr);
static uint32_t _app_drom_vaddr = ((uint32_t)&_image_drom_vaddr);
static struct rom_segments _segments = {
.irom_map_addr = (uint32_t)&_image_irom_vaddr,
.irom_flash_offset = PART_OFFSET + (uint32_t)&_image_irom_start,
.irom_size = (uint32_t)&_image_irom_size,
.drom_map_addr = ((uint32_t)&_image_drom_vaddr),
.drom_flash_offset = PART_OFFSET + (uint32_t)&_image_drom_start,
.drom_size = (uint32_t)&_image_drom_size,
};

#ifndef CONFIG_BOOTLOADER_MCUBOOT
static int spi_flash_read(uint32_t address, void *buffer, size_t length)
Expand All @@ -96,15 +99,15 @@ static int spi_flash_read(uint32_t address, void *buffer, size_t length)
}
#endif /* CONFIG_BOOTLOADER_MCUBOOT */

void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr, uint32_t app_drom_size,
uint32_t app_irom_start, uint32_t app_irom_vaddr, uint32_t app_irom_size)
void map_rom_segments(int core, struct rom_segments *map)
{
uint32_t app_irom_start_aligned = app_irom_start & MMU_FLASH_MASK;
uint32_t app_irom_vaddr_aligned = app_irom_vaddr & MMU_FLASH_MASK;
uint32_t app_irom_vaddr_aligned = map->irom_map_addr; //app_irom_vaddr & MMU_FLASH_MASK;

Check failure on line 104 in soc/espressif/common/loader.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

soc/espressif/common/loader.c:104 do not use C99 // comments
uint32_t app_irom_start_aligned = map->irom_flash_offset; //app_irom_start & MMU_FLASH_MASK;

Check failure on line 105 in soc/espressif/common/loader.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

soc/espressif/common/loader.c:105 do not use C99 // comments

uint32_t app_drom_start_aligned = app_drom_start & MMU_FLASH_MASK;
uint32_t app_drom_vaddr_aligned = app_drom_vaddr & MMU_FLASH_MASK;
uint32_t app_drom_vaddr_aligned = map->drom_map_addr;// app_drom_vaddr & MMU_FLASH_MASK;

Check failure on line 107 in soc/espressif/common/loader.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

soc/espressif/common/loader.c:107 do not use C99 // comments
uint32_t app_drom_start_aligned = map->drom_flash_offset;// _app_drom_start & MMU_FLASH_MASK;

Check failure on line 108 in soc/espressif/common/loader.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

soc/espressif/common/loader.c:108 do not use C99 // comments

/* Traverse segments to fix flash offset changes due to post-build processing */
#ifndef CONFIG_BOOTLOADER_MCUBOOT
esp_image_segment_header_t WORD_ALIGNED_ATTR segment_hdr;
size_t offset = FIXED_PARTITION_OFFSET(boot_partition);
Expand Down Expand Up @@ -139,13 +142,13 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr, uint32_t
/* Fix drom and irom produced be the linker, as it could
* be invalidated by the elf2image and flash load offset
*/
if (segment_hdr.load_addr == _app_drom_vaddr) {
app_drom_start = offset + sizeof(esp_image_segment_header_t);
app_drom_start_aligned = app_drom_start & MMU_FLASH_MASK;
if (segment_hdr.load_addr == map->drom_map_addr) {
map->drom_flash_offset = offset + sizeof(esp_image_segment_header_t);
app_drom_start_aligned = map->drom_flash_offset /*app_drom_start*/ & MMU_FLASH_MASK;
}
if (segment_hdr.load_addr == _app_irom_vaddr) {
app_irom_start = offset + sizeof(esp_image_segment_header_t);
app_irom_start_aligned = app_irom_start & MMU_FLASH_MASK;
if (segment_hdr.load_addr == map->irom_map_addr) {
map->irom_flash_offset = offset + sizeof(esp_image_segment_header_t);
app_irom_start_aligned = map->irom_flash_offset & MMU_FLASH_MASK;
}
if (IS_SRAM(segment_hdr.load_addr) || IS_RTC(segment_hdr.load_addr)) {
ram_segments++;
Expand All @@ -167,29 +170,31 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr, uint32_t
#endif /* !CONFIG_BOOTLOADER_MCUBOOT */

#if CONFIG_SOC_SERIES_ESP32
Cache_Read_Disable(0);
Cache_Flush(0);
Cache_Read_Disable(core);
Cache_Flush(core);
#else
cache_hal_disable(CACHE_TYPE_ALL);
#endif /* CONFIG_SOC_SERIES_ESP32 */

/* Clear the MMU entries that are already set up,
* so the new app only has the mappings it creates.
*/
mmu_hal_unmap_all();
if (core == 0) {
mmu_hal_unmap_all();
}

#if CONFIG_SOC_SERIES_ESP32
int rc = 0;
uint32_t drom_page_count =
(app_drom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;
(_app_drom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;

rc |= cache_flash_mmu_set(0, 0, app_drom_vaddr_aligned, app_drom_start_aligned, 64,
drom_page_count);
rc |= cache_flash_mmu_set(1, 0, app_drom_vaddr_aligned, app_drom_start_aligned, 64,
drom_page_count);

uint32_t irom_page_count =
(app_irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;
(map->irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;

rc |= cache_flash_mmu_set(0, 0, app_irom_vaddr_aligned, app_irom_start_aligned, 64,
irom_page_count);
Expand All @@ -202,53 +207,56 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr, uint32_t
#else
uint32_t actual_mapped_len = 0;

mmu_hal_map_region(0, MMU_TARGET_FLASH0, app_drom_vaddr_aligned, app_drom_start_aligned,
app_drom_size, &actual_mapped_len);
mmu_hal_map_region(core, MMU_TARGET_FLASH0, app_drom_vaddr_aligned, app_drom_start_aligned,
map->drom_size, &actual_mapped_len);

mmu_hal_map_region(0, MMU_TARGET_FLASH0, app_irom_vaddr_aligned, app_irom_start_aligned,
app_irom_size, &actual_mapped_len);
mmu_hal_map_region(core, MMU_TARGET_FLASH0, app_irom_vaddr_aligned, app_irom_start_aligned,
map->irom_size, &actual_mapped_len);
#endif /* CONFIG_SOC_SERIES_ESP32 */

/* ----------------------Enable corresponding buses---------------- */
cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, app_drom_vaddr_aligned, app_drom_size);
cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(core, app_drom_vaddr_aligned, map->drom_size);
cache_ll_l1_enable_bus(core, bus_mask);
bus_mask = cache_ll_l1_get_bus(core, app_irom_vaddr_aligned, map->irom_size);
cache_ll_l1_enable_bus(core, bus_mask);

cache_ll_l1_enable_bus(0, bus_mask);
bus_mask = cache_ll_l1_get_bus(0, app_irom_vaddr_aligned, app_irom_size);
cache_ll_l1_enable_bus(0, bus_mask);
#if CONFIG_MP_MAX_NUM_CPUS > 1
bus_mask = cache_ll_l1_get_bus(1, app_drom_vaddr_aligned, app_drom_size);
#error "SMP case not settled"
bus_mask = cache_ll_l1_get_bus(1, app_drom_vaddr_aligned, map->drom_size);
cache_ll_l1_enable_bus(1, bus_mask);
bus_mask = cache_ll_l1_get_bus(1, app_irom_vaddr_aligned, app_irom_size);
bus_mask = cache_ll_l1_get_bus(1, app_irom_vaddr_aligned, map->irom_size);
cache_ll_l1_enable_bus(1, bus_mask);
#endif

/* ----------------------Enable Cache---------------- */
#if CONFIG_SOC_SERIES_ESP32
/* Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) */
Cache_Read_Enable(0);
Cache_Read_Enable(core);
#else
cache_hal_enable(CACHE_TYPE_ALL);
#endif /* CONFIG_SOC_SERIES_ESP32 */

#if !defined(CONFIG_SOC_SERIES_ESP32) && !defined(CONFIG_SOC_SERIES_ESP32S2)
/* Configure the Cache MMU size for instruction and rodata in flash. */
uint32_t cache_mmu_irom_size =
((app_irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE) *
((map->irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE) *
sizeof(uint32_t);

/* Split the cache usage by the segment sizes */
Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
#endif
/* Show map segments continue using same log format as during MCUboot phase */
ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map", "DROM",
app_drom_start_aligned, app_drom_vaddr_aligned, app_drom_size,
app_drom_size);
app_drom_start_aligned, app_drom_vaddr_aligned, map->drom_size,
map->drom_size);
ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map", "IROM",
app_irom_start_aligned, app_irom_vaddr_aligned, app_irom_size,
app_irom_size);
app_irom_start_aligned, app_irom_vaddr_aligned, map->irom_size,
map->irom_size);
esp_rom_uart_tx_wait_idle(0);
}
#endif /* !CONFIG_MCUBOOT */

#include "debugpin.h"
void __start(void)
{
#ifdef CONFIG_RISCV_GP
Expand All @@ -270,10 +278,12 @@ void __start(void)
}
#endif

#if !defined(CONFIG_SOC_ESP32_APPCPU) && !defined(CONFIG_SOC_ESP32S3_APPCPU) && \
!defined(CONFIG_MCUBOOT)
map_rom_segments(_app_drom_start, _app_drom_vaddr, _app_drom_size, _app_irom_start,
_app_irom_vaddr, _app_irom_size);
#if defined(CONFIG_SOC_ESP32S3_APPCPU) || defined(CONFIG_SOC_ESP32_APPCPU)
#error
#endif

#if !defined(CONFIG_MCUBOOT)
map_rom_segments(0, &_segments);
#endif
#ifndef CONFIG_SOC_SERIES_ESP32C2
/* Disable RNG entropy source as it was already used */
Expand All @@ -284,6 +294,6 @@ void __start(void)
ESP_EARLY_LOGI(TAG, "Disabling glitch detection");
ana_clock_glitch_reset_config(false);
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
ESP_EARLY_LOGI(TAG, "Jumping to the main image...");

__esp_platform_start();
}
2 changes: 0 additions & 2 deletions soc/espressif/esp32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ endif()

if(CONFIG_MCUBOOT)
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "")
elseif(CONFIG_SOC_ESP32_APPCPU)
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default_appcpu.ld CACHE INTERNAL "")
else()
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default.ld CACHE INTERNAL "")
endif()
2 changes: 1 addition & 1 deletion soc/espressif/esp32s3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ if(CONFIG_ESP_SIMPLE_BOOT OR CONFIG_MCUBOOT)
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf)

endif()
endif()

endif()

Expand Down
32 changes: 24 additions & 8 deletions soc/espressif/esp32s3/default.ld
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,25 @@ procpu_dram_end = USER_DRAM_END - APPCPU_SRAM_SIZE;
procpu_iram_org = SRAM_USER_IRAM_START;
procpu_iram_len = procpu_iram_end - procpu_iram_org;

procpu_dram_org2 = ORIGIN(dram0_0_seg);
procpu_dram_org = SRAM1_DRAM_START;
procpu_dram_len = procpu_dram_end - procpu_dram_org;

/* User available ROM memory segments */
procpu_irom_end = ICACHE_START + ICACHE_SIZE - APPCPU_ROM_SIZE;
procpu_drom_end = DCACHE_START + DCACHE_SIZE - APPCPU_ROM_SIZE;

procpu_irom_org = ICACHE_START;
procpu_irom_len = ICACHE_SIZE - APPCPU_ROM_SIZE;

procpu_drom_org = DCACHE_START;
procpu_drom_len = DCACHE_SIZE - APPCPU_ROM_SIZE;

#if defined(CONFIG_ESP_SPIRAM)
procpu_extram_org = DCACHE_START
procpu_extram_len = CONFIG_ESP_SPIRAM_SIZE
#endif

/* Aliases */
#define FLASH_CODE_REGION irom0_0_seg
#define RODATA_REGION drom0_0_seg
Expand Down Expand Up @@ -61,17 +77,17 @@ MEMORY
iram0_0_seg(RX): org = procpu_iram_org, len = procpu_iram_len
dram0_0_seg(RW): org = procpu_dram_org, len = procpu_dram_len

irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN
drom0_0_seg(R): org = DROM_SEG_ORG, len = DROM_SEG_LEN
irom0_0_seg(RX): org = procpu_irom_org, len = procpu_irom_len
drom0_0_seg(R): org = procpu_drom_org, len = procpu_drom_len

/* The `ext_ram_seg` and `drom0_0_seg` share the same bus and the address region.
* A dummy section is used to avoid overlap. See `.ext_ram.dummy` in `sections.ld.in`
*/
#if defined(CONFIG_ESP_SPIRAM)
/* `ext_[id]ram_seg` and `drom0_0_seg` share the same bus and the address region.
* A dummy section is used to avoid overlap. See `.ext_ram.dummy` */
ext_dram_seg(RW): org = DROM_SEG_ORG, len = (CONFIG_ESP_SPIRAM_SIZE)
ext_iram_seg(RX): org = IROM_SEG_ORG, len = (CONFIG_ESP_SPIRAM_SIZE)
ext_dram_seg(RW): org = procpu_extram_org, len = procpu_extram_len
ext_iram_seg(RX): org = procpu_extram_org, len = procpu_extram_len
#endif

/* RTC fast memory (executable). Persists over deep sleep.
Expand Down Expand Up @@ -147,7 +163,7 @@ SECTIONS
*/
LONG(ADDR(.dram0.data))
LONG(LOADADDR(.dram0.data))
LONG(LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - LOADADDR(.dram0.data))
LONG(LOADADDR(.dram0.data_end) + SIZEOF(.dram0.data_end) - LOADADDR(.dram0.data))

/* RTC_IRAM metadata:
* 8. Destination address (VMA) for RTC_IRAM region
Expand Down Expand Up @@ -557,8 +573,8 @@ SECTIONS
/* Spacer section is required to skip .iram0.text area because
* iram0_0_seg and dram0_0_seg reflect the same address space on different buses.
*/
. = ORIGIN(dram0_0_seg) + MAX(_iram_end, SRAM1_IRAM_START) - SRAM1_IRAM_START;
. = ALIGN(4) + 16;
. = ORIGIN(dram0_0_seg) + (MAX(_iram_end, SRAM1_IRAM_START) - SRAM1_IRAM_START);
. = ALIGN(16);
} GROUP_LINK_IN(RAMABLE_REGION)

.dram0.data :
Expand Down Expand Up @@ -751,7 +767,7 @@ SECTIONS
#include <zephyr/linker/common-rom/common-rom-logging.ld>
#pragma pop_macro("GROUP_ROM_LINK_IN")

.dram0.end :
.dram0.data_end :
{
__data_end = ABSOLUTE(.);
_data_end = ABSOLUTE(.);
Expand Down
Loading

0 comments on commit da8bd65

Please sign in to comment.