soc: esp32: fixes and updates for AMP

Multiple AMP related updates:

- use common AMP Kconfig
- rework the APPCPU linker script
- use MCUboot image format for APPCPU image
- fix multi-processing startup code

Signed-off-by: Marek Matej <marek.matej@espressif.com>
This commit is contained in:
Marek Matej 2024-11-19 15:35:41 +00:00 committed by Benjamin Cabé
commit 322ab2a86e
12 changed files with 541 additions and 341 deletions

View file

@ -58,6 +58,7 @@ config ESP32_PHY_MAX_TX_POWER
endif
rsource "Kconfig.amp"
rsource "Kconfig.spiram"
rsource "Kconfig.esptool"
rsource "Kconfig.flash"

View file

@ -0,0 +1,26 @@
# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
config SOC_ENABLE_APPCPU
bool
default y
depends on (IPM || MBOX)
depends on SOC_SERIES_ESP32 || SOC_SERIES_ESP32S3
help
This hidden configuration lets PROCPU core to map and start APPCPU whenever IPM is enabled.
menu "Espressif AMP Config"
config ESP_APPCPU_IRAM_SIZE
hex "ESP32* APPCPU IRAM size"
default 0x10000
help
Defines APPCPU IRAM area size in bytes.
config ESP_APPCPU_DRAM_SIZE
hex "ESP32* APPCPU DRAM size"
default 0x10000
help
Defines APPCPU DRAM area size in bytes.
endmenu # AMP config

View file

@ -264,7 +264,8 @@ void __start(void)
}
#endif
#if !defined(CONFIG_MCUBOOT) && !defined(CONFIG_SOC_ESP32S3_APPCPU)
#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);
#endif

View file

@ -1,7 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
if (CONFIG_SOC_ESP32_APPCPU)
zephyr_sources(soc_appcpu.c)
zephyr_sources(
soc_appcpu.c
)
else()
zephyr_sources(
soc.c
@ -24,13 +26,24 @@ zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c)
# get flash size to use in esptool as string
math(EXPR esptoolpy_flashsize "${CONFIG_FLASH_SIZE} / 0x100000")
# This includes CONFIG_MCUBOOT and CONFIG_ESP_SIMPLE_BOOT
if(NOT CONFIG_BOOTLOADER_MCUBOOT)
# Get UART baudrate from DT
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)
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 "")
if(NOT CONFIG_MCUBOOT)
@ -39,56 +52,47 @@ if(NOT CONFIG_BOOTLOADER_MCUBOOT)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND ${PYTHON_EXECUTABLE} ${ESPTOOL_PY}
ARGS --chip esp32 elf2image ${ELF2IMAGE_ARG}
ARGS --chip ${CONFIG_SOC} elf2image ${ELF2IMAGE_ARG}
--flash_mode dio --flash_freq 40m
--flash_size ${esptoolpy_flashsize}MB
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf)
endif()
endif()
## When building for APPCPU
if (CONFIG_SOC_ESP32_APPCPU)
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source)
if(CONFIG_BUILD_OUTPUT_BIN)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/esp_bin2c_array.py
ARGS -i ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin
-o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.c
-a "esp32_appcpu_fw_array")
endif()
else()
set_property(TARGET bintools PROPERTY disassembly_flag_inline_source)
# get code-partition boot address
# Select the image origin depending on the boot configuration
if(CONFIG_SOC_ESP32_APPCPU)
dt_nodelabel(dts_partition_path NODELABEL "slot0_appcpu_partition")
elseif(CONFIG_MCUBOOT)
dt_nodelabel(dts_partition_path NODELABEL "boot_partition")
dt_reg_addr(boot_off PATH ${dts_partition_path})
# get code-partition slot0 address
elseif(CONFIG_ESP_SIMPLE_BOOT)
dt_nodelabel(dts_partition_path NODELABEL "boot_partition")
else()
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()
board_finalize_runner_args(esp32 "--esp-app-address=${boot_off}")
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)
# search from cross references between bootloader sections
message("check_callgraph using: ${ESP_IDF_PATH}/tools/ci/check_callgraph.py")
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
COMMAND
${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/ci/check_callgraph.py
ARGS
--rtl-dirs ${CMAKE_BINARY_DIR}/zephyr
--elf-file ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf
find-refs --from-section=.iram0.iram_loader --to-section=.iram0.text
--elf-file ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf
find-refs
--from-section='.iram0.loader_text'
--to-section='.iram0.text'
--exit-code)
endif()

View file

@ -15,27 +15,6 @@ config SOC_SERIES_ESP32
if SOC_SERIES_ESP32
config ESP32_APPCPU_IRAM
hex "ESP32 APPCPU IRAM size"
depends on SOC_ESP32_PROCPU || SOC_ESP32_APPCPU
default 0x20000
help
Defines APPCPU IRAM area in bytes.
config ESP32_APPCPU_DRAM
hex "ESP32 APPCPU DRAM size"
depends on SOC_ESP32_PROCPU || SOC_ESP32_APPCPU
default 0x10000
help
Defines APPCPU DRAM area in bytes.
config SOC_ENABLE_APPCPU
bool
default y
depends on (IPM || MBOX) && SOC_ESP32_PROCPU
help
This hidden configuration lets PROCPU core to map and start APPCPU whenever IPM is enabled.
config ESP32_BT_RESERVE_DRAM
hex "Bluetooth controller reserved RAM region"
default 0xdb5c if BT

View file

@ -9,6 +9,9 @@ config FLASH_SIZE
config FLASH_BASE_ADDRESS
default $(dt_node_reg_addr_hex,/soc/flash-controller@3ff42000/flash@0)
config BOOTLOADER_MCUBOOT
default y if SOC_ESP32_APPCPU
if SMP
config SCHED_IPI_SUPPORTED

View file

@ -12,19 +12,15 @@
#include "memory.h"
/* The "user_iram_end" represents the last DRAM memory location
* that is occupied by the ROM code. Since the "iram_loader_seg"
* - which is the last memory the bootloader runs from - resides
* in the SRAM0 "cache" memory, the "user_iram_end" applies for\
* all build cases - Simple boot and the MCUboot application.
*/
user_iram_end = SRAM1_DRAM_IRAM_CALC(SRAM1_DRAM_USER_START);
/* User available SRAM memory segments */
user_iram_seg_org = (SRAM0_IRAM_START + SRAM0_CACHE_SIZE);
user_iram_seg_len = user_iram_end - user_iram_seg_org;
user_dram_seg_org = SRAM2_DRAM_USER_START;
user_dram_seg_len = SRAM2_DRAM_USER_SIZE;
procpu_iram_end = USER_IRAM_END - APPCPU_SRAM_SIZE;
procpu_iram_org = SRAM0_IRAM_START + SRAM0_CACHE_SIZE;
procpu_iram_len = procpu_iram_end - procpu_iram_org;
procpu_dram_end = SRAM2_DRAM_END;
procpu_dram_org = SRAM2_DRAM_USER_START + CONFIG_ESP32_BT_RESERVE_DRAM;
procpu_dram_len = SRAM2_DRAM_USER_SIZE - CONFIG_ESP32_BT_RESERVE_DRAM;
user_dram_2_seg_org = SRAM1_DRAM_USER_START;
user_dram_2_seg_len = SRAM1_USER_SIZE;
@ -36,12 +32,6 @@ user_dram_2_seg_len = SRAM1_USER_SIZE;
#define RAMABLE_REGION dram0_0_seg
#define ROMABLE_REGION FLASH
#ifndef CONFIG_SOC_ESP32_PROCPU
#define RAMABLE_REGION_1 dram0_1_seg
#else
#define RAMABLE_REGION_1 dram0_0_seg
#endif
#undef GROUP_DATA_LINK_IN
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion
@ -72,26 +62,8 @@ MEMORY
FLASH (R): org = 0x0, len = FLASH_SIZE - 0x100
#endif /* CONFIG_BOOTLOADER_MCUBOOT */
#ifndef CONFIG_SOC_ESP32_APPCPU
iram0_0_seg(RX): org = user_iram_seg_org, len = user_iram_seg_len
#else
iram0_0_seg(RX): org = user_iram_seg_org, len = 0x8000
#endif /* CONFIG_SOC_ESP32_APPCPU */
dram0_0_seg(RW): org = user_dram_seg_org + CONFIG_ESP32_BT_RESERVE_DRAM,
len = user_dram_seg_len - CONFIG_ESP32_BT_RESERVE_DRAM
#ifdef CONFIG_SOC_ESP32_PROCPU
/* shared RAM reserved for IPM */
dram0_shm0_seg(RW): org = 0x3ffe5230, len = 2K
/* shared data reserved for IPM data header */
dram0_sem0_seg(RW): org = 0x3ffe5a30, len = 8
/* for AMP builds dram0_1 is reserved for network core */
dram0_1_seg(RW): org = 0x3ffe5a38, len = 0K
#else
/* skip data for APP CPU initialization usage */
dram0_1_seg(RW): org = user_dram_2_seg_org, len = user_dram_2_seg_len
#endif /* CONFIG_SOC_ESP32_PROCPU */
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
@ -219,7 +191,6 @@ SECTIONS
.iram0.vectors : ALIGN(4)
{
_iram_start = ABSOLUTE(.);
/* Vectors go to IRAM */
_init_start = ABSOLUTE(.);
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
@ -253,6 +224,7 @@ SECTIONS
*(.init.literal)
*(.init)
_init_end = ABSOLUTE(.);
_iram_start = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
.iram0.text : ALIGN(4)
@ -712,12 +684,12 @@ SECTIONS
*(.noinit)
*(.noinit.*)
. = ALIGN (8);
} GROUP_LINK_IN(RAMABLE_REGION_1)
} GROUP_LINK_IN(RAMABLE_REGION)
/* Provide total SRAM usage, including IRAM and DRAM */
_image_ram_start = _dram_data_start;
#include <zephyr/linker/ram-end.ld>
_image_ram_size += _iram_end - _iram_start;
_image_ram_size += _iram_end - _init_start;
ASSERT(((_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM data does not fit.")

View file

@ -1,42 +1,63 @@
/*
* Copyright (c) 2016 Cadence Design Systems, Inc.
* Copyright (c) 2017 Intel Corporation
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Linker command/script file
*
* Linker script for the Xtensa platform.
*/
#include <zephyr/devicetree.h>
#include <zephyr/linker/sections.h>
#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>
#define RAMABLE_REGION dram0_1_seg
#define RAMABLE_REGION_1 dram0_1_seg
#define RODATA_REGION dram0_1_seg
#define IRAM_REGION iram0_0_seg
#define FLASH_CODE_REGION iram0_0_seg
#define ROMABLE_REGION iram0_0_seg
#define ROMABLE_DATA_REGION dram0_1_seg
#define dram0_0_seg dram0_1_seg
#if !defined(CONFIG_BOOTLOADER_MCUBOOT)
#error "APPCPU image must use MCUboot image format."
#endif /* CONFIG_BOOTLOADER_MCUBOOT */
/* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA.
#include "memory.h"
/* User available SRAM memory segments */
appcpu_iram_end = USER_IRAM_END - APPCPU_DRAM_SIZE;
appcpu_iram_org = appcpu_iram_end - APPCPU_IRAM_SIZE;
appcpu_iram_len = APPCPU_IRAM_SIZE;
appcpu_dram_org = SRAM1_DRAM_USER_START;
appcpu_dram_len = APPCPU_DRAM_SIZE;
/* Aliases */
#define ROMABLE_REGION FLASH
#define RODATA_REGION dram0_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
{
iram0_0_seg(RX): org = 0x40080000 + 0x08000, len = 0x18000
dram0_shm0_seg(RW): org = 0x3FFE5230, len = 16K /* shared RAM reserved for IPM */
dram0_sem0_seg(RW): org = 0x3FFED238, len = 8 /*shared data reserved for IPM data header */
dram0_1_seg(RW): org = 0x3FFE9238 + CONFIG_ESP32_BT_RESERVE_DRAM, len = 0x17CB0 - 0xEE0 - CONFIG_ESP32_BT_RESERVE_DRAM
mcuboot_hdr (R): org = 0x0, len = 0x20
metadata (R): org = 0x20, len = 0x20
FLASH (R): org = 0x40, len = FLASH_SIZE - 0x40
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
IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000
#endif
@ -44,26 +65,60 @@ MEMORY
/* Default entry point: */
PROVIDE ( _ResetVector = 0x40000400 );
ENTRY(__app_cpu_start)
ENTRY(__appcpu_start)
_rom_store_table = 0;
PROVIDE(_memmap_vecbase_reset = 0x40000450);
PROVIDE(_memmap_reset_vector = 0x40000400);
_heap_sentry = 0x3ffe3f20;
_heap_sentry = BOOTLOADER_DRAM_SEG_START + APPCPU_DRAM_SIZE;
SECTIONS
{
#include <zephyr/linker/rel-sections.ld>
/* 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
#include <zephyr/linker/rel-sections.ld>
#ifdef CONFIG_LLEXT
#include <zephyr/linker/llext-sections.ld>
#include <zephyr/linker/llext-sections.ld>
#endif
_image_iram_start = LOADADDR(.iram0.vectors);
_image_iram_size = LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - _image_iram_start;
_image_iram_vaddr = ADDR(.iram0.vectors);
/* --- START OF IRAM --- */
/* Send .iram0 code to iram */
.iram0.vectors : ALIGN(4)
@ -102,12 +157,10 @@ SECTIONS
*(.init)
_init_end = ABSOLUTE(.);
/* This goes here, not at top of linker script, so addr2line finds it last,
and uses it in preference to the first symbol in IRAM */
_iram_start = ABSOLUTE(0);
_iram_start = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4))
.iram0.text : ALIGN(4)
{
/* Code marked as running out of IRAM */
_iram_text_start = ABSOLUTE(.);
@ -150,25 +203,136 @@ SECTIONS
*libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*)
*libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*)
. = ALIGN(16);
_iram_text_end = ABSOLUTE(.);
. = ALIGN(4);
_iram_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
_image_drom_start = LOADADDR(_RODATA_SECTION_NAME);
_image_drom_size = LOADADDR(_RODATA_SECTION_END) + SIZEOF(_RODATA_SECTION_END) - _image_drom_start;
_image_drom_vaddr = ADDR(_RODATA_SECTION_NAME);
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
.flash.text : ALIGN(16)
{
__rodata_region_start = ABSOLUTE(.);
_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);
_iram_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
/* --- END OF IRAM --- */
/* --- START OF DRAM --- */
.dram0.data :
{
. = ALIGN(16);
__data_start = ABSOLUTE(.);
_data_start = ABSOLUTE(.);
_btdm_data_start = ABSOLUTE(.);
*libbtdm_app.a:(.data .data.*)
. = ALIGN (4);
_btdm_data_end = 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:log_core.*(.rodata .rodata.*)
*libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
*libzephyr.a:log_output.*(.rodata .rodata.*)
*libzephyr.a:loader.*(.rodata .rodata.*)
*libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
*libzephyr.a:spi_flash_rom_patch.*(.rodata .rodata.*)
*libdrivers__serial.a:uart_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>
.dram0.rodata : ALIGN(4)
{
_rodata_start = ABSOLUTE(.);
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
__rodata_region_start = ABSOLUTE(.);
. = ALIGN(16);
#include <snippets-rodata.ld>
. = 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.* *libdrivers__flash.a:esp32_mp.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__flash.a:flash_esp32.* *libdrivers__serial.a:uart_esp32.* *libzephyr.a:spi_flash_rom_patch.*) .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.* *libdrivers__flash.a:esp32_mp.* *libzephyr.a:log_output.* *libzephyr.a:loader.* *libdrivers__flash.a:flash_esp32.* *libdrivers__serial.a:uart_esp32.* *libzephyr.a:spi_flash_rom_patch.*) .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)
*(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.*)
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
@ -209,8 +373,9 @@ SECTIONS
*(.rodata_wlog*)
_thread_local_end = ABSOLUTE(.);
. = ALIGN(4);
} GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_DATA_REGION)
} GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION)
#include <zephyr/linker/cplusplus-rom.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-ztest.ld>
@ -218,84 +383,33 @@ SECTIONS
#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-misc.ld>
#include <zephyr/linker/thread-local-storage.ld>
#include <snippets-sections.ld>
/* 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 */
SECTION_PROLOGUE(_RODATA_SECTION_END,,)
.dram0.rodata_end : ALIGN(16)
{
. = ALIGN(4);
_image_rodata_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION)
_image_dram_start = LOADADDR(.dram0.data);
_image_dram_size = LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - _image_dram_start;
_image_dram_vaddr = ADDR(.dram0.data);
.dram0.data :
{
__data_start = ABSOLUTE(.);
_btdm_data_start = ABSOLUTE(.);
*libbtdm_app.a:(.data .data.*)
. = ALIGN (4);
_btdm_data_end = 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:log_core.*(.rodata .rodata.*)
*libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
*libzephyr.a:log_output.*(.rodata .rodata.*)
*libzephyr.a:loader.*(.rodata .rodata.*)
*libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
*libzephyr.a:spi_flash_rom_patch.*(.rodata .rodata.*)
*libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*)
KEEP(*(.jcr))
*(.dram1 .dram1.*)
. = ALIGN(4);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_DATA_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 :
{
. = ALIGN(4);
#include <snippets-rwdata.ld>
. = ALIGN(4);
__data_end = ABSOLUTE(.);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_DATA_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 */
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.); /* required by bluetooth library */
@ -306,9 +420,6 @@ SECTIONS
. = ALIGN (4);
_btdm_bss_end = ABSOLUTE(.);
/* Buffer for system heap should be placed in dram0_0_seg */
*libkernel.a:mempool.*(.noinit.kheap_buf__system_heap .noinit.*.kheap_buf__system_heap)
*(.dynsbss)
*(.sbss)
*(.sbss.*)
@ -330,40 +441,16 @@ SECTIONS
/* Provide total SRAM usage, including IRAM and DRAM */
_image_ram_start = __rodata_region_start;
#include <zephyr/linker/ram-end.ld>
_image_ram_size += _iram_end - _iram_start;
_image_ram_size += _iram_end - _init_start;
ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
ASSERT(((__bss_end - ORIGIN(dram0_1_seg)) <= LENGTH(dram0_1_seg)),
"DRAM segment data does not fit.")
SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),)
{
. = ALIGN (8);
*(.noinit)
*(.noinit.*)
. = ALIGN (8);
} GROUP_LINK_IN(RAMABLE_REGION_1)
_image_irom_start = LOADADDR(.flash.text);
_image_irom_size = LOADADDR(.flash.text) + SIZEOF(.flash.text) - _image_irom_start;
_image_irom_vaddr = ADDR(.flash.text);
.flash.text : ALIGN(4)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.*)
. = ALIGN(4);
_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.
*/
_flash_cache_start = ABSOLUTE(0);
} GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION)
/* --- END OF DRAM --- */
#ifdef CONFIG_GEN_ISR_TABLES
#include <zephyr/linker/intlist.ld>
#endif
#include <zephyr/linker/debug-sections.ld>
@ -400,12 +487,7 @@ SECTIONS
KEEP (*(.xt.profile_files))
KEEP (*(.gnu.linkonce.xt.profile_files.*))
}
#ifdef CONFIG_GEN_ISR_TABLES
#include <zephyr/linker/intlist.ld>
#endif
}
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.")

View file

@ -1,35 +1,32 @@
/*
* Copyright (c) 2018 Intel Corporation
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Include esp-idf headers first to avoid redefining BIT() macro */
#include <soc/dport_reg.h>
#include <soc/gpio_periph.h>
#include <soc/rtc_periph.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
#include <soc.h>
#include <ksched.h>
#include <ipi.h>
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/spinlock.h>
#include <zephyr/kernel_structs.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/drivers/interrupt_controller/intc_esp32.h>
#define Z_REG(base, off) (*(volatile uint32_t *)((base) + (off)))
#include <soc.h>
#include <esp_cpu.h>
#include "esp_rom_uart.h"
#define RTC_CNTL_BASE 0x3ff48000
#define RTC_CNTL_OPTIONS0 Z_REG(RTC_CNTL_BASE, 0x0)
#define RTC_CNTL_SW_CPU_STALL Z_REG(RTC_CNTL_BASE, 0xac)
#define DPORT_BASE 0x3ff00000
#define DPORT_APPCPU_CTRL_A Z_REG(DPORT_BASE, 0x02C)
#define DPORT_APPCPU_CTRL_B Z_REG(DPORT_BASE, 0x030)
#define DPORT_APPCPU_CTRL_C Z_REG(DPORT_BASE, 0x034)
#include "esp_mcuboot_image.h"
#include "esp_memory_utils.h"
#ifdef CONFIG_SMP
#include <ipi.h>
#ifndef CONFIG_SOC_ESP32_PROCPU
static struct k_spinlock loglock;
#endif
struct cpustart_rec {
int cpu;
arch_cpustart_t fn;
@ -44,7 +41,6 @@ static void *appcpu_top;
static bool cpus_active[CONFIG_MP_MAX_NUM_CPUS];
static struct k_spinlock loglock;
/* Note that the logging done here is ACTUALLY REQUIRED FOR RELIABLE
* OPERATION! At least one particular board will experience spurious
* hangs during initialization (usually the APPCPU fails to start at
@ -165,7 +161,6 @@ static void appcpu_entry1(void)
{
z_appcpu_stack_switch(appcpu_top, appcpu_entry2);
}
#endif
/* The calls and sequencing here were extracted from the ESP-32
* FreeRTOS integration with just a tiny bit of cleanup. None of the
@ -223,7 +218,6 @@ void esp_appcpu_start(void *entry_point)
ets_printf("ESP32: APPCPU start sequence complete");
}
#ifdef CONFIG_SMP
IRAM_ATTR static void esp_crosscore_isr(void *arg)
{
ARG_UNUSED(arg);
@ -314,3 +308,154 @@ IRAM_ATTR bool arch_cpu_active(int cpu_num)
return cpus_active[cpu_num];
}
#endif /* CONFIG_SMP */
void esp_appcpu_start2(void *entry_point)
{
esp_cpu_unstall(1);
if (!DPORT_GET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN)) {
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
}
esp_rom_ets_set_appcpu_boot_addr((void *)entry_point);
esp_cpu_reset(1);
}
/* AMP support */
#ifdef CONFIG_SOC_ENABLE_APPCPU
#include "bootloader_flash_priv.h"
#define sys_mmap bootloader_mmap
#define sys_munmap bootloader_munmap
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);
if (entry_addr == NULL) {
ets_printf("Can't return the entry address. Aborting!\n");
abort();
return -1;
}
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("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);
} 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\n", image_header.entry_addr);
esp_rom_uart_tx_wait_idle(0);
assert(entry_addr != NULL);
*entry_addr = image_header.entry_addr;
return 0;
}
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_start2((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

@ -10,13 +10,13 @@
#define SRAM0_SIZE DT_REG_SIZE(DT_NODELABEL(sram0))
/* SRAM1 (128kB) instruction/data memory */
#define SRAM1_IRAM_START (SRAM0_IRAM_START + SRAM0_SIZE)
#define SRAM1_DRAM_START DT_REG_ADDR(DT_NODELABEL(sram1))
#define SRAM1_SIZE DT_REG_SIZE(DT_NODELABEL(sram1))
#define SRAM1_DRAM_END (SRAM1_DRAM_START + SRAM1_SIZE)
#define SRAM1_DRAM_PROAPP_PRIV_SIZE 0x8000
#define SRAM1_DRAM_USER_START (SRAM1_DRAM_START + SRAM1_DRAM_PROAPP_PRIV_SIZE)
#define SRAM1_USER_SIZE (0x40000000 - SRAM1_DRAM_USER_START)
#define SRAM1_IRAM_START (SRAM0_IRAM_START + SRAM0_SIZE)
#define SRAM1_DRAM_START DT_REG_ADDR(DT_NODELABEL(sram1))
#define SRAM1_SIZE DT_REG_SIZE(DT_NODELABEL(sram1))
#define SRAM1_DRAM_END (SRAM1_DRAM_START + SRAM1_SIZE)
#define SRAM1_RESERVED_SIZE 0x8000
#define SRAM1_DRAM_USER_START (SRAM1_DRAM_START + SRAM1_RESERVED_SIZE)
#define SRAM1_USER_SIZE (0x40000000 - SRAM1_DRAM_USER_START)
/* SRAM2 (200kB) data memory */
#define SRAM2_DRAM_START DT_REG_ADDR(DT_NODELABEL(sram2))
@ -43,13 +43,15 @@
#define DRAM1_BT_SHM_BUFFERS_START 0x3ffe4350
#define DRAM1_BT_SHM_BUFFERS_END 0x3ffe5230
/* Convert IRAM address to its DRAM counterpart in SRAM1 memory */
#define SRAM1_IRAM_DRAM_CALC(addr_iram) ((addr_iram > SRAM1_IRAM_START) ? \
(SRAM1_SIZE - (addr_iram - SRAM1_IRAM_START) + SRAM1_DRAM_START) : (SRAM1_DRAM_END))
/* The address is a limit set manually for AMP build */
#define DRAM1_AMP_SHM_BUFFERS_END 0x3ffe9800
/* Convert IRAM address to its DRAM counterpart in SRAM1 memory */
#define SRAM1_IRAM_DRAM_CALC(addr_iram) (SRAM1_SIZE - (addr_iram - SRAM1_IRAM_START) + \
SRAM1_DRAM_START)
/* Convert DRAM address to its IRAM counterpart in SRAM1 memory */
#define SRAM1_DRAM_IRAM_CALC(addr_dram) \
(SRAM1_SIZE - (addr_dram - SRAM1_DRAM_START) + SRAM1_IRAM_START)
#define SRAM1_DRAM_IRAM_CALC(addr_dram) (SRAM1_SIZE - (addr_dram - SRAM1_DRAM_START) + \
SRAM1_IRAM_START)
/* Set bootloader segments size */
#define BOOTLOADER_DRAM_SEG_LEN 0x7a00
@ -62,6 +64,29 @@
#define BOOTLOADER_IRAM_LOADER_SEG_START 0x40078000
#define BOOTLOADER_IRAM_SEG_START 0x400a0000
/* The `USER_IRAM_END` represents the end of staticaly allocated memory.
* This address is where 2nd stage bootloader starts allocating memory.
* The `iram_loader_seg` which is the last memory the bootloader runs from
* resides in the SRAM0 'cache' area, the `user_iram_end` applies for
* all build cases - Simple boot and the MCUboot application.
*/
#if defined(CONFIG_SOC_ENABLE_APPCPU) || defined(CONFIG_SOC_ESP32_APPCPU)
#define USER_IRAM_END SRAM1_DRAM_IRAM_CALC(DRAM1_AMP_SHM_BUFFERS_END)
#else
#define USER_IRAM_END SRAM1_DRAM_IRAM_CALC(SRAM1_DRAM_USER_START)
#endif
/* AMP memory */
#if defined(CONFIG_SOC_ENABLE_APPCPU) || defined(CONFIG_SOC_ESP32_APPCPU)
#define APPCPU_IRAM_SIZE CONFIG_ESP_APPCPU_IRAM_SIZE
#define APPCPU_DRAM_SIZE CONFIG_ESP_APPCPU_DRAM_SIZE
#else
#define APPCPU_IRAM_SIZE 0
#define APPCPU_DRAM_SIZE 0
#endif
#define APPCPU_SRAM_SIZE (APPCPU_IRAM_SIZE + APPCPU_DRAM_SIZE)
/* Flash */
#ifdef CONFIG_FLASH_SIZE
#define FLASH_SIZE CONFIG_FLASH_SIZE
@ -75,10 +100,3 @@
#define IROM_SEG_LEN (FLASH_SIZE - 0x1000)
#define DROM_SEG_ORG 0x3f400000
#define DROM_SEG_LEN (FLASH_SIZE - 0x1000)
/* AMP: TODO utilise memory for APPCPU */
#ifndef CONFIG_SOC_ESP32_PROCPU
#define APPCPU_IRAM_SIZE 0x20000
#else
#define APPCPU_IRAM_SIZE 0x8000
#endif

View file

@ -47,45 +47,7 @@
extern void z_prep_c(void);
extern void esp_reset_reason_init(void);
#ifdef CONFIG_SOC_ENABLE_APPCPU
extern const unsigned char esp32_appcpu_fw_array[];
void IRAM_ATTR esp_start_appcpu(void)
{
esp_image_header_t *header = (esp_image_header_t *)&esp32_appcpu_fw_array[0];
esp_image_segment_header_t *segment =
(esp_image_segment_header_t *)&esp32_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 *)&esp32_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 j = 0; j < segment->data_len / 4; j++) {
dst[j] = src[j];
}
} 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 *)&esp32_appcpu_fw_array[idx];
idx += sizeof(esp_image_segment_header_t);
}
esp_appcpu_start((void *)entry_addr);
}
#endif /* CONFIG_SOC_ENABLE_APPCPU */
extern int esp_appcpu_init(void);
/*
* This is written in C rather than assembly since, during the port bring up,
@ -97,24 +59,14 @@ void IRAM_ATTR __esp_platform_start(void)
extern uint32_t _init_start;
/* Move the exception vector table to IRAM. */
__asm__ __volatile__ (
"wsr %0, vecbase"
:
: "r"(&_init_start));
__asm__ __volatile__ ("wsr %0, vecbase" : : "r"(&_init_start));
z_bss_zero();
__asm__ __volatile__ (
""
:
: "g"(&__bss_start)
: "memory");
__asm__ __volatile__ ("" : : "g"(&__bss_start) : "memory");
/* Disable normal interrupts. */
__asm__ __volatile__ (
"wsr %0, PS"
:
: "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
__asm__ __volatile__ ("wsr %0, PS" : : "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
/* Initialize the architecture CPU pointer. Some of the
* initialization code wants a valid arch_current_thread() before
@ -137,11 +89,6 @@ void IRAM_ATTR __esp_platform_start(void)
esp_timer_early_init();
#if CONFIG_SOC_ENABLE_APPCPU
/* start the ESP32 APP CPU */
esp_start_appcpu();
#endif
esp_mspi_pin_init();
esp_flash_app_init();
@ -185,3 +132,8 @@ void sys_arch_reboot(int type)
{
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, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#endif

View file

@ -33,14 +33,28 @@
#include <esp_app_format.h>
#include <zephyr/sys/printk.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);
static void core_intr_matrix_clear(void)
{
uint32_t core_id = esp_cpu_get_core_id();
for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
intr_matrix_set(core_id, i, ETS_INVALID_INUM);
}
}
/*
* This is written in C rather than assembly since, during the port bring up,
* Zephyr is being booted by the Espressif bootloader. With it, the C stack
* is already set up.
*/
void __app_cpu_start(void)
void IRAM_ATTR __appcpu_start(void)
{
extern uint32_t _init_start;
@ -69,9 +83,12 @@ void __app_cpu_start(void)
* initialization code wants a valid arch_current_thread() before
* z_prep_c() is invoked.
*/
__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[1]));
core_intr_matrix_clear();
esp_intr_initialize();
/* Start Zephyr */
z_prep_c();