soc: esp32s3: AMP support

Updates and fixes to support APPCPU.
- fix ld scripts
- fix and update memory layout
- fix build issues
- fix sysbuild

Signed-off-by: Marek Matej <marek.matej@espressif.com>
This commit is contained in:
Marek Matej 2024-09-04 14:28:07 +02:00 committed by Mahesh Mahadevan
commit ed1179713c
12 changed files with 557 additions and 291 deletions

View file

@ -84,7 +84,6 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,
unsigned int segments = 0; unsigned int segments = 0;
unsigned int ram_segments = 0; unsigned int ram_segments = 0;
/* Using already fetched bootloader image header from bootloader_init */
offset += sizeof(esp_image_header_t); offset += sizeof(esp_image_header_t);
while (segments++ < 16) { while (segments++ < 16) {
@ -223,7 +222,6 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,
"IROM", "IROM",
app_irom_start_aligned, app_irom_vaddr_aligned, app_irom_start_aligned, app_irom_vaddr_aligned,
app_irom_size, app_irom_size); app_irom_size, app_irom_size);
ets_printf("\n\r");
esp_rom_uart_tx_wait_idle(0); esp_rom_uart_tx_wait_idle(0);
} }
@ -248,7 +246,7 @@ void __start(void)
} }
#endif #endif
#ifndef CONFIG_MCUBOOT #if !defined(CONFIG_MCUBOOT) && !defined(CONFIG_SOC_ESP32S3_APPCPU)
map_rom_segments(_app_drom_start, _app_drom_vaddr, _app_drom_size, map_rom_segments(_app_drom_start, _app_drom_vaddr, _app_drom_size,
_app_irom_start, _app_irom_vaddr, _app_irom_size); _app_irom_start, _app_irom_vaddr, _app_irom_size);
#endif #endif

View file

@ -32,8 +32,7 @@ config ESP32_APPCPU_DRAM
config SOC_ENABLE_APPCPU config SOC_ENABLE_APPCPU
bool bool
default y default y
depends on IPM && SOC_ESP32_PROCPU depends on (IPM || MBOX) && SOC_ESP32_PROCPU
depends on MBOX && SOC_ESP32_PROCPU
help help
This hidden configuration lets PROCPU core to map and start APPCPU whenever IPM is enabled. This hidden configuration lets PROCPU core to map and start APPCPU whenever IPM is enabled.

View file

@ -1,14 +1,20 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
if (CONFIG_SOC_ESP32S3_APPCPU) if (CONFIG_SOC_ESP32S3_APPCPU)
zephyr_sources(soc_appcpu.c)
zephyr_sources(
soc_appcpu.c
)
else() else()
zephyr_sources( zephyr_sources(
soc.c soc.c
soc_cache.c soc_cache.c
esp32s3-mp.c esp32s3-mp.c
../common/loader.c ../common/loader.c
) )
endif() endif()
zephyr_include_directories(.) zephyr_include_directories(.)
@ -22,13 +28,24 @@ zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c)
# Get flash size to use in esptool as string # Get flash size to use in esptool as string
math(EXPR esptoolpy_flashsize "${CONFIG_FLASH_SIZE} / 0x100000") math(EXPR esptoolpy_flashsize "${CONFIG_FLASH_SIZE} / 0x100000")
# Make rom loader compatible binary file # Get UART baudrate from DT
if(NOT CONFIG_BOOTLOADER_MCUBOOT) dt_chosen(dts_shell_uart PROPERTY "zephyr,shell-uart")
if(${dts_shell_uart})
dt_prop(monitor_baud PATH ${dts_shell_uart} PROPERTY "current-speed")
endif()
board_runner_args(esp32 "--esp-monitor-baud=${monitor_baud}")
message("-- Espressif HAL path: ${ESP_IDF_PATH}")
# Select image processing
if(CONFIG_ESP_SIMPLE_BOOT OR CONFIG_MCUBOOT)
if(CONFIG_BUILD_OUTPUT_BIN) if(CONFIG_BUILD_OUTPUT_BIN)
set(ESPTOOL_PY ${ESP_IDF_PATH}/tools/esptool_py/esptool.py) set(ESPTOOL_PY ${ESP_IDF_PATH}/tools/esptool_py/esptool.py)
message("esptool path: ${ESPTOOL_PY}") message("-- Use the esptool.py: ${ESPTOOL_PY}")
set(ELF2IMAGE_ARG "") set(ELF2IMAGE_ARG "")
if(NOT CONFIG_MCUBOOT) if(NOT CONFIG_MCUBOOT)
@ -37,49 +54,35 @@ if(NOT CONFIG_BOOTLOADER_MCUBOOT)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND ${PYTHON_EXECUTABLE} ${ESPTOOL_PY} COMMAND ${PYTHON_EXECUTABLE} ${ESPTOOL_PY}
ARGS --chip esp32s3 elf2image ${ELF2IMAGE_ARG} ARGS --chip ${CONFIG_SOC} elf2image ${ELF2IMAGE_ARG}
--flash_mode dio --flash_freq 40m --flash_mode dio --flash_freq 40m
--flash_size ${esptoolpy_flashsize}MB --flash_size ${esptoolpy_flashsize}MB
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin -o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf) ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf)
endif() endif()
endif() endif()
## When building for APPCPU # Select the image origin depending on the boot configuration
if(CONFIG_SOC_ESP32S3_APPCPU) if(CONFIG_SOC_ESP32S3_APPCPU)
dt_nodelabel(dts_partition_path NODELABEL "slot0_appcpu_partition")
if(CONFIG_BUILD_OUTPUT_BIN) elseif(CONFIG_MCUBOOT)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands dt_nodelabel(dts_partition_path NODELABEL "boot_partition")
COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/esp_bin2c_array.py elseif(CONFIG_ESP_SIMPLE_BOOT)
ARGS -i ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.c
-a "esp32s3_appcpu_fw_array")
endif()
else()
## Building for PROCPU
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source)
# Get code-partition boot address
dt_nodelabel(dts_partition_path NODELABEL "boot_partition") dt_nodelabel(dts_partition_path NODELABEL "boot_partition")
dt_reg_addr(boot_off PATH ${dts_partition_path})
# Get code-partition slot0 address
dt_nodelabel(dts_partition_path NODELABEL "slot0_partition")
dt_reg_addr(img_0_off PATH ${dts_partition_path})
if(CONFIG_BOOTLOADER_MCUBOOT)
board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}")
else() else()
board_finalize_runner_args(esp32 "--esp-app-address=${boot_off}") dt_nodelabel(dts_partition_path NODELABEL "slot0_partition")
endif() endif()
endif() dt_reg_addr(image_off PATH ${dts_partition_path})
board_finalize_runner_args(esp32 "--esp-app-address=${image_off}")
message("-- Image partition ${dts_partition_path}")
# Look for cross references between bootloader sections
if(CONFIG_MCUBOOT) if(CONFIG_MCUBOOT)
# search from cross references between bootloader sections
message("check_callgraph using: ${ESP_IDF_PATH}/tools/ci/check_callgraph.py") message("check_callgraph using: ${ESP_IDF_PATH}/tools/ci/check_callgraph.py")
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND COMMAND

View file

@ -14,28 +14,6 @@ config SOC_SERIES_ESP32S3
if SOC_SERIES_ESP32S3 if SOC_SERIES_ESP32S3
config ESP32S3_APPCPU_IRAM
hex "ESP32S3 APPCPU IRAM size"
depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU
default 0x20000
help
Defines APPCPU IRAM area in bytes.
config ESP32S3_APPCPU_DRAM
hex "ESP32S3 APPCPU DRAM size"
depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU
default 0x10000
help
Defines APPCPU DRAM area in bytes.
config SOC_ENABLE_APPCPU
bool
default y
depends on IPM && SOC_ESP32S3_PROCPU
depends on MBOX && SOC_ESP32S3_PROCPU
help
This hidden configuration lets PROCPU core to map and start APPCPU whenever IPM is enabled.
menu "Cache config" menu "Cache config"
choice ESP32S3_INSTRUCTION_CACHE_SIZE choice ESP32S3_INSTRUCTION_CACHE_SIZE
@ -178,4 +156,6 @@ config MAC_BB_PD
endmenu # Cache config endmenu # Cache config
rsource "Kconfig.amp"
endif # SOC_SERIES_ESP32S3 endif # SOC_SERIES_ESP32S3

View file

@ -0,0 +1,31 @@
# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
if SOC_SERIES_ESP32S3
menu "AMP config"
config ESP32S3_APPCPU_IRAM_SIZE
hex "ESP32S3 APPCPU IRAM size"
depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU
default 0x10000
help
Defines APPCPU IRAM area size in bytes.
config ESP32S3_APPCPU_DRAM_SIZE
hex "ESP32S3 APPCPU DRAM size"
depends on SOC_ESP32S3_PROCPU || SOC_ESP32S3_APPCPU
default 0x10000
help
Defines APPCPU DRAM area size in bytes.
config SOC_ENABLE_APPCPU
bool
default y
depends on (IPM || MBOX) && SOC_ESP32S3_PROCPU
help
This hidden configuration lets PROCPU core to map and start APPCPU whenever IPM is enabled.
endmenu # AMP config
endif # SOC_SERIES_ESP32S3

View file

@ -9,4 +9,7 @@ config FLASH_SIZE
config FLASH_BASE_ADDRESS config FLASH_BASE_ADDRESS
default $(dt_node_reg_addr_hex,/soc/flash-controller@60002000/flash@0) default $(dt_node_reg_addr_hex,/soc/flash-controller@60002000/flash@0)
config BOOTLOADER_MCUBOOT
default y if SOC_ESP32S3_APPCPU
endif # SOC_SERIES_ESP32S3 endif # SOC_SERIES_ESP32S3

View file

@ -10,24 +10,16 @@
#include "memory.h" #include "memory.h"
/* The "user_iram_end" represents the 2nd stage bootloader
* "iram_loader_seg" start address (that should not be overlapped).
* If no bootloader is used, we can extend it to gain more user ram.
*/
#ifdef CONFIG_ESP_SIMPLE_BOOT
user_iram_end = (BOOTLOADER_USER_DRAM_END + IRAM_DRAM_OFFSET);
#else
user_iram_end = BOOTLOADER_IRAM_LOADER_SEG_START;
#endif
/* User available SRAM memory segments */ /* User available SRAM memory segments */
user_dram_seg_org = SRAM1_DRAM_START; amp_total_size = APPCPU_SRAM_TOTAL_SIZE;
user_iram_seg_org = SRAM0_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE; procpu_iram_end = USER_IRAM_END - APPCPU_SRAM_TOTAL_SIZE;
user_dram_end = BOOTLOADER_IRAM_LOADER_SEG_START - IRAM_DRAM_OFFSET; procpu_dram_end = USER_DRAM_END - APPCPU_SRAM_TOTAL_SIZE;
user_idram_size = user_dram_end - SRAM1_DRAM_START;
sram0_iram_size = SRAM0_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE; procpu_iram_org = SRAM_USER_IRAM_START;
user_iram_seg_len = user_idram_size + sram0_iram_size; procpu_iram_len = procpu_iram_end - procpu_iram_org;
user_dram_seg_len = user_idram_size;
procpu_dram_org = SRAM1_DRAM_START;
procpu_dram_len = procpu_dram_end - procpu_dram_org;
/* Aliases */ /* Aliases */
#define FLASH_CODE_REGION irom0_0_seg #define FLASH_CODE_REGION irom0_0_seg
@ -36,6 +28,7 @@ user_dram_seg_len = user_idram_size;
#define RAMABLE_REGION dram0_0_seg #define RAMABLE_REGION dram0_0_seg
#define ROMABLE_REGION FLASH #define ROMABLE_REGION FLASH
/* Zephyr macro re-definitions */
#undef GROUP_DATA_LINK_IN #undef GROUP_DATA_LINK_IN
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion #define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion
@ -66,14 +59,13 @@ MEMORY
FLASH (R): org = 0x0, len = FLASH_SIZE - 0x100 FLASH (R): org = 0x0, len = FLASH_SIZE - 0x100
#endif /* CONFIG_BOOTLOADER_MCUBOOT */ #endif /* CONFIG_BOOTLOADER_MCUBOOT */
iram0_0_seg(RX): org = user_iram_seg_org, len = user_iram_seg_len - APPCPU_IRAM_SIZE iram0_0_seg(RX): org = procpu_iram_org, len = procpu_iram_len
dram0_0_seg(RW): org = user_dram_seg_org, len = user_dram_seg_len - APPCPU_DRAM_SIZE dram0_0_seg(RW): org = procpu_dram_org, len = procpu_dram_len
irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_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 drom0_0_seg(R): org = DROM_SEG_ORG, len = DROM_SEG_LEN
/** /* The `ext_ram_seg` and `drom0_0_seg` share the same bus and the address region.
* `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` * A dummy section is used to avoid overlap. See `.ext_ram.dummy` in `sections.ld.in`
*/ */
#if defined(CONFIG_ESP_SPIRAM) #if defined(CONFIG_ESP_SPIRAM)
@ -101,7 +93,11 @@ MEMORY
ENTRY(CONFIG_KERNEL_ENTRY) ENTRY(CONFIG_KERNEL_ENTRY)
/* Used as a pointer to the heap end */ /* Used as a pointer to the heap end */
#ifdef CONFIG_SOC_ENABLE_APPCPU
_heap_sentry = procpu_dram_end;
#else
_heap_sentry = DRAM_RESERVED_START; _heap_sentry = DRAM_RESERVED_START;
#endif
SECTIONS SECTIONS
{ {
@ -116,6 +112,7 @@ SECTIONS
QUAD(0x0) QUAD(0x0)
QUAD(0x0) QUAD(0x0)
} > mcuboot_hdr } > mcuboot_hdr
/* Image load table */
.metadata : .metadata :
{ {
/* 0. Magic byte for load header */ /* 0. Magic byte for load header */
@ -144,7 +141,6 @@ SECTIONS
} > metadata } > metadata
#endif /* CONFIG_BOOTLOADER_MCUBOOT */ #endif /* CONFIG_BOOTLOADER_MCUBOOT */
/* Virtual non-loadable sections */ /* Virtual non-loadable sections */
#include <zephyr/linker/rel-sections.ld> #include <zephyr/linker/rel-sections.ld>
@ -275,7 +271,9 @@ SECTIONS
*(.entry.text) *(.entry.text)
*(.init.literal) *(.init.literal)
*(.init) *(.init)
_init_end = ABSOLUTE(.); _init_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
.iram0.text : ALIGN(4) .iram0.text : ALIGN(4)
@ -310,6 +308,11 @@ SECTIONS
*libphy.a:(.phyiram .phyiram.*) *libphy.a:(.phyiram .phyiram.*)
*libgcov.a:(.literal .text .literal.* .text.*) *libgcov.a:(.literal .text .literal.* .text.*)
/* APPCPU_ENABLED */
*libzephyr.a:esp32s3-mp.*(.literal .text .literal.* .text.*)
*libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libzephyr.a:flash_mmap.*(.literal .text .literal.* .text.*)
/* [mapping:esp_psram] */ /* [mapping:esp_psram] */
*libzephyr.a:mmu_psram_flash.*(.literal .literal.* .text .text.*) *libzephyr.a:mmu_psram_flash.*(.literal .literal.* .text .text.*)
*libzephyr.a:esp_psram_impl_quad.*(.literal .literal.* .text .text.*) *libzephyr.a:esp_psram_impl_quad.*(.literal .literal.* .text .text.*)
@ -550,6 +553,11 @@ SECTIONS
*libzephyr.a:esp_mmu_map.*(.rodata .rodata.*) *libzephyr.a:esp_mmu_map.*(.rodata .rodata.*)
*libdrivers__interrupt_controller.a:(.rodata .rodata.*) *libdrivers__interrupt_controller.a:(.rodata .rodata.*)
/* APPCPU_ENABLE */
*libzephyr.a:esp32s3-mp.*(.rodata .rodata.*)
*libzephyr.a:bootloader_flash.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
*libzephyr.a:flash_mmap.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
/* [mapping:esp_psram] */ /* [mapping:esp_psram] */
*libzephyr.a:mmu_psram_flash.*(.rodata .rodata.*) *libzephyr.a:mmu_psram_flash.*(.rodata .rodata.*)
*libzephyr.a:esp_psram_impl_octal.*(.rodata .rodata.*) *libzephyr.a:esp_psram_impl_octal.*(.rodata .rodata.*)
@ -798,6 +806,10 @@ SECTIONS
} GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION)
/* --- END OF IROM --- */
/* --- START OF DROM --- */
/* This dummy section represents the .flash.text section but in default_rodata_seg. /* This dummy section represents the .flash.text section but in default_rodata_seg.
* Thus, it must have its alignment and (at least) its size. * Thus, it must have its alignment and (at least) its size.
*/ */
@ -879,6 +891,10 @@ SECTIONS
_image_rodata_end = ABSOLUTE(.); _image_rodata_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION)
/* --- END OF DROM --- */
/* --- START OF SPIRAM --- */
/** /**
* This section is required to skip flash rodata sections, because `ext_ram_seg` * This section is required to skip flash rodata sections, because `ext_ram_seg`
* and `drom0_0_seg` are on the same bus * and `drom0_0_seg` are on the same bus
@ -907,8 +923,9 @@ SECTIONS
#endif /* CONFIG_ESP_SPIRAM */ #endif /* CONFIG_ESP_SPIRAM */
/* --- XTENSA GLUE AND DEBUG BEGIN --- */ /* --- END OF SPIRAM --- */
/* --- XTENSA GLUE AND DEBUG BEGIN --- */
#ifdef CONFIG_GEN_ISR_TABLES #ifdef CONFIG_GEN_ISR_TABLES
#include <zephyr/linker/intlist.ld> #include <zephyr/linker/intlist.ld>
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -8,48 +8,121 @@
#include <zephyr/linker/linker-defs.h> #include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h> #include <zephyr/linker/linker-tool.h>
#define SRAM_IRAM_START 0x40370000 #include "memory.h"
#define SRAM_DIRAM_I_START 0x40378000
#define SRAM_IRAM_END 0x403BA000
#define I_D_SRAM_OFFSET (SRAM_DIRAM_I_START - SRAM_DRAM_START)
#define DRAM_RESERVED_START 0x3fce9704
#define IRAM_DRAM_OFFSET 0x6f0000
#define SRAM_DRAM_START 0x3FC88000 /* User available SRAM memory segments */
#define SRAM_DRAM_END (SRAM_IRAM_END - I_D_SRAM_OFFSET) appcpu_iram_end = USER_IRAM_END;
appcpu_dram_end = USER_DRAM_END;
#define IRAM_REGION iram0_0_seg appcpu_iram_org = appcpu_iram_end - APPCPU_SRAM_SIZE;
#define RAMABLE_REGION dram0_0_seg appcpu_dram_org = appcpu_dram_end - APPCPU_SRAM_SIZE;
#define ROMABLE_REGION iram0_0_seg
#define IROM_SEG_ALIGN 0x4 appcpu_iram_len = APPCPU_SRAM_SIZE;
appcpu_dram_len = APPCPU_SRAM_SIZE;
/* Aliases */
#define ROMABLE_REGION FLASH
#define RODATA_REGION dram0_1_seg /* drom0_1_seg */
#define RAMABLE_REGION dram0_1_seg
#define IRAM_REGION iram0_1_seg
/* Zephyr macro re-definitions */
#undef GROUP_DATA_LINK_IN
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion
#undef GROUP_NOLOAD_LINK_IN
#define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion
/* Flash segments (rodata and text) should be mapped in the virtual address spaces.
* Executing directly from LMA is not possible. */
#undef GROUP_ROM_LINK_IN
#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion
/* Make sure new sections have consistent alignment between input and output sections */
#undef SECTION_DATA_PROLOGUE
#define SECTION_DATA_PROLOGUE(name, options, align) name options : ALIGN_WITH_INPUT
#undef SECTION_PROLOGUE
#define SECTION_PROLOGUE SECTION_DATA_PROLOGUE
MEMORY MEMORY
{ {
iram0_0_seg(RX): org = SRAM_IRAM_END - CONFIG_ESP32S3_APPCPU_IRAM, len = CONFIG_ESP32S3_APPCPU_IRAM #ifdef CONFIG_BOOTLOADER_MCUBOOT
dram0_0_seg(RW): org = SRAM_DRAM_END - CONFIG_ESP32S3_APPCPU_DRAM, len = CONFIG_ESP32S3_APPCPU_DRAM mcuboot_hdr (R): org = 0x0, len = 0x20
metadata (R): org = 0x20, len = 0x20
FLASH (R): org = 0x40, len = FLASH_SIZE - 0x40
#else
/* Make safety margin in the FLASH memory size so the
* (esp_img_header + (n*esp_seg_headers)) would fit */
FLASH (R): org = 0x0, len = FLASH_SIZE - 0x100
#endif /* CONFIG_BOOTLOADER_MCUBOOT */
iram0_1_seg(RX): org = appcpu_iram_org, len = appcpu_iram_len
dram0_1_seg(RW): org = appcpu_dram_org, len = appcpu_dram_len
#ifdef CONFIG_GEN_ISR_TABLES #ifdef CONFIG_GEN_ISR_TABLES
IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000
#endif #endif
} }
/* Default entry point: */ /* Default entry point: */
ENTRY(__app_cpu_start) ENTRY(__appcpu_start)
/* Used as a pointer to the heap end */ /* Used as a pointer to the heap end */
_heap_sentry = DRAM_RESERVED_START; _heap_sentry = DRAM_RESERVED_START;
SECTIONS SECTIONS
{ {
#if defined(CONFIG_BOOTLOADER_MCUBOOT)
/* Reserve space for MCUboot header in the binary */
.mcuboot_header :
{
QUAD(0x0)
QUAD(0x0)
QUAD(0x0)
QUAD(0x0)
} > mcuboot_hdr
/* Image load table */
.metadata :
{
/* 0. Magic byte for load header */
LONG(0xace637d3)
/* 1. Application entry point address */
KEEP(*(.entry_addr))
/* IRAM metadata:
* 2. Destination address (VMA) for IRAM region
* 3. Flash offset (LMA) for start of IRAM region
* 4. Size of IRAM region
*/
LONG(ADDR(.iram0.vectors))
LONG(LOADADDR(.iram0.vectors))
LONG(_iram_end - _init_start);
/* DRAM metadata:
* 5. Destination address (VMA) for DRAM region
* 6. Flash offset (LMA) for start of DRAM region
* 7. Size of DRAM region
*/
LONG(ADDR(.dram0.data))
LONG(LOADADDR(.dram0.data))
LONG(_data_end - _data_start)
} > metadata
#endif /* CONFIG_BOOTLOADER_MCUBOOT */
#include <zephyr/linker/rel-sections.ld> #include <zephyr/linker/rel-sections.ld>
#ifdef CONFIG_LLEXT #ifdef CONFIG_LLEXT
#include <zephyr/linker/llext-sections.ld> #include <zephyr/linker/llext-sections.ld>
#endif #endif
/* --- START OF IRAM --- */
/* Send .iram0 code to iram */ /* Send .iram0 code to iram */
.iram0.vectors : ALIGN(4) .iram0.vectors : ALIGN(4)
{ {
_iram_start = ABSOLUTE(.);
/* Vectors go to IRAM */ /* Vectors go to IRAM */
_init_start = ABSOLUTE(.); _init_start = ABSOLUTE(.);
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
@ -83,15 +156,14 @@ SECTIONS
*(.entry.text) *(.entry.text)
*(.init.literal) *(.init.literal)
*(.init) *(.init)
. = ALIGN (4); . = ALIGN (16);
_init_end = ABSOLUTE(.); _init_end = ABSOLUTE(.);
_iram_start = ABSOLUTE(.); } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
} GROUP_LINK_IN(IRAM_REGION)
SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) .iram0.text : ALIGN(4)
{ {
/* Code marked as running out of IRAM */
_iram_text_start = ABSOLUTE(.); _iram_text_start = ABSOLUTE(.);
*(.iram1 .iram1.*) *(.iram1 .iram1.*)
*(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text)
@ -122,13 +194,104 @@ SECTIONS
*libphy.a:(.phyiram .phyiram.*) *libphy.a:(.phyiram .phyiram.*)
*libgcov.a:(.literal .text .literal.* .text.*) *libgcov.a:(.literal .text .literal.* .text.*)
. = ALIGN(16);
} GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
.flash.text : ALIGN(16)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
*(.literal .text .literal.* .text.*)
/* CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
/* Similar to _iram_start, this symbol goes here so it is
* resolved by addr2line in preference to the first symbol in
* the flash.text segment.
*/
. = ALIGN(4);
_flash_cache_start = ABSOLUTE(0);
. = ALIGN(4); . = ALIGN(4);
_iram_end = ABSOLUTE(.); _iram_end = ABSOLUTE(.);
. = ALIGN(4) + 16;
} GROUP_LINK_IN(IRAM_REGION) } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) /* --- END OF IRAM --- */
/* --- START OF DRAM --- */
.dram0.dummy (NOLOAD):
{
. = ORIGIN(dram0_1_seg) + MAX(_iram_end, appcpu_iram_org) - appcpu_iram_org;
. = ALIGN(16);
} GROUP_LINK_IN(RAMABLE_REGION)
.dram0.data :
{
. = ALIGN (8);
__data_start = ABSOLUTE(.);
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
/* rodata for panic handler(libarch__xtensa__core.a) and all
* dependent functions should be placed in DRAM to avoid issue
* when flash cache is disabled */
*libarch__xtensa__core.a:(.rodata .rodata.*)
*libkernel.a:fatal.*(.rodata .rodata.*)
*libkernel.a:init.*(.rodata .rodata.*)
*libzephyr.a:cbprintf_complete*(.rodata .rodata.*)
*libzephyr.a:systimer_hal.*(.rodata .rodata.*)
*libzephyr.a:log_core.*(.rodata .rodata.*)
*libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
*libzephyr.a:log_output.*(.rodata .rodata.*)
*libzephyr.a:loader.*(.rodata .rodata.*)
*libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*)
*libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
. = ALIGN(4);
#include <snippets-rwdata.ld>
. = ALIGN(4);
KEEP(*(.jcr))
*(.dram1 .dram1.*)
. = ALIGN(16);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#include <snippets-data-sections.ld>
#include <zephyr/linker/common-ram.ld>
#include <snippets-ram-sections.ld>
#include <zephyr/linker/cplusplus-ram.ld>
#include <zephyr/linker/kobject-data.ld>
#include <zephyr/linker/common-rom/common-rom-logging.ld>
/* SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) */
.dram0.rodata : ALIGN(4)
{ {
_rodata_start = ABSOLUTE(.); _rodata_start = ABSOLUTE(.);
@ -140,8 +303,29 @@ SECTIONS
#include <snippets-rodata.ld> #include <snippets-rodata.ld>
. = ALIGN(4); . = ALIGN(4);
*(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__serial.a:uart_esp32.*) .rodata) *(EXCLUDE_FILE (
*(EXCLUDE_FILE (*libarch__xtensa__core.a:* *libkernel.a:fatal.* *libkernel.a:init.* *libzephyr.a:cbprintf_complete* *libzephyr.a:log_core.* *libzephyr.a:log_backend_uart.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__serial.a:uart_esp32.*) .rodata.*) *libarch__xtensa__core.a:*
*libkernel.a:fatal.*
*libkernel.a:init.*
*libzephyr.a:cbprintf_complete*
*libzephyr.a:log_core.*
*libzephyr.a:log_backend_uart.*
*libzephyr.a:log_output.*
*libzephyr.a:loader.*
*libdrivers__serial.a:uart_esp32.*) .rodata)
*(EXCLUDE_FILE (
*libarch__xtensa__core.a:*
*libkernel.a:fatal.*
*libkernel.a:init.*
*libzephyr.a:cbprintf_complete*
*libzephyr.a:log_core.*
*libzephyr.a:log_backend_uart.*
*libzephyr.a:log_output.*
*libzephyr.a:loader.*
*libdrivers__serial.a:uart_esp32.*) .rodata.*)
. = ALIGN(4);
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*) *(.gnu.linkonce.r.*)
@ -183,13 +367,15 @@ SECTIONS
_thread_local_end = ABSOLUTE(.); _thread_local_end = ABSOLUTE(.);
_rodata_reserved_end = ABSOLUTE(.); _rodata_reserved_end = ABSOLUTE(.);
. = ALIGN(4); . = ALIGN(4);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA.
* Executing directly from LMA is not possible. */ * Executing directly from LMA is not possible. */
#pragma push_macro("GROUP_ROM_LINK_IN") #pragma push_macro("GROUP_ROM_LINK_IN")
#undef GROUP_ROM_LINK_IN #undef GROUP_ROM_LINK_IN
#define GROUP_ROM_LINK_IN(vregion, lregion) > RAMABLE_REGION AT > lregion #define GROUP_ROM_LINK_IN(vregion, lregion) > RAMABLE_REGION AT > lregion
#include <zephyr/linker/cplusplus-rom.ld>
#include <zephyr/linker/common-rom/common-rom-init.ld> #include <zephyr/linker/common-rom/common-rom-init.ld>
#include <zephyr/linker/common-rom/common-rom-kernel-devices.ld> #include <zephyr/linker/common-rom/common-rom-kernel-devices.ld>
#include <zephyr/linker/common-rom/common-rom-ztest.ld> #include <zephyr/linker/common-rom/common-rom-ztest.ld>
@ -197,78 +383,37 @@ SECTIONS
#include <zephyr/linker/common-rom/common-rom-bt.ld> #include <zephyr/linker/common-rom/common-rom-bt.ld>
#include <zephyr/linker/common-rom/common-rom-debug.ld> #include <zephyr/linker/common-rom/common-rom-debug.ld>
#include <zephyr/linker/common-rom/common-rom-misc.ld> #include <zephyr/linker/common-rom/common-rom-misc.ld>
#include <zephyr/linker/thread-local-storage.ld>
#include <snippets-sections.ld>
#pragma pop_macro("GROUP_ROM_LINK_IN") #pragma pop_macro("GROUP_ROM_LINK_IN")
/* Create an explicit section at the end of all the data that shall be mapped into drom. /* Create an explicit section at the end of all the data that shall be mapped into drom.
* This is used to calculate the size of the _image_drom_size variable */ * This is used to calculate the size of the _image_drom_size variable */
SECTION_PROLOGUE(_RODATA_SECTION_END,,) /* SECTION_PROLOGUE(_RODATA_SECTION_END,,) */
.dram0.rodata_end : ALIGN(0x10)
{ {
. = ALIGN(16); . = ALIGN(16);
_image_rodata_end = ABSOLUTE(.); _image_rodata_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#include <snippets-sections.ld>
.dram0.data :
{
. = ALIGN (8);
__data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
/* rodata for panic handler(libarch__xtensa__core.a) and all
* dependent functions should be placed in DRAM to avoid issue
* when flash cache is disabled */
*libarch__xtensa__core.a:(.rodata .rodata.*)
*libkernel.a:fatal.*(.rodata .rodata.*)
*libkernel.a:init.*(.rodata .rodata.*)
*libzephyr.a:cbprintf_complete*(.rodata .rodata.*)
*libzephyr.a:systimer_hal.*(.rodata .rodata.*)
*libzephyr.a:log_core.*(.rodata .rodata.*)
*libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
*libzephyr.a:log_output.*(.rodata .rodata.*)
*libzephyr.a:loader.*(.rodata .rodata.*)
*libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*)
*libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
KEEP(*(.jcr))
*(.dram1 .dram1.*)
. = ALIGN(4);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION)
#include <zephyr/linker/cplusplus-rom.ld>
#include <snippets-data-sections.ld>
#include <zephyr/linker/common-ram.ld>
#include <snippets-ram-sections.ld>
#include <zephyr/linker/cplusplus-ram.ld>
/* logging sections should be placed in RAM area to avoid flash cache disabled issues */
#pragma push_macro("GROUP_ROM_LINK_IN")
#undef GROUP_ROM_LINK_IN
#define GROUP_ROM_LINK_IN GROUP_DATA_LINK_IN
#include <zephyr/linker/common-rom/common-rom-logging.ld>
#pragma pop_macro("GROUP_ROM_LINK_IN")
.dram0.end : .dram0.end :
{ {
. = ALIGN(4);
#include <snippets-rwdata.ld>
. = ALIGN(4);
__data_end = ABSOLUTE(.); __data_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, IRAM_REGION) _data_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
.dram0.noinit (NOLOAD):
{
. = ALIGN(8);
*(.noinit)
*(.noinit.*)
. = ALIGN(8) ;
} GROUP_LINK_IN(RAMABLE_REGION)
/* Shared RAM */ /* Shared RAM */
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) .dram0.bss (NOLOAD) :
{ {
. = ALIGN (8); . = ALIGN (8);
_bss_start = ABSOLUTE(.); /* required by bluetooth library */ _bss_start = ABSOLUTE(.); /* required by bluetooth library */
@ -296,45 +441,15 @@ SECTIONS
_image_ram_start = _iram_start - IRAM_DRAM_OFFSET; _image_ram_start = _iram_start - IRAM_DRAM_OFFSET;
#include <zephyr/linker/ram-end.ld> #include <zephyr/linker/ram-end.ld>
ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") ASSERT(((__bss_end - ORIGIN(dram0_1_seg)) <= LENGTH(dram0_1_seg)), "DRAM segment data does not fit.")
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) /* --- END OF DRAM --- */
{
. = ALIGN(8);
*(.noinit)
*(.noinit.*)
. = ALIGN(8) ;
} GROUP_LINK_IN(RAMABLE_REGION)
.flash.text : ALIGN(IROM_SEG_ALIGN) /* --- START OF IROM --- */
{ /* --- END OF IROM --- */
_stext = .;
_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) /* --- START OF DROM --- */
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ /* --- END OF DROM --- */
*(.fini.literal)
*(.fini)
*(.gnu.version)
*(.literal .text .literal.* .text.*)
/* CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
/* Similar to _iram_start, this symbol goes here so it is
* resolved by addr2line in preference to the first symbol in
* the flash.text segment.
*/
. = ALIGN(4);
_flash_cache_start = ABSOLUTE(0);
} GROUP_LINK_IN(IRAM_REGION)
#ifdef CONFIG_GEN_ISR_TABLES #ifdef CONFIG_GEN_ISR_TABLES
#include <zephyr/linker/intlist.ld> #include <zephyr/linker/intlist.ld>
@ -375,8 +490,7 @@ SECTIONS
KEEP (*(.xt.profile_files)) KEEP (*(.xt.profile_files))
KEEP (*(.gnu.linkonce.xt.profile_files.*)) KEEP (*(.gnu.linkonce.xt.profile_files.*))
} }
} }
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), ASSERT(((_iram_end - ORIGIN(iram0_1_seg)) <= LENGTH(iram0_1_seg)),
"IRAM0 segment data does not fit.") "IRAM0 segment data does not fit.")

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -8,19 +8,22 @@
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/spinlock.h> #include <zephyr/spinlock.h>
#include <zephyr/kernel_structs.h> #include <zephyr/kernel_structs.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
#include <soc.h> #include <soc.h>
#include <esp_cpu.h> #include <esp_cpu.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h> #include "esp_rom_uart.h"
void smp_log(const char *msg) #include "esp_mcuboot_image.h"
{ #include "esp_memory_utils.h"
while (*msg) {
esp_rom_uart_tx_one_char(*msg++); #ifdef CONFIG_SOC_ENABLE_APPCPU
}
esp_rom_uart_tx_one_char('\r'); #include "bootloader_flash_priv.h"
esp_rom_uart_tx_one_char('\n');
} #define sys_mmap bootloader_mmap
#define sys_munmap bootloader_munmap
void esp_appcpu_start(void *entry_point) void esp_appcpu_start(void *entry_point)
{ {
@ -35,7 +38,135 @@ void esp_appcpu_start(void *entry_point)
esp_rom_ets_set_appcpu_boot_addr((void *)entry_point); esp_rom_ets_set_appcpu_boot_addr((void *)entry_point);
ets_delay_us(50000); esp_cpu_reset(1);
smp_log("ESP32S3: CPU1 start sequence complete");
} }
static int load_segment(uint32_t src_addr, uint32_t src_len, uint32_t dst_addr)
{
const uint32_t *data = (const uint32_t *)sys_mmap(src_addr, src_len);
if (!data) {
ets_printf("%s: mmap failed", __func__);
return -1;
}
volatile uint32_t *dst = (volatile uint32_t *)dst_addr;
for (int i = 0; i < src_len / 4; i++) {
dst[i] = data[i];
}
sys_munmap(data);
return 0;
}
int IRAM_ATTR esp_appcpu_image_load(unsigned int hdr_offset, unsigned int *entry_addr)
{
const uint32_t img_off = FIXED_PARTITION_OFFSET(slot0_appcpu_partition);
const uint32_t fa_size = FIXED_PARTITION_SIZE(slot0_appcpu_partition);
const uint8_t fa_id = FIXED_PARTITION_ID(slot0_appcpu_partition);
int rc = 0;
if (entry_addr == NULL) {
ets_printf("Can't return the entry address. Aborting!\n");
abort();
return -1;
}
ets_printf("Loading appcpu image, area id: %d, offset: 0x%x, hdr.off: 0x%x, size: %d kB\n",
fa_id, img_off, hdr_offset, fa_size / 1024);
uint32_t mcuboot_header[8] = {0};
esp_image_load_header_t image_header = {0};
const uint32_t *data = (const uint32_t *)sys_mmap(img_off, 0x40);
memcpy((void *)&mcuboot_header, data, sizeof(mcuboot_header));
memcpy((void *)&image_header, data + (hdr_offset / sizeof(uint32_t)),
sizeof(esp_image_load_header_t));
sys_munmap(data);
if (image_header.header_magic == ESP_LOAD_HEADER_MAGIC) {
ets_printf("MCUboot image format\n");
} else if ((image_header.header_magic & 0xff) == 0xE9) {
ets_printf("ESP image format is not supported\n");
abort();
} else {
ets_printf("Unknown or empty image detected. Aborting!\n");
abort();
}
if (!esp_ptr_in_iram((void *)image_header.iram_dest_addr) ||
!esp_ptr_in_iram((void *)(image_header.iram_dest_addr + image_header.iram_size))) {
ets_printf("IRAM region in load header is not valid. Aborting");
abort();
}
if (!esp_ptr_in_dram((void *)image_header.dram_dest_addr) ||
!esp_ptr_in_dram((void *)(image_header.dram_dest_addr + image_header.dram_size))) {
ets_printf("DRAM region in load header is not valid. Aborting");
abort();
}
if (!esp_ptr_in_iram((void *)image_header.entry_addr)) {
ets_printf("Application entry point (%xh) is not in IRAM. Aborting",
image_header.entry_addr);
abort();
}
ets_printf("IRAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) load\n",
(img_off + image_header.iram_flash_offset), image_header.iram_dest_addr,
image_header.iram_size, image_header.iram_size);
load_segment(img_off + image_header.iram_flash_offset, image_header.iram_size,
image_header.iram_dest_addr);
ets_printf("DRAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) load\n",
(img_off + image_header.dram_flash_offset), image_header.dram_dest_addr,
image_header.dram_size, image_header.dram_size);
load_segment(img_off + image_header.dram_flash_offset, image_header.dram_size,
image_header.dram_dest_addr);
ets_printf("Application start=%xh\n", image_header.entry_addr);
esp_rom_uart_tx_wait_idle(0);
assert(entry_addr != NULL);
*entry_addr = image_header.entry_addr;
return rc;
}
void esp_appcpu_image_stop(void)
{
esp_cpu_stall(1);
}
void esp_appcpu_image_start(unsigned int hdr_offset)
{
static int started;
unsigned int entry_addr = 0;
if (started) {
printk("APPCPU already started.\r\n");
return;
}
/* Input image meta header, output appcpu entry point */
esp_appcpu_image_load(hdr_offset, &entry_addr);
esp_appcpu_start((void *)entry_addr);
}
int esp_appcpu_init(void)
{
/* Load APPCPU image using image header offset
* (skipping the MCUBoot header)
*/
esp_appcpu_image_start(0x20);
return 0;
}
#endif /* CONFIG_SOC_ENABLE_APPCPU */

View file

@ -4,17 +4,19 @@
*/ */
#pragma once #pragma once
/* SRAM0 (64k), SRAM1 (416k), SRAM2 (64k) memories /* SRAM0 (32k), SRAM1 (416k), SRAM2 (64k) memories
* Ibus and Dbus address space * Ibus and Dbus address space
*/ */
#define SRAM0_IRAM_START 0x40370000 #define SRAM0_IRAM_START 0x40370000
#define SRAM0_SIZE 0x8000 #define SRAM0_SIZE 0x8000
#define SRAM1_DRAM_START 0x3fc88000 #define SRAM1_DRAM_START 0x3fc88000
#define SRAM1_IRAM_START 0x40378000
#define SRAM_USER_IRAM_START (SRAM0_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE)
/* IRAM equivalent address where DRAM actually start */
#define SRAM1_IRAM_START (SRAM0_IRAM_START + SRAM0_SIZE)
#define SRAM2_DRAM_START 0x3fcf0000 #define SRAM2_DRAM_START 0x3fcf0000
#define SRAM2_SIZE 0x10000 #define SRAM2_SIZE 0x10000
#define SRAM2_USER_DRAM_START (SRAM2_DRAM_START + CONFIG_ESP32S3_DATA_CACHE_SIZE)
#define SRAM2_USER_DRAM_SIZE (SRAM2_SIZE - CONFIG_ESP32S3_DATA_CACHE_SIZE)
/** Simplified memory map for the bootloader. /** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself. * Make sure the bootloader can load into main memory without overwriting itself.
@ -43,24 +45,51 @@
/* Set the limit for the application runtime dynamic allocations */ /* Set the limit for the application runtime dynamic allocations */
#define DRAM_RESERVED_START DRAM_BUFFERS_END #define DRAM_RESERVED_START DRAM_BUFFERS_END
/* Base address used for calculating memory layout
* counted from Dbus backwards and back to the Ibus
*/
#define BOOTLOADER_USER_DRAM_END DRAM_BUFFERS_START
/* For safety margin between bootloader data section and startup stacks */ /* For safety margin between bootloader data section and startup stacks */
#define BOOTLOADER_STACK_OVERHEAD 0x0 #define BOOTLOADER_STACK_OVERHEAD 0x0
#define BOOTLOADER_DRAM_SEG_LEN 0x15000 #define BOOTLOADER_DRAM_SEG_LEN 0x15000
#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x1a00 #define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x1a00
#define BOOTLOADER_IRAM_SEG_LEN 0xc000 #define BOOTLOADER_IRAM_SEG_LEN 0xc000
/* Base address used for calculating memory layout
* counted from Dbus backwards and back to the Ibus
*/
#define BOOTLOADER_USER_DRAM_END (DRAM_BUFFERS_START - BOOTLOADER_STACK_OVERHEAD)
/* Start of the lower region is determined by region size and the end of the higher region */ /* Start of the lower region is determined by region size and the end of the higher region */
#define BOOTLOADER_IRAM_LOADER_SEG_START (BOOTLOADER_USER_DRAM_END - BOOTLOADER_STACK_OVERHEAD + \ #define BOOTLOADER_IRAM_LOADER_SEG_START \
IRAM_DRAM_OFFSET - BOOTLOADER_IRAM_LOADER_SEG_LEN) (BOOTLOADER_USER_DRAM_END - BOOTLOADER_IRAM_LOADER_SEG_LEN + IRAM_DRAM_OFFSET)
#define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN) #define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN)
#define BOOTLOADER_DRAM_SEG_END (BOOTLOADER_IRAM_SEG_START - IRAM_DRAM_OFFSET) #define BOOTLOADER_DRAM_SEG_END (BOOTLOADER_IRAM_SEG_START - IRAM_DRAM_OFFSET)
#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_DRAM_SEG_END - BOOTLOADER_DRAM_SEG_LEN) #define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_DRAM_SEG_END - BOOTLOADER_DRAM_SEG_LEN)
/* The "USER_IRAM_END" represents the end of staticaly allocated memory.
* This address is where 2nd stage bootloader starts allocating memory,
* and it should not be overlapped by the user image.
* When there is no 2nd stage bootloader the bootstrapping is done
* by the so-called SIMPLE_BOOT.
*/
#ifdef CONFIG_ESP_SIMPLE_BOOT
#define USER_DRAM_END BOOTLOADER_USER_DRAM_END
#else
#define USER_DRAM_END (BOOTLOADER_IRAM_LOADER_SEG_START - IRAM_DRAM_OFFSET)
#endif
#define USER_IRAM_END (USER_DRAM_END + IRAM_DRAM_OFFSET)
/* AMP */
#if defined(CONFIG_SOC_ENABLE_APPCPU) || defined(CONFIG_SOC_ESP32S3_APPCPU)
#define APPCPU_IRAM_SIZE CONFIG_ESP32S3_APPCPU_IRAM_SIZE
#define APPCPU_DRAM_SIZE CONFIG_ESP32S3_APPCPU_DRAM_SIZE
#define AMP_COMM_SIZE (0x4000 + 0x400)
#else
#define APPCPU_IRAM_SIZE 0
#define APPCPU_DRAM_SIZE 0
#define AMP_COMM_SIZE 0
#endif
#define APPCPU_SRAM_SIZE (APPCPU_IRAM_SIZE + APPCPU_DRAM_SIZE)
#define APPCPU_SRAM_TOTAL_SIZE (APPCPU_SRAM_SIZE + AMP_COMM_SIZE)
/* Flash */ /* Flash */
#ifdef CONFIG_FLASH_SIZE #ifdef CONFIG_FLASH_SIZE
#define FLASH_SIZE CONFIG_FLASH_SIZE #define FLASH_SIZE CONFIG_FLASH_SIZE
@ -74,12 +103,3 @@
#define IROM_SEG_LEN FLASH_SIZE #define IROM_SEG_LEN FLASH_SIZE
#define DROM_SEG_ORG 0x3c000000 #define DROM_SEG_ORG 0x3c000000
#define DROM_SEG_LEN FLASH_SIZE #define DROM_SEG_LEN FLASH_SIZE
/* AMP */
#ifdef CONFIG_SOC_ENABLE_APPCPU
#define APPCPU_IRAM_SIZE CONFIG_ESP32S3_APPCPU_IRAM
#define APPCPU_DRAM_SIZE CONFIG_ESP32S3_APPCPU_DRAM
#else
#define APPCPU_IRAM_SIZE 0
#define APPCPU_DRAM_SIZE 0
#endif

View file

@ -47,49 +47,14 @@
#include <zephyr/sys/printk.h> #include <zephyr/sys/printk.h>
#include "esp_log.h" #include "esp_log.h"
#include <zephyr/drivers/flash.h>
#include <zephyr/storage/flash_map.h>
#define TAG "boot.esp32s3" #define TAG "boot.esp32s3"
extern void z_prep_c(void); extern void z_prep_c(void);
extern void esp_reset_reason_init(void); extern void esp_reset_reason_init(void);
extern int esp_appcpu_init(void);
#ifdef CONFIG_SOC_ENABLE_APPCPU
extern const unsigned char esp32s3_appcpu_fw_array[];
void IRAM_ATTR esp_start_appcpu(void)
{
esp_image_header_t *header = (esp_image_header_t *)&esp32s3_appcpu_fw_array[0];
esp_image_segment_header_t *segment =
(esp_image_segment_header_t *)&esp32s3_appcpu_fw_array[sizeof(esp_image_header_t)];
uint8_t *segment_payload;
uint32_t entry_addr = header->entry_addr;
uint32_t idx = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t);
for (int i = 0; i < header->segment_count; i++) {
segment_payload = (uint8_t *)&esp32s3_appcpu_fw_array[idx];
if (segment->load_addr >= SOC_IRAM_LOW && segment->load_addr < SOC_IRAM_HIGH) {
/* IRAM segment only accepts 4 byte access, avoid memcpy usage here */
volatile uint32_t *src = (volatile uint32_t *)segment_payload;
volatile uint32_t *dst = (volatile uint32_t *)segment->load_addr;
for (int i = 0; i < segment->data_len / 4; i++) {
dst[i] = src[i];
}
} else if (segment->load_addr >= SOC_DRAM_LOW &&
segment->load_addr < SOC_DRAM_HIGH) {
memcpy((void *)segment->load_addr, (const void *)segment_payload,
segment->data_len);
}
idx += segment->data_len;
segment = (esp_image_segment_header_t *)&esp32s3_appcpu_fw_array[idx];
idx += sizeof(esp_image_segment_header_t);
}
esp_appcpu_start((void *)entry_addr);
}
#endif /* CONFIG_SOC_ENABLE_APPCPU*/
#ifndef CONFIG_MCUBOOT #ifndef CONFIG_MCUBOOT
/* /*
@ -175,11 +140,6 @@ void IRAM_ATTR __esp_platform_start(void)
esp_init_psram(); esp_init_psram();
#endif /* CONFIG_ESP_SPIRAM */ #endif /* CONFIG_ESP_SPIRAM */
#if CONFIG_SOC_ENABLE_APPCPU
/* start the ESP32S3 APP CPU */
esp_start_appcpu();
#endif
#endif /* !CONFIG_MCUBOOT */ #endif /* !CONFIG_MCUBOOT */
esp_intr_initialize(); esp_intr_initialize();
@ -213,3 +173,8 @@ void sys_arch_reboot(int type)
{ {
esp_restart_noos(); esp_restart_noos();
} }
#if defined(CONFIG_SOC_ENABLE_APPCPU) && !defined(CONFIG_MCUBOOT)
extern int esp_appcpu_init(void);
SYS_INIT(esp_appcpu_init, POST_KERNEL, 50);
#endif

View file

@ -33,6 +33,11 @@
#include <esp_app_format.h> #include <esp_app_format.h>
#include <esp_clk_internal.h> #include <esp_clk_internal.h>
#define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used))
void __appcpu_start(void);
static HDR_ATTR void (*_entry_point)(void) = &__appcpu_start;
extern void z_prep_c(void); extern void z_prep_c(void);
static void core_intr_matrix_clear(void) static void core_intr_matrix_clear(void)
@ -44,7 +49,7 @@ static void core_intr_matrix_clear(void)
} }
} }
void IRAM_ATTR __app_cpu_start(void) void IRAM_ATTR __appcpu_start(void)
{ {
extern uint32_t _init_start; extern uint32_t _init_start;