From 322ab2a86e9ca86a1a2380be81218ba4574c91d4 Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Tue, 19 Nov 2024 15:35:41 +0000 Subject: [PATCH] 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 --- soc/espressif/common/Kconfig | 1 + soc/espressif/common/Kconfig.amp | 26 ++ soc/espressif/common/loader.c | 3 +- soc/espressif/esp32/CMakeLists.txt | 72 ++--- soc/espressif/esp32/Kconfig | 21 -- soc/espressif/esp32/Kconfig.defconfig | 3 + soc/espressif/esp32/default.ld | 54 +--- soc/espressif/esp32/default_appcpu.ld | 372 ++++++++++++++++---------- soc/espressif/esp32/esp32-mp.c | 187 +++++++++++-- soc/espressif/esp32/memory.h | 56 ++-- soc/espressif/esp32/soc.c | 66 +---- soc/espressif/esp32/soc_appcpu.c | 21 +- 12 files changed, 541 insertions(+), 341 deletions(-) create mode 100644 soc/espressif/common/Kconfig.amp diff --git a/soc/espressif/common/Kconfig b/soc/espressif/common/Kconfig index ffeac4ab045..e33aa2e0f38 100644 --- a/soc/espressif/common/Kconfig +++ b/soc/espressif/common/Kconfig @@ -58,6 +58,7 @@ config ESP32_PHY_MAX_TX_POWER endif +rsource "Kconfig.amp" rsource "Kconfig.spiram" rsource "Kconfig.esptool" rsource "Kconfig.flash" diff --git a/soc/espressif/common/Kconfig.amp b/soc/espressif/common/Kconfig.amp new file mode 100644 index 00000000000..236f48c3ad6 --- /dev/null +++ b/soc/espressif/common/Kconfig.amp @@ -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 diff --git a/soc/espressif/common/loader.c b/soc/espressif/common/loader.c index cf66bfd356f..792eb959608 100644 --- a/soc/espressif/common/loader.c +++ b/soc/espressif/common/loader.c @@ -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 diff --git a/soc/espressif/esp32/CMakeLists.txt b/soc/espressif/esp32/CMakeLists.txt index eb4ba71f56d..5ccc92b682a 100644 --- a/soc/espressif/esp32/CMakeLists.txt +++ b/soc/espressif/esp32/CMakeLists.txt @@ -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() diff --git a/soc/espressif/esp32/Kconfig b/soc/espressif/esp32/Kconfig index 9aeaada682e..17d67408c09 100644 --- a/soc/espressif/esp32/Kconfig +++ b/soc/espressif/esp32/Kconfig @@ -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 diff --git a/soc/espressif/esp32/Kconfig.defconfig b/soc/espressif/esp32/Kconfig.defconfig index 74f7949e714..c2217013826 100644 --- a/soc/espressif/esp32/Kconfig.defconfig +++ b/soc/espressif/esp32/Kconfig.defconfig @@ -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 diff --git a/soc/espressif/esp32/default.ld b/soc/espressif/esp32/default.ld index 82aaa3699e3..d084228f1aa 100644 --- a/soc/espressif/esp32/default.ld +++ b/soc/espressif/esp32/default.ld @@ -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 - _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.") diff --git a/soc/espressif/esp32/default_appcpu.ld b/soc/espressif/esp32/default_appcpu.ld index 145f23e6d71..4761120afa6 100644 --- a/soc/espressif/esp32/default_appcpu.ld +++ b/soc/espressif/esp32/default_appcpu.ld @@ -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 #include #include #include -#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 + /* 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 #ifdef CONFIG_LLEXT -#include + #include #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 + . = ALIGN(4); + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(16); + + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + + .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 . = 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 #include #include #include @@ -218,84 +383,33 @@ SECTIONS #include #include #include + #include #include /* 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 - #include - #include - #include - #include - - /* 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 - #pragma pop_macro("GROUP_ROM_LINK_IN") - .dram0.end : { - . = ALIGN(4); - - #include - - . = 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 - _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 +#endif #include @@ -400,12 +487,7 @@ SECTIONS KEEP (*(.xt.profile_files)) KEEP (*(.gnu.linkonce.xt.profile_files.*)) } - -#ifdef CONFIG_GEN_ISR_TABLES -#include -#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.") diff --git a/soc/espressif/esp32/esp32-mp.c b/soc/espressif/esp32/esp32-mp.c index 7b32734cfc3..71a6b8d7616 100644 --- a/soc/espressif/esp32/esp32-mp.c +++ b/soc/espressif/esp32/esp32-mp.c @@ -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 -#include -#include - -#include -#include -#include -#include #include #include #include #include +#include +#include -#define Z_REG(base, off) (*(volatile uint32_t *)((base) + (off))) +#include +#include +#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 + +#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 */ diff --git a/soc/espressif/esp32/memory.h b/soc/espressif/esp32/memory.h index da7d9bbf278..67da219f2d1 100644 --- a/soc/espressif/esp32/memory.h +++ b/soc/espressif/esp32/memory.h @@ -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 diff --git a/soc/espressif/esp32/soc.c b/soc/espressif/esp32/soc.c index f6f21eddffb..d244ff5c84c 100644 --- a/soc/espressif/esp32/soc.c +++ b/soc/espressif/esp32/soc.c @@ -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 diff --git a/soc/espressif/esp32/soc_appcpu.c b/soc/espressif/esp32/soc_appcpu.c index 74d80760624..e942bab01a2 100644 --- a/soc/espressif/esp32/soc_appcpu.c +++ b/soc/espressif/esp32/soc_appcpu.c @@ -33,14 +33,28 @@ #include #include +#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();