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:
parent
5d0dc14c82
commit
322ab2a86e
12 changed files with 541 additions and 341 deletions
|
@ -58,6 +58,7 @@ config ESP32_PHY_MAX_TX_POWER
|
|||
|
||||
endif
|
||||
|
||||
rsource "Kconfig.amp"
|
||||
rsource "Kconfig.spiram"
|
||||
rsource "Kconfig.esptool"
|
||||
rsource "Kconfig.flash"
|
||||
|
|
26
soc/espressif/common/Kconfig.amp
Normal file
26
soc/espressif/common/Kconfig.amp
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue