From 4796746b5e01cc4b2c573b3cd13191069edd4b76 Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Tue, 9 May 2023 11:10:05 +0200 Subject: [PATCH] soc: esp32: MCUboot support This make MCUboot build as Zephyr application. Providing optinal 2nd stage bootloader to the IDF bootloader, which is used by default. This provides more flexibility when building and loading multiple images and aims to brings better DX to users by using the sysbuild. MCUboot and applications has now separate linker scripts. Signed-off-by: Marek Matej --- Kconfig.zephyr | 4 +- arch/riscv/core/isr.S | 2 + arch/xtensa/core/xtensa-asm2.c | 4 + boards/riscv/esp32c3_devkitm/Kconfig.board | 1 - boards/riscv/esp32c3_devkitm/Kconfig.sysbuild | 10 + boards/riscv/icev_wireless/Kconfig.sysbuild | 10 + boards/riscv/stamp_c3/Kconfig.sysbuild | 10 + boards/riscv/xiao_esp32c3/Kconfig.sysbuild | 10 + boards/xtensa/esp32/Kconfig.sysbuild | 10 + .../esp32_ethernet_kit/Kconfig.sysbuild | 10 + .../esp32s2_franzininho/Kconfig.sysbuild | 10 + .../esp32s2_franzininho_defconfig | 2 - boards/xtensa/esp32s2_saola/Kconfig.sysbuild | 10 + .../esp32s2_saola/esp32s2_saola_defconfig | 2 - .../xtensa/esp32s3_devkitm/Kconfig.sysbuild | 10 + boards/xtensa/esp_wrover_kit/Kconfig.sysbuild | 10 + .../heltec_wifi_lora32_v2/Kconfig.sysbuild | 10 + boards/xtensa/m5stickc_plus/Kconfig.sysbuild | 10 + boards/xtensa/odroid_go/Kconfig.sysbuild | 10 + .../xtensa/olimex_esp32_evb/Kconfig.sysbuild | 10 + drivers/flash/flash_esp32.c | 11 + soc/riscv/esp32c3/CMakeLists.txt | 24 +- soc/riscv/esp32c3/Kconfig.soc | 2 +- soc/riscv/esp32c3/default.ld | 509 ++++++++++++++ soc/riscv/esp32c3/linker.ld | 503 +------------ soc/riscv/esp32c3/loader.c | 13 +- soc/riscv/esp32c3/mcuboot.ld | 339 +++++++++ soc/riscv/esp32c3/soc.c | 24 +- soc/xtensa/esp32/CMakeLists.txt | 24 +- soc/xtensa/esp32/Kconfig.soc | 3 +- soc/xtensa/esp32/default.ld | 583 ++++++++++++++++ soc/xtensa/esp32/linker.ld | 577 +-------------- soc/xtensa/esp32/loader.c | 12 + soc/xtensa/esp32/mcuboot.ld | 362 ++++++++++ soc/xtensa/esp32/soc.c | 35 +- soc/xtensa/esp32s2/CMakeLists.txt | 24 +- soc/xtensa/esp32s2/Kconfig.soc | 2 +- soc/xtensa/esp32s2/default.ld | 557 +++++++++++++++ soc/xtensa/esp32s2/linker.ld | 545 +-------------- soc/xtensa/esp32s2/loader.c | 12 +- soc/xtensa/esp32s2/mcuboot.ld | 365 ++++++++++ soc/xtensa/esp32s2/soc.c | 24 +- soc/xtensa/esp32s2/soc_cache.c | 1 - soc/xtensa/esp32s3/CMakeLists.txt | 27 +- soc/xtensa/esp32s3/Kconfig.soc | 2 +- soc/xtensa/esp32s3/default.ld | 648 +++++++++++++++++ soc/xtensa/esp32s3/linker.ld | 660 +----------------- soc/xtensa/esp32s3/loader.c | 76 +- soc/xtensa/esp32s3/mcuboot.ld | 374 ++++++++++ soc/xtensa/esp32s3/soc.c | 117 ++-- soc/xtensa/esp32s3/soc.h | 9 + soc/xtensa/esp32s3/soc_cache.c | 104 +++ 52 files changed, 4306 insertions(+), 2417 deletions(-) create mode 100644 boards/riscv/esp32c3_devkitm/Kconfig.sysbuild create mode 100644 boards/riscv/icev_wireless/Kconfig.sysbuild create mode 100644 boards/riscv/stamp_c3/Kconfig.sysbuild create mode 100644 boards/riscv/xiao_esp32c3/Kconfig.sysbuild create mode 100644 boards/xtensa/esp32/Kconfig.sysbuild create mode 100644 boards/xtensa/esp32_ethernet_kit/Kconfig.sysbuild create mode 100644 boards/xtensa/esp32s2_franzininho/Kconfig.sysbuild create mode 100644 boards/xtensa/esp32s2_saola/Kconfig.sysbuild create mode 100644 boards/xtensa/esp32s3_devkitm/Kconfig.sysbuild create mode 100644 boards/xtensa/esp_wrover_kit/Kconfig.sysbuild create mode 100644 boards/xtensa/heltec_wifi_lora32_v2/Kconfig.sysbuild create mode 100644 boards/xtensa/m5stickc_plus/Kconfig.sysbuild create mode 100644 boards/xtensa/odroid_go/Kconfig.sysbuild create mode 100644 boards/xtensa/olimex_esp32_evb/Kconfig.sysbuild create mode 100644 soc/riscv/esp32c3/default.ld create mode 100644 soc/riscv/esp32c3/mcuboot.ld create mode 100644 soc/xtensa/esp32/default.ld create mode 100644 soc/xtensa/esp32/mcuboot.ld create mode 100644 soc/xtensa/esp32s2/default.ld create mode 100644 soc/xtensa/esp32s2/mcuboot.ld create mode 100644 soc/xtensa/esp32s3/default.ld create mode 100644 soc/xtensa/esp32s3/mcuboot.ld create mode 100644 soc/xtensa/esp32s3/soc_cache.c diff --git a/Kconfig.zephyr b/Kconfig.zephyr index daf4d05c565..05670647bfd 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -816,8 +816,8 @@ config BOOTLOADER_SRAM_SIZE config BOOTLOADER_ESP_IDF bool "ESP-IDF bootloader support" - depends on (SOC_ESP32 || SOC_ESP32S2 || SOC_ESP32C3 || SOC_ESP32S3) && !BOOTLOADER_MCUBOOT - default y + depends on SOC_FAMILY_ESP32 && !BOOTLOADER_MCUBOOT && !MCUBOOT + default y help This option will trigger the compilation of the ESP-IDF bootloader inside the build folder. diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index d50aa82b23e..99acb87840a 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -569,7 +569,9 @@ check_reschedule: addi sp, sp, -16 sr a1, 0(sp) mv a0, zero +#ifdef CONFIG_MULTITHREADING call z_get_next_switch_handle +#endif lr a1, 0(sp) addi sp, sp, 16 beqz a0, no_reschedule diff --git a/arch/xtensa/core/xtensa-asm2.c b/arch/xtensa/core/xtensa-asm2.c index 339158eac9b..2a3c720e87b 100644 --- a/arch/xtensa/core/xtensa-asm2.c +++ b/arch/xtensa/core/xtensa-asm2.c @@ -194,8 +194,12 @@ static ALWAYS_INLINE void usage_stop(void) static inline void *return_to(void *interrupted) { +#ifdef CONFIG_MULTITHREADING return _current_cpu->nested <= 1 ? z_get_next_switch_handle(interrupted) : interrupted; +#else + return interrupted; +#endif /* CONFIG_MULTITHREADING */ } /* The wrapper code lives here instead of in the python script that diff --git a/boards/riscv/esp32c3_devkitm/Kconfig.board b/boards/riscv/esp32c3_devkitm/Kconfig.board index 8f5157be8b9..3a4d97f3523 100644 --- a/boards/riscv/esp32c3_devkitm/Kconfig.board +++ b/boards/riscv/esp32c3_devkitm/Kconfig.board @@ -6,4 +6,3 @@ config BOARD_ESP32C3_DEVKITM bool "ESP32C3 Devkit-M Board" depends on SOC_ESP32C3 - select CONSOLE_HAS_DRIVER diff --git a/boards/riscv/esp32c3_devkitm/Kconfig.sysbuild b/boards/riscv/esp32c3_devkitm/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/riscv/esp32c3_devkitm/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/riscv/icev_wireless/Kconfig.sysbuild b/boards/riscv/icev_wireless/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/riscv/icev_wireless/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/riscv/stamp_c3/Kconfig.sysbuild b/boards/riscv/stamp_c3/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/riscv/stamp_c3/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/riscv/xiao_esp32c3/Kconfig.sysbuild b/boards/riscv/xiao_esp32c3/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/riscv/xiao_esp32c3/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32/Kconfig.sysbuild b/boards/xtensa/esp32/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/esp32/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32_ethernet_kit/Kconfig.sysbuild b/boards/xtensa/esp32_ethernet_kit/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/esp32_ethernet_kit/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32s2_franzininho/Kconfig.sysbuild b/boards/xtensa/esp32s2_franzininho/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/esp32s2_franzininho/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig index 39a1f249529..3a17ce5b547 100644 --- a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig +++ b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig @@ -18,5 +18,3 @@ CONFIG_GEN_ISR_TABLES=y CONFIG_GEN_IRQ_VECTOR_TABLE=n CONFIG_CLOCK_CONTROL=y - -CONFIG_BOOTLOADER_ESP_IDF=y diff --git a/boards/xtensa/esp32s2_saola/Kconfig.sysbuild b/boards/xtensa/esp32s2_saola/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/esp32s2_saola/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig b/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig index 8567404b1c7..f1402eace80 100644 --- a/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig @@ -18,5 +18,3 @@ CONFIG_GEN_ISR_TABLES=y CONFIG_GEN_IRQ_VECTOR_TABLE=n CONFIG_CLOCK_CONTROL=y - -CONFIG_BOOTLOADER_ESP_IDF=y diff --git a/boards/xtensa/esp32s3_devkitm/Kconfig.sysbuild b/boards/xtensa/esp32s3_devkitm/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/esp32s3_devkitm/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp_wrover_kit/Kconfig.sysbuild b/boards/xtensa/esp_wrover_kit/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/esp_wrover_kit/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.sysbuild b/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/m5stickc_plus/Kconfig.sysbuild b/boards/xtensa/m5stickc_plus/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/m5stickc_plus/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/odroid_go/Kconfig.sysbuild b/boards/xtensa/odroid_go/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/odroid_go/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/olimex_esp32_evb/Kconfig.sysbuild b/boards/xtensa/olimex_esp32_evb/Kconfig.sysbuild new file mode 100644 index 00000000000..3a2d17ac5cf --- /dev/null +++ b/boards/xtensa/olimex_esp32_evb/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/drivers/flash/flash_esp32.c b/drivers/flash/flash_esp32.c index 241e662ea99..e2919258294 100644 --- a/drivers/flash/flash_esp32.c +++ b/drivers/flash/flash_esp32.c @@ -62,7 +62,9 @@ struct flash_esp32_dev_config { }; struct flash_esp32_dev_data { +#ifdef CONFIG_MULTITHREADING struct k_sem sem; +#endif }; static const struct flash_parameters flash_esp32_parameters = { @@ -70,6 +72,7 @@ static const struct flash_parameters flash_esp32_parameters = { .erase_value = 0xff, }; +#ifdef CONFIG_MULTITHREADING static inline void flash_esp32_sem_take(const struct device *dev) { struct flash_esp32_dev_data *data = dev->data; @@ -83,6 +86,12 @@ static inline void flash_esp32_sem_give(const struct device *dev) k_sem_give(&data->sem); } +#else + +#define flash_esp32_sem_take(dev) do {} while (0) +#define flash_esp32_sem_give(dev) do {} while (0) + +#endif /* CONFIG_MULTITHREADING */ static int flash_esp32_read(const struct device *dev, off_t address, void *buffer, size_t length) { @@ -150,7 +159,9 @@ static int flash_esp32_init(const struct device *dev) { struct flash_esp32_dev_data *const dev_data = dev->data; +#ifdef CONFIG_MULTITHREADING k_sem_init(&dev_data->sem, 1, 1); +#endif /* CONFIG_MULTITHREADING */ return 0; } diff --git a/soc/riscv/esp32c3/CMakeLists.txt b/soc/riscv/esp32c3/CMakeLists.txt index cd2d715da0f..49c3f57b9e8 100644 --- a/soc/riscv/esp32c3/CMakeLists.txt +++ b/soc/riscv/esp32c3/CMakeLists.txt @@ -62,14 +62,6 @@ if(CONFIG_BOOTLOADER_ESP_IDF) INSTALL_COMMAND "" ) - if(CONFIG_BUILD_OUTPUT_BIN) - set_property(GLOBAL APPEND PROPERTY extra_post_build_commands - COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py - ARGS --chip ${CONFIG_SOC} elf2image --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() - set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) add_dependencies(app EspIdfBootloader EspPartitionTable) @@ -82,6 +74,22 @@ if(CONFIG_BOOTLOADER_ESP_IDF) endif() +if(CONFIG_MCUBOOT OR CONFIG_BOOTLOADER_ESP_IDF) + + if(CONFIG_BUILD_OUTPUT_BIN) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py + ARGS --chip esp32c3 elf2image --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() + + if(CONFIG_MCUBOOT) + board_finalize_runner_args(esp32 "--esp-flash-bootloader=${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin") + endif() + +endif() + board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") diff --git a/soc/riscv/esp32c3/Kconfig.soc b/soc/riscv/esp32c3/Kconfig.soc index 6ffc0fc9a55..63321375841 100644 --- a/soc/riscv/esp32c3/Kconfig.soc +++ b/soc/riscv/esp32c3/Kconfig.soc @@ -8,7 +8,7 @@ config SOC_ESP32C3 select DYNAMIC_INTERRUPTS select CLOCK_CONTROL select PINCTRL - select XIP + select XIP if !MCUBOOT select HAS_ESPRESSIF_HAL select RISCV_ISA_RV32I select RISCV_ISA_EXT_M diff --git a/soc/riscv/esp32c3/default.ld b/soc/riscv/esp32c3/default.ld new file mode 100644 index 00000000000..13d08d39bee --- /dev/null +++ b/soc/riscv/esp32c3/default.ld @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the esp32c3 platform. + */ + +#include +#include +#include +#include + +#define RAMABLE_REGION dram0_0_seg +#define RODATA_REGION drom0_0_seg +#define IRAM_REGION iram0_0_seg +#define FLASH_CODE_REGION irom0_0_seg + +#define ROMABLE_REGION ROM + +#define SRAM_IRAM_START 0x4037C000 +#define SRAM_DRAM_START 0x3FC7C000 +#define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */ +#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START) +#define SRAM_DRAM_END 0x403D0000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */ +#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE) +#define SRAM_DRAM_ORG (SRAM_DRAM_START + ICACHE_SIZE) +#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG + +#ifdef CONFIG_FLASH_SIZE +#define FLASH_SIZE CONFIG_FLASH_SIZE +#else +#define FLASH_SIZE 0x400000 +#endif + +#ifdef CONFIG_BOOTLOADER_ESP_IDF +#define IROM_SEG_ORG 0x42000020 +#define IROM_SEG_LEN (FLASH_SIZE-0x20) +#define IROM_SEG_ALIGN 0x4 +#else +#define IROM_SEG_ORG 0x42000000 +#define IROM_SEG_LEN FLASH_SIZE +#define IROM_SEG_ALIGN 0x10000 +#endif + +/* Global symbols required for espressif hal build */ +MEMORY +{ + mcuboot_hdr (RX): org = 0x0, len = 0x20 + metadata (RX): org = 0x20, len = 0x20 + ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 + + iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE + irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN + + drom0_0_seg (R) : org = 0x3C000040, len = FLASH_SIZE - 0x40 + dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = I_D_SRAM_SIZE + + rtc_iram_seg(RWX): org = 0x50000000, len = 0x2000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + + +/* The line below defines location alias for .rtc.data section + * As C3 only has RTC fast memory, this is not configurable like + * on other targets. + */ +REGION_ALIAS("rtc_slow_seg", rtc_iram_seg); + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +_rom_store_table = 0; + +SECTIONS +{ + /* Reserve space for MCUboot header in the binary */ + .mcuboot_header : + { + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + } > mcuboot_hdr + .metadata : + { + /* Magic byte for load header */ + LONG(0xace637d3) + + /* Application entry point address */ + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * - Destination address (VMA) for IRAM region + * - Flash offset (LMA) for start of IRAM region + * - Size of IRAM region + */ + LONG(ADDR(.iram0.text)) + LONG(LOADADDR(.iram0.text)) + LONG(SIZEOF(.iram0.text)) + + /* DRAM metadata: + * - Destination address (VMA) for DRAM region + * - Flash offset (LMA) for start of DRAM region + * - Size of DRAM region + */ + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(LOADADDR(.dummy.dram.data) + SIZEOF(.dummy.dram.data) - LOADADDR(.dram0.data)) + } > metadata + +#include + _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,,) + { + _rodata_start = ABSOLUTE(.); + + *(.rodata_desc .rodata_desc.*) + *(.rodata_custom_desc .rodata_custom_desc.*) + + __rodata_region_start = .; + + . = ALIGN(4); + #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.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + __rodata_region_end = .; + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.srodata) + *(.srodata.*) + *(.rodata) + *(.rodata.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + _rodata_reserved_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + #include + #include + #include + #include + #include + #include + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + /* 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,,) + { + . = ALIGN(4); + _image_rodata_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + .iram0.text : ALIGN(4) + { + /* Vectors go to IRAM */ + _iram_start = ABSOLUTE(.); + _init_start = ABSOLUTE(.); + + KEEP(*(.exception_vectors.text)); + . = ALIGN(256); + + _invalid_pc_placeholder = ABSOLUTE(.); + + _iram_text_start = ABSOLUTE(.); + + KEEP(*(.exception.entry*)); /* contains _isr_wrapper */ + *(.exception.other*) + . = ALIGN(4); + + *(.entry.text) + *(.init.literal) + *(.init) + . = ALIGN(4); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *libesp32.a:panic.*(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) + *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) + *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) + *libsubsys__net.a:(.literal .text .literal.* .text.*) + *libkernel.a:(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) + *libdrivers__timer.a:esp32c3_sys_timer.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) + *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) + *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) + *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *libzephyr.a:loader.*(.literal .text .literal.* .text.*) + *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) + *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) + *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *libc.a:*(.literal .text .literal.* .text.*) + *libphy.a:( .phyiram .phyiram.*) + *libgcov.a:(.literal .text .literal.* .text.*) + +#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) +#endif + +#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + . = ALIGN(4); + _init_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .dram0.dummy (NOLOAD): + { + /** + * This section is required to skip .iram0.text area because iram0_0_seg and + * dram0_0_seg reflect the same address space on different buses. + */ + . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; + } GROUP_LINK_IN(RAMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + __bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN(4); + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + } GROUP_LINK_IN(RAMABLE_REGION) + + #include + + .dram0.data : + { + . = ALIGN(4); + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) +#ifdef CONFIG_RISCV_GP + __global_pointer$ = . + 0x800; +#endif /* CONFIG_RISCV_GP */ + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + + /* All dependent functions should be placed in DRAM to avoid issue + * when flash cache is disabled */ + *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.*) + *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*) + *libzephyr.a:spi_flash_rom_patch.*(.rodata .rodata.*) + + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + #include + #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") + + .dummy.dram.data : + { + . = ALIGN(4); + #include + _end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + .iram0.text_end (NOLOAD) : + { + /* C3 memprot requires 512 B alignment for split lines */ + . = ALIGN (16); + } GROUP_LINK_IN(IRAM_REGION) + + .iram0.data : + { + . = ALIGN(16); + *(.iram.data) + *(.iram.data*) + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram0.bss (NOLOAD) : + { + . = ALIGN(16); + *(.iram.bss) + *(.iram.bss*) + + . = ALIGN(16); + _iram_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + _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_dummy (NOLOAD): ALIGN(IROM_SEG_ALIGN) + { + . = SIZEOF(_RODATA_SECTION_NAME); + . = ALIGN(0x10000) + 0x20; + _rodata_reserved_start = .; + } GROUP_LINK_IN(FLASH_CODE_REGION) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + _stext = .; + _text_start = ABSOLUTE(.); + +#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) +#endif + +#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + *(.literal .text .literal.* .text.*) + *(.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) + + /** 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. + */ + _flash_cache_start = ABSOLUTE(0); + } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) + + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + /* This section is required to skip rtc.text area because the text and + * data segments reflect the same address space on different buses. + */ + .rtc.dummy (NOLOAD): + { + . = SIZEOF(.rtc.text); + } GROUP_LINK_IN(rtc_iram_seg) + + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(rtc_iram_seg) + + /** + * This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Get size of rtc slow data */ + _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.riscv.attributes, 0,) + { + KEEP(*(.riscv.attributes)) + KEEP(*(.gnu.attributes)) + } +} diff --git a/soc/riscv/esp32c3/linker.ld b/soc/riscv/esp32c3/linker.ld index 13d08d39bee..934088ca728 100644 --- a/soc/riscv/esp32c3/linker.ld +++ b/soc/riscv/esp32c3/linker.ld @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. * SPDX-License-Identifier: Apache-2.0 */ @@ -7,503 +7,14 @@ * @file * @brief Linker command/script file * - * Linker script for the esp32c3 platform. */ -#include -#include -#include -#include +#if defined(CONFIG_MCUBOOT) + /* Using mcuboot as ESP32C3 2nd stage bootloader */ + #include "mcuboot.ld" -#define RAMABLE_REGION dram0_0_seg -#define RODATA_REGION drom0_0_seg -#define IRAM_REGION iram0_0_seg -#define FLASH_CODE_REGION irom0_0_seg - -#define ROMABLE_REGION ROM - -#define SRAM_IRAM_START 0x4037C000 -#define SRAM_DRAM_START 0x3FC7C000 -#define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */ -#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START) -#define SRAM_DRAM_END 0x403D0000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */ -#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE) -#define SRAM_DRAM_ORG (SRAM_DRAM_START + ICACHE_SIZE) -#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG - -#ifdef CONFIG_FLASH_SIZE -#define FLASH_SIZE CONFIG_FLASH_SIZE #else -#define FLASH_SIZE 0x400000 -#endif + /* Application default linker script */ + #include "default.ld" -#ifdef CONFIG_BOOTLOADER_ESP_IDF -#define IROM_SEG_ORG 0x42000020 -#define IROM_SEG_LEN (FLASH_SIZE-0x20) -#define IROM_SEG_ALIGN 0x4 -#else -#define IROM_SEG_ORG 0x42000000 -#define IROM_SEG_LEN FLASH_SIZE -#define IROM_SEG_ALIGN 0x10000 -#endif - -/* Global symbols required for espressif hal build */ -MEMORY -{ - mcuboot_hdr (RX): org = 0x0, len = 0x20 - metadata (RX): org = 0x20, len = 0x20 - ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 - - iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE - irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN - - drom0_0_seg (R) : org = 0x3C000040, len = FLASH_SIZE - 0x40 - dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = I_D_SRAM_SIZE - - rtc_iram_seg(RWX): org = 0x50000000, len = 0x2000 - -#ifdef CONFIG_GEN_ISR_TABLES - IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 -#endif -} - - -/* The line below defines location alias for .rtc.data section - * As C3 only has RTC fast memory, this is not configurable like - * on other targets. - */ -REGION_ALIAS("rtc_slow_seg", rtc_iram_seg); - -/* Default entry point: */ -ENTRY(CONFIG_KERNEL_ENTRY) - -_rom_store_table = 0; - -SECTIONS -{ - /* Reserve space for MCUboot header in the binary */ - .mcuboot_header : - { - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - } > mcuboot_hdr - .metadata : - { - /* Magic byte for load header */ - LONG(0xace637d3) - - /* Application entry point address */ - KEEP(*(.entry_addr)) - - /* IRAM metadata: - * - Destination address (VMA) for IRAM region - * - Flash offset (LMA) for start of IRAM region - * - Size of IRAM region - */ - LONG(ADDR(.iram0.text)) - LONG(LOADADDR(.iram0.text)) - LONG(SIZEOF(.iram0.text)) - - /* DRAM metadata: - * - Destination address (VMA) for DRAM region - * - Flash offset (LMA) for start of DRAM region - * - Size of DRAM region - */ - LONG(ADDR(.dram0.data)) - LONG(LOADADDR(.dram0.data)) - LONG(LOADADDR(.dummy.dram.data) + SIZEOF(.dummy.dram.data) - LOADADDR(.dram0.data)) - } > metadata - -#include - _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,,) - { - _rodata_start = ABSOLUTE(.); - - *(.rodata_desc .rodata_desc.*) - *(.rodata_custom_desc .rodata_custom_desc.*) - - __rodata_region_start = .; - - . = ALIGN(4); - #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.*) - - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 3) & ~ 3; - __eh_frame = ABSOLUTE(.); - KEEP(*(.eh_frame)) - . = (. + 7) & ~ 3; - - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - __rodata_region_end = .; - _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - *(.srodata) - *(.srodata.*) - *(.rodata) - *(.rodata.*) - *(.rodata_wlog) - *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN(4); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion - #include - #include - #include - #include - #include - #include - #include - #pragma pop_macro("GROUP_ROM_LINK_IN") - - /* 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,,) - { - . = ALIGN(4); - _image_rodata_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - .iram0.text : ALIGN(4) - { - /* Vectors go to IRAM */ - _iram_start = ABSOLUTE(.); - _init_start = ABSOLUTE(.); - - KEEP(*(.exception_vectors.text)); - . = ALIGN(256); - - _invalid_pc_placeholder = ABSOLUTE(.); - - _iram_text_start = ABSOLUTE(.); - - KEEP(*(.exception.entry*)); /* contains _isr_wrapper */ - *(.exception.other*) - . = ALIGN(4); - - *(.entry.text) - *(.init.literal) - *(.init) - . = ALIGN(4); - *(.iram1 .iram1.*) - *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) - *libesp32.a:panic.*(.literal .text .literal.* .text.*) - *librtc.a:(.literal .text .literal.* .text.*) - *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) - *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) - *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) - *libsubsys__net.a:(.literal .text .literal.* .text.*) - *libkernel.a:(.literal .text .literal.* .text.*) - *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) - *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) - *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) - *libdrivers__timer.a:esp32c3_sys_timer.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) - *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) - *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) - *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) - *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) - *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) - *libzephyr.a:loader.*(.literal .text .literal.* .text.*) - *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) - *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) - *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) - *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) - *libc.a:*(.literal .text .literal.* .text.*) - *libphy.a:( .phyiram .phyiram.*) - *libgcov.a:(.literal .text .literal.* .text.*) - -#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) -#endif - -#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - . = ALIGN(4); - _init_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - .dram0.dummy (NOLOAD): - { - /** - * This section is required to skip .iram0.text area because iram0_0_seg and - * dram0_0_seg reflect the same address space on different buses. - */ - . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; - } GROUP_LINK_IN(RAMABLE_REGION) - - /* Shared RAM */ - SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) - { - . = ALIGN (8); - __bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.share.mem) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - __bss_end = ABSOLUTE(.); - } GROUP_LINK_IN(RAMABLE_REGION) - - SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) - { - . = ALIGN(4); - *(.noinit) - *(.noinit.*) - . = ALIGN(4); - } GROUP_LINK_IN(RAMABLE_REGION) - - #include - - .dram0.data : - { - . = ALIGN(4); - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - *(.data1) -#ifdef CONFIG_RISCV_GP - __global_pointer$ = . + 0x800; -#endif /* CONFIG_RISCV_GP */ - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - - /* All dependent functions should be placed in DRAM to avoid issue - * when flash cache is disabled */ - *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.*) - *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*) - *libzephyr.a:spi_flash_rom_patch.*(.rodata .rodata.*) - - - KEEP(*(.jcr)) - *(.dram1 .dram1.*) - . = ALIGN(4); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - #include - #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") - - .dummy.dram.data : - { - . = ALIGN(4); - #include - _end = ABSOLUTE(.); - _data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - .iram0.text_end (NOLOAD) : - { - /* C3 memprot requires 512 B alignment for split lines */ - . = ALIGN (16); - } GROUP_LINK_IN(IRAM_REGION) - - .iram0.data : - { - . = ALIGN(16); - *(.iram.data) - *(.iram.data*) - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - .iram0.bss (NOLOAD) : - { - . = ALIGN(16); - *(.iram.bss) - *(.iram.bss*) - - . = ALIGN(16); - _iram_end = ABSOLUTE(.); - } GROUP_LINK_IN(IRAM_REGION) - - _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_dummy (NOLOAD): ALIGN(IROM_SEG_ALIGN) - { - . = SIZEOF(_RODATA_SECTION_NAME); - . = ALIGN(0x10000) + 0x20; - _rodata_reserved_start = .; - } GROUP_LINK_IN(FLASH_CODE_REGION) - - .flash.text : ALIGN(IROM_SEG_ALIGN) - { - _stext = .; - _text_start = ABSOLUTE(.); - -#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) -#endif - -#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - *(.literal .text .literal.* .text.*) - *(.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) - - /** 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. - */ - _flash_cache_start = ABSOLUTE(0); - } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) - - .rtc.text : - { - . = ALIGN(4); - *(.rtc.literal .rtc.text) - *rtc_wake_stub*.o(.literal .text .literal.* .text.*) - } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) - - /* This section is required to skip rtc.text area because the text and - * data segments reflect the same address space on different buses. - */ - .rtc.dummy (NOLOAD): - { - . = SIZEOF(.rtc.text); - } GROUP_LINK_IN(rtc_iram_seg) - - .rtc.data : - { - _rtc_data_start = ABSOLUTE(.); - *(.rtc.data) - *(.rtc.rodata) - *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) - _rtc_data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) - - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - *rtc_wake_stub*.o(.bss .bss.*) - *rtc_wake_stub*.o(COMMON) - _rtc_bss_end = ABSOLUTE(.); - } GROUP_LINK_IN(rtc_iram_seg) - - /** - * This section located in RTC SLOW Memory area. - * It holds data marked with RTC_SLOW_ATTR attribute. - * See the file "esp_attr.h" for more information. - */ - .rtc.force_slow : - { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); - *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); - } > rtc_slow_seg - - /* Get size of rtc slow data */ - _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); - -#ifdef CONFIG_GEN_ISR_TABLES -#include -#endif - -#include - /DISCARD/ : { *(.note.GNU-stack) } - - SECTION_PROLOGUE(.riscv.attributes, 0,) - { - KEEP(*(.riscv.attributes)) - KEEP(*(.gnu.attributes)) - } -} +#endif /* CONFIG_MCUBOOT */ diff --git a/soc/riscv/esp32c3/loader.c b/soc/riscv/esp32c3/loader.c index 7b369c88590..bf1665d76eb 100644 --- a/soc/riscv/esp32c3/loader.c +++ b/soc/riscv/esp32c3/loader.c @@ -16,6 +16,10 @@ #include #ifdef CONFIG_BOOTLOADER_MCUBOOT + +#define BOOT_LOG_INF(_fmt, ...) \ + ets_printf("[" CONFIG_SOC "] [INF] " _fmt "\n\r", ##__VA_ARGS__) + #define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used)) extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr; @@ -64,9 +68,16 @@ static int map_rom_segments(void) esp_rom_Cache_Resume_ICache(autoload); + /* Show map segments continue using same log format as during MCUboot phase */ + BOOT_LOG_INF("DROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map", + _app_drom_start, _app_drom_vaddr, _app_drom_size, _app_drom_size); + BOOT_LOG_INF("IROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map\r\n", + _app_irom_start, _app_irom_vaddr, _app_irom_size, _app_irom_size); + esp_rom_uart_tx_wait_idle(0); + return rc; } -#endif +#endif /* CONFIG_BOOTLOADER_MCUBOOT */ void __start(void) { diff --git a/soc/riscv/esp32c3/mcuboot.ld b/soc/riscv/esp32c3/mcuboot.ld new file mode 100644 index 00000000000..fe68368fdd1 --- /dev/null +++ b/soc/riscv/esp32c3/mcuboot.ld @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the esp32c3 platform. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_XIP +#error "ESP32C3 bootloader cannot use XIP" +#endif /* CONFIG_XIP */ + +/* Disable all romable LMA */ +#udef GROUP_DATA_LINK_IN +#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion + +#define RAMABLE_REGION dram_seg +#define RODATA_REGION dram_seg + +#define IRAM_REGION iram_seg +#define IRAM_LOADER_REGION iram_loader_seg + +#define ROMABLE_REGION dram_seg +#define IROM_SEG_ALIGN 0x4 + +/* Global symbols required for espressif hal build */ +MEMORY +{ + iram_seg (RX) : org = 0x403CA000, len = 0x6000 + iram_loader_seg (RX) : org = 0x403D0000, len = 0x4000 + dram_seg (RW) : org = 0x3FCD8000, len = 0x8000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + _rodata_start = ABSOLUTE(.); + + *(.rodata_desc .rodata_desc.*) + *(.rodata_custom_desc .rodata_custom_desc.*) + + __rodata_region_start = .; + + . = ALIGN(4); + #include + . = ALIGN(4); + + *(.rodata) + *(.rodata.*) + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + __rodata_region_end = .; + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.srodata) + *(.srodata.*) + *(.rodata) + *(.rodata.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + /* _rodata_reserved_end = ABSOLUTE(.); */ + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + + #include + + .dram0.data : + { + . = ALIGN(4); + __data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) +#ifdef CONFIG_RISCV_GP + __global_pointer$ = . + 0x800; +#endif /* CONFIG_RISCV_GP */ + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + + #include + + .dram0.end : + { + . = ALIGN(4); + #include + . = ALIGN(4); + _end = ABSOLUTE(.); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + __bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + _bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN(4); + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + } GROUP_LINK_IN(RAMABLE_REGION) + + .iram_loader.text : + { + . = ALIGN (16); + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash_config_esp32c3.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_init_common.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) + *libzephyr.a:bootloader_efuse_esp32c3.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_partitions.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libzephyr.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_fields.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api_key_esp32xx.*(.literal .text .literal.* .text.*) + *esp_mcuboot.*(.literal .text .literal.* .text.*) + *esp_loader.*(.literal .text .literal.* .text.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _loader_text_end = ABSOLUTE(.); + } > iram_loader_seg + + /* .iram0.text : ALIGN(4) */ + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Vectors go to IRAM */ + _iram_start = ABSOLUTE(.); + _init_start = ABSOLUTE(.); + + KEEP(*(.exception_vectors.text)); + . = ALIGN(256); + + _invalid_pc_placeholder = ABSOLUTE(.); + + _iram_text_start = ABSOLUTE(.); + + KEEP(*(.exception.entry*)); /* contains _isr_wrapper */ + *(.exception.other*) + . = ALIGN(4); + + *(.entry.text) + *(.init.literal) + *(.init) + . = ALIGN(4); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + + . = ALIGN(4); + _init_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_LOADER_REGION, ROMABLE_REGION) + + .iram0.text_end (NOLOAD) : + { + /* C3 memprot requires 512 B alignment for split lines */ + . = ALIGN (16); + } GROUP_LINK_IN(IRAM_LOADER_REGION) + + .iram0.data : + { + . = ALIGN(16); + *(.iram.data) + *(.iram.data*) + } GROUP_DATA_LINK_IN(IRAM_LOADER_REGION, ROMABLE_REGION) + + .iram0.bss (NOLOAD) : + { + . = ALIGN(16); + *(.iram.bss) + *(.iram.bss*) + + . = ALIGN(16); + _iram_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_LOADER_REGION) + + .flash_text_dummy (NOLOAD): ALIGN(IROM_SEG_ALIGN) + { + . = SIZEOF(_RODATA_SECTION_NAME); + . = ALIGN(4) + 0x20; + _rodata_reserved_start = .; + } GROUP_LINK_IN(IRAM_REGION) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + _stext = .; + _text_start = ABSOLUTE(.); + + *(.literal .text .literal.* .text.*) + *(.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) + + /* 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. + */ + _flash_cache_start = ABSOLUTE(0); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + /* linker rel sections*/ + #include + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.riscv.attributes, 0,) + { + KEEP(*(.riscv.attributes)) + KEEP(*(.gnu.attributes)) + } +} diff --git a/soc/riscv/esp32c3/soc.c b/soc/riscv/esp32c3/soc.c index 11c304de14f..be94280a96a 100644 --- a/soc/riscv/esp32c3/soc.c +++ b/soc/riscv/esp32c3/soc.c @@ -12,6 +12,7 @@ #include #include #include "hal/soc_ll.h" +#include "hal/wdt_hal.h" #include "esp_cpu.h" #include "esp_timer.h" #include "esp_spi_flash.h" @@ -25,6 +26,10 @@ #include #include +#ifdef CONFIG_MCUBOOT +#include "bootloader_init.h" +#endif /* CONFIG_MCUBOOT */ + /* * 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 @@ -32,9 +37,6 @@ */ void __attribute__((section(".iram1"))) __esp_platform_start(void) { - volatile uint32_t *wdt_rtc_protect = (uint32_t *)RTC_CNTL_WDTWPROTECT_REG; - volatile uint32_t *wdt_rtc_reg = (uint32_t *)RTC_CNTL_WDTCONFIG0_REG; - #ifdef CONFIG_RISCV_GP /* Configure the global pointer register * (This should be the first thing startup does, as any other piece of code could be @@ -54,13 +56,21 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) /* Disable normal interrupts. */ csr_read_clear(mstatus, MSTATUS_MIE); +#ifdef CONFIG_MCUBOOT + /* MCUboot early initialisation. + */ + bootloader_init(); + +#else /* ESP-IDF 2nd stage bootloader enables RTC WDT to check on startup sequence * related issues in application. Hence disable that as we are about to start * Zephyr environment. */ - *wdt_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE; - *wdt_rtc_reg &= ~RTC_CNTL_WDT_EN; - *wdt_rtc_protect = 0; + wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; + + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_disable(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); /* Configure the Cache MMU size for instruction and rodata in flash. */ extern uint32_t esp_rom_cache_set_idrom_mmu_size(uint32_t irom_size, @@ -93,6 +103,8 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) spi_flash_guard_set(&g_flash_guard_default_ops); #endif +#endif /* CONFIG_MCUBOOT */ + /*Initialize the esp32c3 interrupt controller */ esp_intr_initialize(); diff --git a/soc/xtensa/esp32/CMakeLists.txt b/soc/xtensa/esp32/CMakeLists.txt index a2c3d7e2d84..0728e94e253 100644 --- a/soc/xtensa/esp32/CMakeLists.txt +++ b/soc/xtensa/esp32/CMakeLists.txt @@ -63,14 +63,6 @@ if(CONFIG_BOOTLOADER_ESP_IDF) INSTALL_COMMAND "" ) - if(CONFIG_BUILD_OUTPUT_BIN) - set_property(GLOBAL APPEND PROPERTY extra_post_build_commands - COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py - ARGS --chip esp32 elf2image --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() - set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) add_dependencies(app EspIdfBootloader EspPartitionTable) @@ -83,6 +75,22 @@ if(CONFIG_BOOTLOADER_ESP_IDF) endif() +if(CONFIG_MCUBOOT OR CONFIG_BOOTLOADER_ESP_IDF) + + if(CONFIG_BUILD_OUTPUT_BIN) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py + ARGS --chip esp32 elf2image --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() + + if(CONFIG_MCUBOOT) + board_finalize_runner_args(esp32 "--esp-flash-bootloader=${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin") + endif() + +endif() + board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") diff --git a/soc/xtensa/esp32/Kconfig.soc b/soc/xtensa/esp32/Kconfig.soc index 234a4a2bd1a..56949f96599 100644 --- a/soc/xtensa/esp32/Kconfig.soc +++ b/soc/xtensa/esp32/Kconfig.soc @@ -9,7 +9,7 @@ config SOC_ESP32 select ARCH_HAS_GDBSTUB select ARCH_SUPPORTS_COREDUMP select PINCTRL - select XIP + select XIP if !MCUBOOT select HAS_ESPRESSIF_HAL select CPU_HAS_FPU @@ -45,6 +45,7 @@ config ESP32_BT_RESERVE_DRAM config ESP_HEAP_MEM_POOL_REGION_1_SIZE int "Internal DRAM region 1 mempool size" + default 0 if MCUBOOT default 1024 if ESP32_NETWORK_CORE default 49152 help diff --git a/soc/xtensa/esp32/default.ld b/soc/xtensa/esp32/default.ld new file mode 100644 index 00000000000..3dbd0819597 --- /dev/null +++ b/soc/xtensa/esp32/default.ld @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2016 Cadence Design Systems, Inc. + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 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_0_seg +#ifndef CONFIG_ESP32_NETWORK_CORE +#define RAMABLE_REGION_1 dram0_1_seg +#else +#define RAMABLE_REGION_1 dram0_0_seg +#endif +#define RODATA_REGION drom0_0_seg +#define IRAM_REGION iram0_0_seg +#define FLASH_CODE_REGION irom0_0_seg + +#define ROMABLE_REGION ROM + +#ifdef CONFIG_FLASH_SIZE +#define ROM_SIZE CONFIG_FLASH_SIZE +#else +#define ROM_SIZE 0x400000 +#endif + +#ifdef CONFIG_BOOTLOADER_ESP_IDF +#define IROM_SEG_ORG 0x400D0020 +#define IROM_SEG_LEN 0x330000-0x20 +#define IROM_SEG_ALIGN 0x4 +#define IRAM_SEG_LEN 0x20000 +#else +#define IROM_SEG_ORG 0x400D0000 +#define IROM_SEG_LEN 0x330000 +#define IROM_SEG_ALIGN 0x10000 +#define IRAM_SEG_LEN 0x13000 +#endif + +MEMORY +{ + mcuboot_hdr (RX): org = 0x0, len = 0x20 + metadata (RX): org = 0x20, len = 0x20 + ROM (RX): org = 0x40, len = ROM_SIZE - 0x40 + + #ifdef CONFIG_ESP32_NETWORK_CORE + iram0_0_seg(RX): org = 0x40080000, len = 0x08000 + #else + iram0_0_seg(RX): org = 0x40080000, len = IRAM_SEG_LEN + #endif + + irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN + /* + * Following is DRAM memory split with reserved address ranges in ESP32: + * + * 0x3FFA_E000 - 0x3FFB_0000 (Reserved: data memory for ROM functions) + * 0x3FFB_0000 - 0x3FFE_0000 (RAM bank 1 for application usage) + * 0x3FFE_0000 - 0x3FFE_0440 (Reserved: data memory for ROM PRO CPU) + * 0x3FFE_3F20 - 0x3FFE_4350 (Reserved: data memory for ROM APP CPU) + * 0x3FFE_4350 - 0x3F10_0000 (RAM bank 2 for application usage) + * + * FIXME: + * - Utilize available memory regions to full capacity + */ + dram0_0_seg(RW): org = 0x3FFB0000 + CONFIG_ESP32_BT_RESERVE_DRAM, len = 0x2c200 - CONFIG_ESP32_BT_RESERVE_DRAM + + #ifdef CONFIG_ESP32_NETWORK_CORE + dram0_shm0_seg(RW): org = 0x3FFE5230, len = 2K /* shared RAM reserved for IPM */ + dram0_sem0_seg(RW): org = 0x3FFE5A30, len = 8 /* shared data reserved for IPM data header */ + dram0_1_seg(RW): org = 0x3FFE5A38, len = 0K /* for AMP builds dram0_1 is reserved for network core */ + #else + dram0_1_seg(RW): org = 0x3FFE5230, len = 0x1BCB0 - 0xEE0 /* skip data for APP CPU initialization usage */ + #endif + + /* DROM is the first segment placed in generated binary. + * MCUboot binary for ESP32 has image header of 0x20 bytes. + * Additional load header of 0x20 bytes are appended to the image. + * Hence, an offset of 0x40 is added to DROM segment origin. + */ + drom0_0_seg(R): org = 0x3F400040, len = 0x400000 - 0x40 + rtc_iram_seg(RWX): org = 0x400C0000, len = 0x2000 + rtc_slow_seg(RW): org = 0x50000000, len = 0x1000 +#if defined(CONFIG_ESP_SPIRAM) + ext_ram_seg(RW): org = 0x3F800000, len = CONFIG_ESP_SPIRAM_SIZE +#endif +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +PROVIDE ( _ResetVector = 0x40000400 ); +ENTRY(CONFIG_KERNEL_ENTRY) + +_rom_store_table = 0; + +PROVIDE(_memmap_vecbase_reset = 0x40000450); +PROVIDE(_memmap_reset_vector = 0x40000400); + +SECTIONS +{ + /* Reserve space for MCUboot header in the binary */ + .mcuboot_header : + { + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + } > mcuboot_hdr + .metadata : + { + /* Magic byte for load header */ + LONG(0xace637d3) + + /* Application entry point address */ + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * - Destination address (VMA) for IRAM region + * - Flash offset (LMA) for start of IRAM region + * - Size of IRAM region + */ + + LONG(ADDR(.iram0.vectors)) + LONG(LOADADDR(.iram0.vectors)) + LONG(LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - LOADADDR(.iram0.vectors)) + + /* DRAM metadata: + * - Destination address (VMA) for DRAM region + * - Flash offset (LMA) for start of DRAM region + * - Size of DRAM region + */ + + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - LOADADDR(.dram0.data)) + } > metadata + +#include + + _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); + + /* NOTE: .rodata section should be the first section in the linker script and no + * other section should appear before .rodata section. This is the requirement + * to align ROM section to 64K page offset. + * Adding .rodata as first section helps to reduce size of generated binary by + * few kBs. + */ + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + __rodata_region_start = ABSOLUTE(.); + + . = ALIGN(4); + #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.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + #include + #include + #include + #include + #include + #include + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + /* 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,,) + { + . = 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); + + #include + + .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_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); + _end = ABSOLUTE(.); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + _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); + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.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); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *libesp32.a:panic.*(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) + *libkernel.a:(.literal .text .literal.* .text.*) + *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) + *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) + *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) + *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) + *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) + *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) + *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *libzephyr.a:loader.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) + *libc.a:*(.literal .text .literal.* .text.*) + *libphy.a:( .phyiram .phyiram.*) + *libgcov.a:(.literal .text .literal.* .text.*) + +#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) +#endif + +#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + _iram_text_end = ABSOLUTE(.); + . = ALIGN(4); + _iram_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + /* RTC slow memory holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(rtc_slow_seg) + + /* This section located in RTC SLOW Memory area. + It holds data marked with RTC_SLOW_ATTR attribute. + See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Get size of rtc slow data */ + _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); + +#if defined(CONFIG_ESP_SPIRAM) + .ext_ram.bss (NOLOAD): + { + _ext_ram_data_start = ABSOLUTE(.); + +#if defined(CONFIG_ESP32_WIFI_NET_ALLOC_SPIRAM) + *libdrivers__wifi.a:(.noinit .noinit.*) + *libsubsys__net__l2__ethernet.a:(.noinit .noinit.*) + *libsubsys__net__lib__config.a:(.noinit .noinit.*) + *libsubsys__net__ip.a:(.noinit .noinit.*) + *libsubsys__net.a:(.noinit .noinit.*) +#endif + + *(.ext_ram.bss*) + _ext_ram_data_end = ABSOLUTE(.) + CONFIG_ESP_SPIRAM_SIZE; + } GROUP_LINK_IN(ext_ram_seg) +#endif + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); /* required by bluetooth library */ + __bss_start = ABSOLUTE(.); + + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = 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.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + _end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_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(IROM_SEG_ALIGN) + { + _stext = .; + _text_start = ABSOLUTE(.); + +#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) +#endif + +#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + *(.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) + +_heap_sentry = 0x3ffe3f20; + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + 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)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32/linker.ld b/soc/xtensa/esp32/linker.ld index 9d3a1b84c37..981d25bf18a 100644 --- a/soc/xtensa/esp32/linker.ld +++ b/soc/xtensa/esp32/linker.ld @@ -1,7 +1,5 @@ /* - * Copyright (c) 2016 Cadence Design Systems, Inc. - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. * SPDX-License-Identifier: Apache-2.0 */ @@ -9,575 +7,14 @@ * @file * @brief Linker command/script file * - * Linker script for the Xtensa platform. */ -#include -#include -#include -#include +#if defined(CONFIG_MCUBOOT) + /* Using mcuboot as ESP32 2nd stage bootloader */ + #include "mcuboot.ld" -#define RAMABLE_REGION dram0_0_seg -#ifndef CONFIG_ESP32_NETWORK_CORE -#define RAMABLE_REGION_1 dram0_1_seg #else -#define RAMABLE_REGION_1 dram0_0_seg -#endif -#define RODATA_REGION drom0_0_seg -#define IRAM_REGION iram0_0_seg -#define FLASH_CODE_REGION irom0_0_seg + /* Application default linker script */ + #include "default.ld" -#define ROMABLE_REGION ROM - -#ifdef CONFIG_FLASH_SIZE -#define ROM_SIZE CONFIG_FLASH_SIZE -#else -#define ROM_SIZE 0x400000 -#endif - -#ifdef CONFIG_BOOTLOADER_ESP_IDF -#define IROM_SEG_ORG 0x400D0020 -#define IROM_SEG_LEN 0x330000-0x20 -#define IROM_SEG_ALIGN 0x4 -#define IRAM_SEG_LEN 0x20000 -#else -#define IROM_SEG_ORG 0x400D0000 -#define IROM_SEG_LEN 0x330000 -#define IROM_SEG_ALIGN 0x10000 -#define IRAM_SEG_LEN 0x13000 -#endif - -MEMORY -{ - mcuboot_hdr (RX): org = 0x0, len = 0x20 - metadata (RX): org = 0x20, len = 0x20 - ROM (RX): org = 0x40, len = ROM_SIZE - 0x40 - - #ifdef CONFIG_ESP32_NETWORK_CORE - iram0_0_seg(RX): org = 0x40080000, len = 0x08000 - #else - iram0_0_seg(RX): org = 0x40080000, len = IRAM_SEG_LEN - #endif - - irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN - /* - * Following is DRAM memory split with reserved address ranges in ESP32: - * - * 0x3FFA_E000 - 0x3FFB_0000 (Reserved: data memory for ROM functions) - * 0x3FFB_0000 - 0x3FFE_0000 (RAM bank 1 for application usage) - * 0x3FFE_0000 - 0x3FFE_0440 (Reserved: data memory for ROM PRO CPU) - * 0x3FFE_3F20 - 0x3FFE_4350 (Reserved: data memory for ROM APP CPU) - * 0x3FFE_4350 - 0x3F10_0000 (RAM bank 2 for application usage) - * - * FIXME: - * - Utilize available memory regions to full capacity - */ - dram0_0_seg(RW): org = 0x3FFB0000 + CONFIG_ESP32_BT_RESERVE_DRAM, len = 0x2c200 - CONFIG_ESP32_BT_RESERVE_DRAM - - #ifdef CONFIG_ESP32_NETWORK_CORE - 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, len = 0K /* for AMP builds dram0_1 is reserved for network core */ - #else - dram0_1_seg(RW): org = 0x3FFE5230, len = 0x1BCB0 - 0xEE0 /* skip data for APP CPU initialization usage */ - #endif - - /* DROM is the first segment placed in generated binary. - * MCUboot binary for ESP32 has image header of 0x20 bytes. - * Additional load header of 0x20 bytes are appended to the image. - * Hence, an offset of 0x40 is added to DROM segment origin. - */ - drom0_0_seg(R): org = 0x3F400040, len = 0x400000 - 0x40 - rtc_iram_seg(RWX): org = 0x400C0000, len = 0x2000 - rtc_slow_seg(RW): org = 0x50000000, len = 0x1000 -#if defined(CONFIG_ESP_SPIRAM) - ext_ram_seg(RW): org = 0x3F800000, len = CONFIG_ESP_SPIRAM_SIZE -#endif -#ifdef CONFIG_GEN_ISR_TABLES - IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 -#endif -} - -/* Default entry point: */ -PROVIDE ( _ResetVector = 0x40000400 ); -ENTRY(CONFIG_KERNEL_ENTRY) - -_rom_store_table = 0; - -PROVIDE(_memmap_vecbase_reset = 0x40000450); -PROVIDE(_memmap_reset_vector = 0x40000400); - -SECTIONS -{ - /* Reserve space for MCUboot header in the binary */ - .mcuboot_header : - { - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - } > mcuboot_hdr - .metadata : - { - /* Magic byte for load header */ - LONG(0xace637d3) - - /* Application entry point address */ - KEEP(*(.entry_addr)) - - /* IRAM metadata: - * - Destination address (VMA) for IRAM region - * - Flash offset (LMA) for start of IRAM region - * - Size of IRAM region - */ - - LONG(ADDR(.iram0.vectors)) - LONG(LOADADDR(.iram0.vectors)) - LONG(LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - LOADADDR(.iram0.vectors)) - - /* DRAM metadata: - * - Destination address (VMA) for DRAM region - * - Flash offset (LMA) for start of DRAM region - * - Size of DRAM region - */ - - LONG(ADDR(.dram0.data)) - LONG(LOADADDR(.dram0.data)) - LONG(LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - LOADADDR(.dram0.data)) - } > metadata - -#include - - _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); - - /* NOTE: .rodata section should be the first section in the linker script and no - * other section should appear before .rodata section. This is the requirement - * to align ROM section to 64K page offset. - * Adding .rodata as first section helps to reduce size of generated binary by - * few kBs. - */ - SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) - { - __rodata_region_start = ABSOLUTE(.); - - . = ALIGN(4); - #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.*) - - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 3) & ~ 3; - __eh_frame = ABSOLUTE(.); - KEEP(*(.eh_frame)) - . = (. + 7) & ~ 3; - - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - . = ALIGN(4); - __rodata_region_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - *(.rodata_wlog) - *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); - . = ALIGN(4); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion - #include - #include - #include - #include - #include - #include - #include - #pragma pop_macro("GROUP_ROM_LINK_IN") - - /* 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,,) - { - . = 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); - - #include - - .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_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); - _end = ABSOLUTE(.); - __data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - _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); - - /* Send .iram0 code to iram */ - .iram0.vectors : ALIGN(4) - { - /* Vectors go to IRAM */ - _init_start = ABSOLUTE(.); - /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ - . = 0x0; - KEEP(*(.WindowVectors.text)); - . = 0x180; - KEEP(*(.Level2InterruptVector.text)); - . = 0x1c0; - KEEP(*(.Level3InterruptVector.text)); - . = 0x200; - KEEP(*(.Level4InterruptVector.text)); - . = 0x240; - KEEP(*(.Level5InterruptVector.text)); - . = 0x280; - KEEP(*(.DebugExceptionVector.text)); - . = 0x2c0; - KEEP(*(.NMIExceptionVector.text)); - . = 0x300; - KEEP(*(.KernelExceptionVector.text)); - . = 0x340; - KEEP(*(.UserExceptionVector.text)); - . = 0x3C0; - KEEP(*(.DoubleExceptionVector.text)); - . = 0x400; - *(.*Vector.literal) - - *(.UserEnter.literal); - *(.UserEnter.text); - . = ALIGN (16); - *(.entry.text) - *(.init.literal) - *(.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); - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) - { - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - *(.iram1 .iram1.*) - *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) - *libesp32.a:panic.*(.literal .text .literal.* .text.*) - *librtc.a:(.literal .text .literal.* .text.*) - *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) - *libkernel.a:(.literal .text .literal.* .text.*) - *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) - *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) - *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) - *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) - *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) - *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) - *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) - *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) - *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) - *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) - *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) - *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) - *libzephyr.a:loader.*(.literal .text .literal.* .text.*) - *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) - *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) - *libc.a:*(.literal .text .literal.* .text.*) - *libphy.a:( .phyiram .phyiram.*) - *libgcov.a:(.literal .text .literal.* .text.*) - -#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) -#endif - -#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - _iram_text_end = ABSOLUTE(.); - . = ALIGN(4); - _iram_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - /* RTC fast memory holds RTC wake stub code, - including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - . = ALIGN(4); - *(.rtc.literal .rtc.text) - *rtc_wake_stub*.o(.literal .text .literal.* .text.*) - } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) - - /* RTC slow memory holds RTC wake stub - data/rodata, including from any source file - named rtc_wake_stub*.c - */ - .rtc.data : - { - _rtc_data_start = ABSOLUTE(.); - *(.rtc.data) - *(.rtc.rodata) - *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) - _rtc_data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - *rtc_wake_stub*.o(.bss .bss.*) - *rtc_wake_stub*.o(COMMON) - _rtc_bss_end = ABSOLUTE(.); - } GROUP_LINK_IN(rtc_slow_seg) - - /* This section located in RTC SLOW Memory area. - It holds data marked with RTC_SLOW_ATTR attribute. - See the file "esp_attr.h" for more information. - */ - .rtc.force_slow : - { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); - *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); - } > rtc_slow_seg - - /* Get size of rtc slow data */ - _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); - -#if defined(CONFIG_ESP_SPIRAM) - .ext_ram.bss (NOLOAD): - { - _ext_ram_data_start = ABSOLUTE(.); - -#if defined(CONFIG_ESP32_WIFI_NET_ALLOC_SPIRAM) - *libdrivers__wifi.a:(.noinit .noinit.*) - *libsubsys__net__l2__ethernet.a:(.noinit .noinit.*) - *libsubsys__net__lib__config.a:(.noinit .noinit.*) - *libsubsys__net__ip.a:(.noinit .noinit.*) - *libsubsys__net.a:(.noinit .noinit.*) -#endif - - *(.ext_ram.bss*) - _ext_ram_data_end = ABSOLUTE(.) + CONFIG_ESP_SPIRAM_SIZE; - } GROUP_LINK_IN(ext_ram_seg) -#endif - - /* Shared RAM */ - SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); /* required by bluetooth library */ - __bss_start = ABSOLUTE(.); - - _btdm_bss_start = ABSOLUTE(.); - *libbtdm_app.a:(.bss .bss.* COMMON) - . = 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.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.share.mem) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - __bss_end = ABSOLUTE(.); - _end = ABSOLUTE(.); - } GROUP_LINK_IN(RAMABLE_REGION) - - ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_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(IROM_SEG_ALIGN) - { - _stext = .; - _text_start = ABSOLUTE(.); - -#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) -#endif - -#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - *(.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) - -_heap_sentry = 0x3ffe3f20; - -#include - - .xtensa.info 0 : { *(.xtensa.info) } - .xt.insn 0 : - { - KEEP (*(.xt.insn)) - KEEP (*(.gnu.linkonce.x.*)) - } - .xt.prop 0 : - { - KEEP (*(.xt.prop)) - KEEP (*(.xt.prop.*)) - KEEP (*(.gnu.linkonce.prop.*)) - } - .xt.lit 0 : - { - KEEP (*(.xt.lit)) - KEEP (*(.xt.lit.*)) - KEEP (*(.gnu.linkonce.p.*)) - } - .xt.profile_range 0 : - { - KEEP (*(.xt.profile_range)) - KEEP (*(.gnu.linkonce.profile_range.*)) - } - .xt.profile_ranges 0 : - { - KEEP (*(.xt.profile_ranges)) - KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) - } - .xt.profile_files 0 : - { - 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)), - "IRAM0 segment data does not fit.") +#endif /* CONFIG_MCUBOOT */ diff --git a/soc/xtensa/esp32/loader.c b/soc/xtensa/esp32/loader.c index d9be772f81e..ed18aa8d02a 100644 --- a/soc/xtensa/esp32/loader.c +++ b/soc/xtensa/esp32/loader.c @@ -14,6 +14,10 @@ #include #ifdef CONFIG_BOOTLOADER_MCUBOOT + +#define BOOT_LOG_INF(_fmt, ...) \ + ets_printf("[" CONFIG_SOC "] [INF] " _fmt "\n\r", ##__VA_ARGS__) + #define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used)) extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr; @@ -78,6 +82,14 @@ static int map_rom_segments(void) DPORT_APP_CACHE_MASK_DRAM1); esp_rom_Cache_Read_Enable(0); + + /* Show map segments continue using same log format as during MCUboot phase */ + BOOT_LOG_INF("DROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map", + _app_drom_start, _app_drom_vaddr, _app_drom_size, _app_drom_size); + BOOT_LOG_INF("IROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map\r\n", + _app_irom_start, _app_irom_vaddr, _app_irom_size, _app_irom_size); + esp_rom_uart_tx_wait_idle(0); + return rc; } #endif diff --git a/soc/xtensa/esp32/mcuboot.ld b/soc/xtensa/esp32/mcuboot.ld new file mode 100644 index 00000000000..a3b2af762dd --- /dev/null +++ b/soc/xtensa/esp32/mcuboot.ld @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the MCUboot on Xtensa platform. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_XIP +#error "Xtensa bootloader cannot use XIP" +#endif /* CONFIG_XIP */ + +/* Disable all romable LMA */ +#undef GROUP_DATA_LINK_IN +#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion + +#define RAMABLE_REGION dram_seg +#define RAMABLE_REGION_1 dram_seg + +#define RODATA_REGION dram_seg +#define ROMABLE_REGION dram_seg + +#define IRAM_REGION iram_seg +#define FLASH_CODE_REGION iram_seg + +#define IROM_SEG_ALIGN 16 + +MEMORY +{ + iram_loader_seg (RWX) : org = 0x40078000, len = 0x4000 + iram_seg (RWX) : org = 0x4009C000, len = 0x8000 + dram_seg (RW) : org = 0x3FFF0000, len = 0x6000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ + /* NOTE: .rodata section should be the first section in the linker script and no + * other section should appear before .rodata section. This is the requirement + * to align ROM section to 64K page offset. + * Adding .rodata as first section helps to reduce size of generated binary by + * few kBs. + */ + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + __rodata_region_start = ABSOLUTE(.); + + . = ALIGN(4); + #include + + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + + .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.*) + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + + .dram0.end : + { + . = ALIGN(4); + #include + . = ALIGN(4); + _end = ABSOLUTE(.); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.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); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram_loader.text : + { + . = ALIGN (16); + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash_config_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_init_common.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) + *libzephyr.a:bootloader_efuse_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_partitions.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libzephyr.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_fields.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api_key_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:app_cpu_start.*(.literal .text .literal.* .text.*) + *esp_mcuboot.*(.literal .text .literal.* .text.*) + *esp_loader.*(.literal .text .literal.* .text.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _loader_text_end = ABSOLUTE(.); + } > iram_loader_seg + + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + + . = ALIGN(4); + _iram_text_end = ABSOLUTE(.); + _iram_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); /* required by bluetooth library */ + __bss_start = ABSOLUTE(.); + + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _btdm_bss_end = ABSOLUTE(.); + + /* Buffer for system heap should be placed in dram_seg */ + *libkernel.a:mempool.*(.noinit.kheap_buf__system_heap .noinit.*.kheap_buf__system_heap) + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + _bss_end = ABSOLUTE(.); + _end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + ASSERT(((__bss_end - ORIGIN(RAMABLE_REGION)) <= LENGTH(RAMABLE_REGION)), + "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) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + _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) + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +} + +ASSERT(((_iram_end - ORIGIN(IRAM_REGION)) <= LENGTH(IRAM_REGION)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32/soc.c b/soc/xtensa/esp32/soc.c index aad04968f0a..cb1e3433fa8 100644 --- a/soc/xtensa/esp32/soc.c +++ b/soc/xtensa/esp32/soc.c @@ -29,9 +29,15 @@ #include "esp_timer.h" #include "esp32/spiram.h" #include "esp_app_format.h" +#include "hal/wdt_hal.h" + #ifndef CONFIG_SOC_ESP32_NET #include "esp_clk_internal.h" -#endif +#endif /* CONFIG_SOC_ESP32_NET */ + +#ifdef CONFIG_MCUBOOT +#include "bootloader_init.h" +#endif /* CONFIG_MCUBOOT */ #include extern void z_cstart(void); @@ -76,7 +82,7 @@ void __attribute__((section(".iram1"))) start_esp32_net_cpu(void) esp_appcpu_start((void *)entry_addr); } -#endif +#endif /* CONFIG_ESP32_NETWORK_CORE */ /* * This is written in C rather than assembly since, during the port bring up, @@ -85,8 +91,6 @@ void __attribute__((section(".iram1"))) start_esp32_net_cpu(void) */ void __attribute__((section(".iram1"))) __esp_platform_start(void) { - volatile uint32_t *wdt_rtc_protect = (uint32_t *)RTC_CNTL_WDTWPROTECT_REG; - volatile uint32_t *wdt_rtc_reg = (uint32_t *)RTC_CNTL_WDTCONFIG0_REG; extern uint32_t _init_start; /* Move the exception vector table to IRAM. */ @@ -115,13 +119,21 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) */ __asm__ volatile("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0])); - /* ESP-IDF/MCUboot 2nd stage bootloader enables RTC WDT to check on startup sequence - * related issues in application. Hence disable that as we are about to start - * Zephyr environment. +#ifdef CONFIG_MCUBOOT + /* MCUboot early initialisation. */ + if (bootloader_init()) { + abort(); + } +#else + /* ESP-IDF/MCUboot 2nd stage bootloader enables RTC WDT to check + * on startup sequence related issues in application. Hence disable that + * as we are about to start Zephyr environment. */ - *wdt_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE; - *wdt_rtc_reg &= ~RTC_CNTL_WDT_EN; - *wdt_rtc_protect = 0; + wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; + + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_disable(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); #ifndef CONFIG_SOC_ESP32_NET /* Configures the CPU clock, RTC slow and fast clocks, and performs @@ -161,6 +173,9 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) #if CONFIG_SOC_FLASH_ESP32 || CONFIG_ESP_SPIRAM spi_flash_guard_set(&g_flash_guard_default_ops); #endif + +#endif /* CONFIG_MCUBOOT */ + esp_intr_initialize(); /* Start Zephyr */ diff --git a/soc/xtensa/esp32s2/CMakeLists.txt b/soc/xtensa/esp32s2/CMakeLists.txt index e356dcb165d..c520dabda27 100644 --- a/soc/xtensa/esp32s2/CMakeLists.txt +++ b/soc/xtensa/esp32s2/CMakeLists.txt @@ -61,14 +61,6 @@ if(CONFIG_BOOTLOADER_ESP_IDF) INSTALL_COMMAND "" ) - if(CONFIG_BUILD_OUTPUT_BIN) - set_property(GLOBAL APPEND PROPERTY extra_post_build_commands - COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py - ARGS --chip esp32s2 elf2image --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() - set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) add_dependencies(app EspIdfBootloader EspPartitionTable) @@ -81,6 +73,22 @@ if(CONFIG_BOOTLOADER_ESP_IDF) endif() +if(CONFIG_MCUBOOT OR CONFIG_BOOTLOADER_ESP_IDF) + + if(CONFIG_BUILD_OUTPUT_BIN) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py + ARGS --chip esp32s2 elf2image --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() + + if(CONFIG_MCUBOOT) + board_finalize_runner_args(esp32 "--esp-flash-bootloader=${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin") + endif() + +endif() + board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") diff --git a/soc/xtensa/esp32s2/Kconfig.soc b/soc/xtensa/esp32s2/Kconfig.soc index cf6ae79222d..f9d77cc1f5d 100644 --- a/soc/xtensa/esp32s2/Kconfig.soc +++ b/soc/xtensa/esp32s2/Kconfig.soc @@ -8,7 +8,7 @@ config SOC_ESP32S2 select DYNAMIC_INTERRUPTS select CLOCK_CONTROL select PINCTRL - select XIP + select XIP if !MCUBOOT select HAS_ESPRESSIF_HAL if SOC_ESP32S2 diff --git a/soc/xtensa/esp32s2/default.ld b/soc/xtensa/esp32s2/default.ld new file mode 100644 index 00000000000..7aff462873b --- /dev/null +++ b/soc/xtensa/esp32s2/default.ld @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the esp32s2 platform. + */ + +#include +#include +#include +#include + +#define RAM_IRAM_START 0x40020000 +#define RAM_DRAM_START 0x3ffb0000 + +#define DATA_RAM_END 0x40000000 + +#define IRAM_ORG (RAM_IRAM_START + CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE \ + + CONFIG_ESP32S2_DATA_CACHE_SIZE) + +#define DRAM_ORG (RAM_DRAM_START + CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE \ + + CONFIG_ESP32S2_DATA_CACHE_SIZE) + +#define I_D_RAM_SIZE DATA_RAM_END - DRAM_ORG + +#define RAMABLE_REGION dram0_0_seg +#define RODATA_REGION drom0_0_seg +#define IRAM_REGION iram0_0_seg +#define FLASH_CODE_REGION irom0_0_seg + +#define ROMABLE_REGION ROM + +#ifdef CONFIG_FLASH_SIZE +#define FLASH_SIZE CONFIG_FLASH_SIZE +#else +#define FLASH_SIZE 0x400000 +#endif + +#ifdef CONFIG_BOOTLOADER_ESP_IDF +#define IROM_SEG_ORG 0x40080020 +#define IROM_SEG_LEN (FLASH_SIZE-0x20) +#define IROM_SEG_ALIGN 0x4 +#else +#define IROM_SEG_ORG 0x40080000 +#define IROM_SEG_LEN FLASH_SIZE +#define IROM_SEG_ALIGN 0x10000 +#endif + +MEMORY +{ + mcuboot_hdr (RX): org = 0x0, len = 0x20 + metadata (RX): org = 0x20, len = 0x20 + ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 + iram0_0_seg(RX): org = IRAM_ORG, len = I_D_RAM_SIZE + irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN + dram0_0_seg(RW): org = DRAM_ORG, len = I_D_RAM_SIZE + drom0_0_seg(R): org = 0x3f000040, len = FLASH_SIZE - 0x40 + + rtc_iram_seg(RWX): org = 0x40070000, len = 0x2000 + rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 +#if defined(CONFIG_ESP_SPIRAM) + ext_ram_seg(RW): org = 0x3f500000, len = CONFIG_ESP_SPIRAM_SIZE +#endif +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +_rom_store_table = 0; + +_heap_sentry = 0x3fffe710; + +SECTIONS +{ + /* Reserve space for MCUboot header in the binary */ + .mcuboot_header : + { + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + } > mcuboot_hdr + .metadata : + { + /* Magic byte for load header */ + LONG(0xace637d3) + + /* Application entry point address */ + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * - Destination address (VMA) for IRAM region + * - Flash offset (LMA) for start of IRAM region + * - Size of IRAM region + */ + LONG(ADDR(.iram0.vectors)) + LONG(LOADADDR(.iram0.vectors)) + LONG(LOADADDR(.iram0.text) + SIZEOF(.iram0.text) - LOADADDR(.iram0.vectors)) + + /* DRAM metadata: + * - Destination address (VMA) for DRAM region + * - Flash offset (LMA) for start of DRAM region + * - Size of DRAM region + */ + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(LOADADDR(.dummy.dram.data) + SIZEOF(.dummy.dram.data) - LOADADDR(.dram0.data)) + } > metadata + +#include + _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); + + /* NOTE: .rodata section should be the first section in the linker script and no + * other section should appear before .rodata section. This is the requirement + * to align ROM section to 64K page offset. + * Adding .rodata as first section helps to reduce size of generated binary by + * few kBs. + */ + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(4)) + { + __rodata_region_start = ABSOLUTE(.); + + . = ALIGN(4); + #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.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + _rodata_reserved_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + #include + #include + #include + #include + #include + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + /* 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,,ALIGN(0x10)) + { + . = ALIGN(4); + _image_rodata_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + + /* Send .iram0 code to iram */ + .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 */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.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 */ + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram0.text : ALIGN(4) + { + . = ALIGN(8); + /* Code marked as running out of IRAM */ + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *libesp32.a:panic.*(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) + *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) + *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) + *libsubsys__net.a:(.literal .text .literal.* .text.*) + *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) + *libkernel.a:(.literal .text .literal.* .text.*) + *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) + *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) + *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) + *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) + *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) + *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) + *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *libzephyr.a:loader.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) + *libc.a:*(.literal .text .literal.* .text.*) + *libphy.a:( .phyiram .phyiram.*) + *libgcov.a:(.literal .text .literal.* .text.*) + +#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) +#endif + +#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + /* align + add 16B for CPU dummy speculative instr. fetch */ + . = ALIGN(4) + 16; + _iram_text = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .dram0.dummy (NOLOAD): + { + /** + * This section is required to skip .iram0.text area because iram0_0_seg and + * dram0_0_seg reflect the same address space on different buses. + */ + . = ALIGN (8); + . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; + } GROUP_LINK_IN(RAMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + __bss_start = ABSOLUTE(.); + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + +#if defined(CONFIG_ESP_SPIRAM) + .ext_ram.bss (NOLOAD): + { + _ext_ram_bss_start = ABSOLUTE(.); + +#if defined(CONFIG_ESP32_WIFI_NET_ALLOC_SPIRAM) + *libdrivers__wifi.a:(.noinit .noinit.*) + *libsubsys__net__l2__ethernet.a:(.noinit .noinit.*) + *libsubsys__net__lib__config.a:(.noinit .noinit.*) + *libsubsys__net__ip.a:(.noinit .noinit.*) + *libsubsys__net.a:(.noinit .noinit.*) +#endif + + *(.ext_ram.bss*) + . = ALIGN(4); + _ext_ram_bss_end = ABSOLUTE(.) + CONFIG_ESP_SPIRAM_SIZE; + } > ext_ram_seg +#endif + + SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) + { + . = ALIGN(8); + *(.noinit) + *(.noinit.*) + . = ALIGN(8); + } GROUP_LINK_IN(RAMABLE_REGION) + +#include + + .dram0.data : + { + . = ALIGN (8); + __data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + /* rodata for panic handler(libarch__xtensa__core.a) and all + * dependent functions should be placed in DRAM to avoid issue + * when flash cache is disabled */ + *libarch__xtensa__core.a:(.rodata .rodata.*) + *libkernel.a:fatal.*(.rodata .rodata.*) + *libkernel.a:init.*(.rodata .rodata.*) + *libzephyr.a:cbprintf_complete*(.rodata .rodata.*) + *libzephyr.a: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_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") + + .dummy.dram.data : + { + . = ALIGN(4); + #include + . = ALIGN(4); + _end = ABSOLUTE(.); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + .iram0.text_end (NOLOAD) : + { + . = ALIGN(4); + _iram_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + _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_dummy (NOLOAD): ALIGN(IROM_SEG_ALIGN) + { + . = ALIGN(4); + . = SIZEOF(_RODATA_SECTION_NAME); + } GROUP_LINK_IN(FLASH_CODE_REGION) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + . = ALIGN(8); + _stext = .; + _text_start = ABSOLUTE(.); + +#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) +#endif + + . = ALIGN(8); +#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + . = ALIGN(8); + *(.literal .text .literal.* .text.*) + . = ALIGN(8); + _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) + + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + /* RTC slow memory holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(rtc_slow_seg) + + /* This section located in RTC SLOW Memory area. + It holds data marked with RTC_SLOW_ATTR attribute. + See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Get size of rtc slow data */ + _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } +} + +ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), + "DRAM0 segment data does not fit.") + +ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32s2/linker.ld b/soc/xtensa/esp32s2/linker.ld index 3313fb7cc9c..dc2d891834e 100644 --- a/soc/xtensa/esp32s2/linker.ld +++ b/soc/xtensa/esp32s2/linker.ld @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. * SPDX-License-Identifier: Apache-2.0 */ @@ -7,545 +7,14 @@ * @file * @brief Linker command/script file * - * Linker script for the esp32s2 platform. */ -#include -#include -#include -#include +#if defined(CONFIG_MCUBOOT) + /* Using mcuboot as ESP32S2 2nd stage bootloader */ + #include "mcuboot.ld" -#define RAM_IRAM_START 0x40020000 -#define RAM_DRAM_START 0x3ffb0000 - -#define DATA_RAM_END 0x3ffe0000 /* 2nd stage bootloader iram_loader_seg - * starts at SRAM block 14 (reclaimed after - * app boots) - */ - -#define IRAM_ORG (RAM_IRAM_START + CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE \ - + CONFIG_ESP32S2_DATA_CACHE_SIZE) - -#define DRAM_ORG (RAM_DRAM_START + CONFIG_ESP32S2_INSTRUCTION_CACHE_SIZE \ - + CONFIG_ESP32S2_DATA_CACHE_SIZE) - -#define I_D_RAM_SIZE DATA_RAM_END - DRAM_ORG - -#define RAMABLE_REGION dram0_0_seg -#define RODATA_REGION drom0_0_seg -#define IRAM_REGION iram0_0_seg -#define FLASH_CODE_REGION irom0_0_seg - -#define ROMABLE_REGION ROM - -#ifdef CONFIG_FLASH_SIZE -#define FLASH_SIZE CONFIG_FLASH_SIZE #else -#define FLASH_SIZE 0x400000 -#endif + /* Application default linker script */ + #include "default.ld" -#ifdef CONFIG_BOOTLOADER_ESP_IDF -#define IROM_SEG_ORG 0x40080020 -#define IROM_SEG_LEN (FLASH_SIZE-0x20) -#define IROM_SEG_ALIGN 0x4 -#else -#define IROM_SEG_ORG 0x40080000 -#define IROM_SEG_LEN FLASH_SIZE -#define IROM_SEG_ALIGN 0x10000 -#endif - -MEMORY -{ - mcuboot_hdr (RX): org = 0x0, len = 0x20 - metadata (RX): org = 0x20, len = 0x20 - ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 - iram0_0_seg(RX): org = IRAM_ORG, len = I_D_RAM_SIZE - irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN - dram0_0_seg(RW): org = DRAM_ORG, len = I_D_RAM_SIZE - drom0_0_seg(R): org = 0x3f000040, len = FLASH_SIZE - 0x40 - - rtc_iram_seg(RWX): org = 0x40070000, len = 0x2000 - rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 -#if defined(CONFIG_ESP_SPIRAM) - ext_ram_seg(RW): org = 0x3f500000, len = CONFIG_ESP_SPIRAM_SIZE -#endif -#ifdef CONFIG_GEN_ISR_TABLES - IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 -#endif -} - -/* Default entry point: */ -ENTRY(CONFIG_KERNEL_ENTRY) - -_rom_store_table = 0; - -_heap_sentry = 0x3fffe710; - -SECTIONS -{ - /* Reserve space for MCUboot header in the binary */ - .mcuboot_header : - { - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - } > mcuboot_hdr - .metadata : - { - /* Magic byte for load header */ - LONG(0xace637d3) - - /* Application entry point address */ - KEEP(*(.entry_addr)) - - /* IRAM metadata: - * - Destination address (VMA) for IRAM region - * - Flash offset (LMA) for start of IRAM region - * - Size of IRAM region - */ - LONG(ADDR(.iram0.vectors)) - LONG(LOADADDR(.iram0.vectors)) - LONG(LOADADDR(.iram0.text) + SIZEOF(.iram0.text) - LOADADDR(.iram0.vectors)) - - /* DRAM metadata: - * - Destination address (VMA) for DRAM region - * - Flash offset (LMA) for start of DRAM region - * - Size of DRAM region - */ - LONG(ADDR(.dram0.data)) - LONG(LOADADDR(.dram0.data)) - LONG(LOADADDR(.dummy.dram.data) + SIZEOF(.dummy.dram.data) - LOADADDR(.dram0.data)) - } > metadata - -#include - _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); - - /* NOTE: .rodata section should be the first section in the linker script and no - * other section should appear before .rodata section. This is the requirement - * to align ROM section to 64K page offset. - * Adding .rodata as first section helps to reduce size of generated binary by - * few kBs. - */ - SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) - { - __rodata_region_start = ABSOLUTE(.); - - . = ALIGN(4); - #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.*) - - . = ALIGN(4); - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 3) & ~ 3; - __eh_frame = ABSOLUTE(.); - KEEP(*(.eh_frame)) - . = (. + 7) & ~ 3; - - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - __rodata_region_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - *(.rodata_wlog) - *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN(4); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion - #include - #include - #include - #include - #include - #include - #include - #pragma pop_macro("GROUP_ROM_LINK_IN") - - /* 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,,) - { - . = ALIGN(4); - _image_rodata_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - - /* Send .iram0 code to iram */ - .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 */ - . = 0x0; - KEEP(*(.WindowVectors.text)); - . = 0x180; - KEEP(*(.Level2InterruptVector.text)); - . = 0x1c0; - KEEP(*(.Level3InterruptVector.text)); - . = 0x200; - KEEP(*(.Level4InterruptVector.text)); - . = 0x240; - KEEP(*(.Level5InterruptVector.text)); - . = 0x280; - KEEP(*(.DebugExceptionVector.text)); - . = 0x2c0; - KEEP(*(.NMIExceptionVector.text)); - . = 0x300; - KEEP(*(.KernelExceptionVector.text)); - . = 0x340; - KEEP(*(.UserExceptionVector.text)); - . = 0x3C0; - KEEP(*(.DoubleExceptionVector.text)); - . = 0x400; - *(.*Vector.literal) - - *(.UserEnter.literal); - *(.UserEnter.text); - . = ALIGN (16); - *(.entry.text) - *(.init.literal) - *(.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 */ - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - .iram0.text : ALIGN(4) - { - /* Code marked as running out of IRAM */ - *(.iram1 .iram1.*) - *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) - *libesp32.a:panic.*(.literal .text .literal.* .text.*) - *librtc.a:(.literal .text .literal.* .text.*) - *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) - *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) - *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) - *libsubsys__net.a:(.literal .text .literal.* .text.*) - *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) - *libkernel.a:(.literal .text .literal.* .text.*) - *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) - *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) - *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) - *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) - *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) - *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) - *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) - *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) - *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) - *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) - *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) - *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) - *libzephyr.a:loader.*(.literal .text .literal.* .text.*) - *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) - *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) - *libc.a:*(.literal .text .literal.* .text.*) - *libphy.a:( .phyiram .phyiram.*) - *libgcov.a:(.literal .text .literal.* .text.*) - -#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) -#endif - -#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - /* align + add 16B for CPU dummy speculative instr. fetch */ - . = ALIGN(4) + 16; - _iram_text = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - .dram0.dummy (NOLOAD): - { - /** - * This section is required to skip .iram0.text area because iram0_0_seg and - * dram0_0_seg reflect the same address space on different buses. - */ - . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; - } GROUP_LINK_IN(RAMABLE_REGION) - - /* Shared RAM */ - SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) - { - . = ALIGN (8); - __bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.share.mem) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - __bss_end = ABSOLUTE(.); - } GROUP_LINK_IN(RAMABLE_REGION) - -#if defined(CONFIG_ESP_SPIRAM) - .ext_ram.bss (NOLOAD): - { - _ext_ram_bss_start = ABSOLUTE(.); - -#if defined(CONFIG_ESP32_WIFI_NET_ALLOC_SPIRAM) - *libdrivers__wifi.a:(.noinit .noinit.*) - *libsubsys__net__l2__ethernet.a:(.noinit .noinit.*) - *libsubsys__net__lib__config.a:(.noinit .noinit.*) - *libsubsys__net__ip.a:(.noinit .noinit.*) - *libsubsys__net.a:(.noinit .noinit.*) -#endif - - *(.ext_ram.bss*) - . = ALIGN(4); - _ext_ram_bss_end = ABSOLUTE(.) + CONFIG_ESP_SPIRAM_SIZE; - } > ext_ram_seg -#endif - - SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) - { - . = ALIGN(8); - *(.noinit) - *(.noinit.*) - . = ALIGN(8); - } GROUP_LINK_IN(RAMABLE_REGION) - -#include - - .dram0.data : - { - __data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - /* rodata for panic handler(libarch__xtensa__core.a) and all - * dependent functions should be placed in DRAM to avoid issue - * when flash cache is disabled */ - *libarch__xtensa__core.a:(.rodata .rodata.*) - *libkernel.a:fatal.*(.rodata .rodata.*) - *libkernel.a:init.*(.rodata .rodata.*) - *libzephyr.a:cbprintf_complete*(.rodata .rodata.*) - *libzephyr.a: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_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") - - .dummy.dram.data : - { - . = ALIGN(4); - #include - . = ALIGN(4); - _end = ABSOLUTE(.); - __data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - .iram0.text_end (NOLOAD) : - { - . = ALIGN(4); - _iram_end = ABSOLUTE(.); - } GROUP_LINK_IN(IRAM_REGION) - - _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_dummy (NOLOAD): ALIGN(IROM_SEG_ALIGN) - { - . = SIZEOF(_RODATA_SECTION_NAME); - } GROUP_LINK_IN(FLASH_CODE_REGION) - - .flash.text : ALIGN(IROM_SEG_ALIGN) - { - _stext = .; - _text_start = ABSOLUTE(.); - -#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) -#endif - -#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - *(.literal .text .literal.* .text.*) - _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) - - /* RTC fast memory holds RTC wake stub code, - including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - . = ALIGN(4); - *(.rtc.literal .rtc.text) - *rtc_wake_stub*.o(.literal .text .literal.* .text.*) - } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) - - /* RTC slow memory holds RTC wake stub - data/rodata, including from any source file - named rtc_wake_stub*.c - */ - .rtc.data : - { - _rtc_data_start = ABSOLUTE(.); - *(.rtc.data) - *(.rtc.rodata) - *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) - _rtc_data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - *rtc_wake_stub*.o(.bss .bss.*) - *rtc_wake_stub*.o(COMMON) - _rtc_bss_end = ABSOLUTE(.); - } GROUP_LINK_IN(rtc_slow_seg) - - /* This section located in RTC SLOW Memory area. - It holds data marked with RTC_SLOW_ATTR attribute. - See the file "esp_attr.h" for more information. - */ - .rtc.force_slow : - { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); - *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); - } > rtc_slow_seg - - /* Get size of rtc slow data */ - _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); - -#ifdef CONFIG_GEN_ISR_TABLES -#include -#endif - -#include - - .xtensa.info 0 : { *(.xtensa.info) } - .xt.insn 0 : - { - KEEP (*(.xt.insn)) - KEEP (*(.gnu.linkonce.x.*)) - } - .xt.prop 0 : - { - KEEP (*(.xt.prop)) - KEEP (*(.xt.prop.*)) - KEEP (*(.gnu.linkonce.prop.*)) - } - .xt.lit 0 : - { - KEEP (*(.xt.lit)) - KEEP (*(.xt.lit.*)) - KEEP (*(.gnu.linkonce.p.*)) - } - .xt.profile_range 0 : - { - KEEP (*(.xt.profile_range)) - KEEP (*(.gnu.linkonce.profile_range.*)) - } - .xt.profile_ranges 0 : - { - KEEP (*(.xt.profile_ranges)) - KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) - } - .xt.profile_files 0 : - { - KEEP (*(.xt.profile_files)) - KEEP (*(.gnu.linkonce.xt.profile_files.*)) - } -} - -ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), - "DRAM0 segment data does not fit.") - -ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), - "IRAM0 segment data does not fit.") +#endif /* CONFIG_MCUBOOT */ diff --git a/soc/xtensa/esp32s2/loader.c b/soc/xtensa/esp32s2/loader.c index 6f55149c180..b42e68a6598 100644 --- a/soc/xtensa/esp32s2/loader.c +++ b/soc/xtensa/esp32s2/loader.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ - #include #include #include @@ -17,6 +16,10 @@ #include #ifdef CONFIG_BOOTLOADER_MCUBOOT + +#define BOOT_LOG_INF(_fmt, ...) \ + ets_printf("[" CONFIG_SOC "] [INF] " _fmt "\n\r", ##__VA_ARGS__) + #define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used)) extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr; @@ -71,6 +74,13 @@ static int map_rom_segments(void) esp_rom_Cache_Resume_ICache(autoload); + /* Show map segments continue using same log format as during MCUboot phase */ + BOOT_LOG_INF("DROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map", + _app_drom_start, _app_drom_vaddr, _app_drom_size, _app_drom_size); + BOOT_LOG_INF("IROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map\r\n", + _app_irom_start, _app_irom_vaddr, _app_irom_size, _app_irom_size); + esp_rom_uart_tx_wait_idle(0); + return rc; } #endif diff --git a/soc/xtensa/esp32s2/mcuboot.ld b/soc/xtensa/esp32s2/mcuboot.ld new file mode 100644 index 00000000000..6d52100db75 --- /dev/null +++ b/soc/xtensa/esp32s2/mcuboot.ld @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the MCUboot on Xtensa platform. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_XIP +#error "Xtensa bootloader cannot use XIP" +#endif /* CONFIG_XIP */ + +/* Disable all romable LMA */ +#udef GROUP_DATA_LINK_IN +#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion + +#define RAMABLE_REGION dram_seg +#define RAMABLE_REGION_1 dram_seg + +#define RODATA_REGION dram_seg +#define ROMABLE_REGION dram_seg + +#define IRAM_REGION iram_seg +#define FLASH_CODE_REGION iram_seg + +#define IROM_SEG_ALIGN 16 + +MEMORY +{ + iram_seg (RWX) : org = 0x40040000, len = 0x6000 + iram_loader_seg (RWX) : org = 0x40046000, len = 0x2000 + dram_seg (RW) : org = 0x3FFE6000, len = 0x6000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif + +} + +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ + /* NOTE: .rodata section should be the first section in the linker script and no + * other section should appear before .rodata section. This is the requirement + * to align ROM section to 64K page offset. + * Adding .rodata as first section helps to reduce size of generated binary by + * few kBs. + */ + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) + { + __rodata_region_start = ABSOLUTE(.); + + . = ALIGN(4); + #include + + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + #include + #include + + .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.*) + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + + .dram0.end : + { + . = ALIGN(4); + #include + . = ALIGN(4); + _end = ABSOLUTE(.); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.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); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram_loader.text : + { + . = ALIGN (16); + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash_config_esp32s2.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_init_common.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) + *libzephyr.a:bootloader_efuse_esp32s2.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_partitions.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libzephyr.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_fields.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api_key_esp32xx.*(.literal .text .literal.* .text.*) + *esp_mcuboot.*(.literal .text .literal.* .text.*) + *esp_loader.*(.literal .text .literal.* .text.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _loader_text_end = ABSOLUTE(.); + } > iram_loader_seg + + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + + . = ALIGN(4); + _iram_text_end = ABSOLUTE(.); + _iram_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); /* required by bluetooth library */ + __bss_start = ABSOLUTE(.); + + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _btdm_bss_end = ABSOLUTE(.); + + /* Buffer for system heap should be placed in dram_seg */ + *libkernel.a:mempool.*(.noinit.kheap_buf__system_heap .noinit.*.kheap_buf__system_heap) + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + _bss_end = ABSOLUTE(.); + _end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + ASSERT(((__bss_end - ORIGIN(RAMABLE_REGION)) <= LENGTH(RAMABLE_REGION)), + "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) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + _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) + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +} + +ASSERT(((_iram_end - ORIGIN(IRAM_REGION)) <= LENGTH(IRAM_REGION)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32s2/soc.c b/soc/xtensa/esp32s2/soc.c index e6faecb13c7..9fc9701db52 100644 --- a/soc/xtensa/esp32s2/soc.c +++ b/soc/xtensa/esp32s2/soc.c @@ -25,12 +25,17 @@ #include "esp_cpu.h" #include "hal/cpu_ll.h" #include "hal/soc_ll.h" +#include "hal/wdt_hal.h" #include "esp_timer.h" #include "esp_err.h" #include "esp32s2/spiram.h" #include "esp_clk_internal.h" #include +#ifdef CONFIG_MCUBOOT +#include "bootloader_init.h" +#endif /* CONFIG_MCUBOOT */ + extern void rtc_clk_cpu_freq_set_xtal(void); #if CONFIG_ESP_SPIRAM @@ -45,8 +50,6 @@ extern int _ext_ram_bss_end; */ void __attribute__((section(".iram1"))) __esp_platform_start(void) { - volatile uint32_t *wdt_rtc_protect = (uint32_t *)RTC_CNTL_WDTWPROTECT_REG; - volatile uint32_t *wdt_rtc_reg = (uint32_t *)RTC_CNTL_WDTCONFIG0_REG; extern uint32_t _init_start; /* Move the exception vector table to IRAM. */ @@ -88,13 +91,21 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) */ __asm__ volatile("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0])); +#ifdef CONFIG_MCUBOOT + /* MCUboot early initialisation. */ + if (bootloader_init()) { + abort(); + } +#else /* ESP-IDF 2nd stage bootloader enables RTC WDT to check on startup sequence * related issues in application. Hence disable that as we are about to start * Zephyr environment. */ - *wdt_rtc_protect = RTC_CNTL_WDT_WKEY_VALUE; - *wdt_rtc_reg &= ~RTC_CNTL_WDT_EN; - *wdt_rtc_protect = 0; + wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; + + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_disable(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); /* Configures the CPU clock, RTC slow and fast clocks, and performs * RTC slow clock calibration. @@ -131,6 +142,9 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) #if CONFIG_SOC_FLASH_ESP32 || CONFIG_ESP_SPIRAM spi_flash_guard_set(&g_flash_guard_default_ops); #endif + +#endif /* CONFIG_MCUBOOT */ + esp_intr_initialize(); /* Start Zephyr */ z_cstart(); diff --git a/soc/xtensa/esp32s2/soc_cache.c b/soc/xtensa/esp32s2/soc_cache.c index 1eec2318ed1..658d0a5988a 100644 --- a/soc/xtensa/esp32s2/soc_cache.c +++ b/soc/xtensa/esp32s2/soc_cache.c @@ -49,7 +49,6 @@ void IRAM_ATTR esp_config_instruction_cache_mode(void) esp_rom_Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID); #endif - cache_size = ESP32S2_ICACHE_SIZE; cache_ways = CACHE_4WAYS_ASSOC; cache_line_size = ESP32S2_ICACHE_LINE_SIZE; diff --git a/soc/xtensa/esp32s3/CMakeLists.txt b/soc/xtensa/esp32s3/CMakeLists.txt index 2feca8a7e74..70cc633e764 100644 --- a/soc/xtensa/esp32s3/CMakeLists.txt +++ b/soc/xtensa/esp32s3/CMakeLists.txt @@ -2,6 +2,7 @@ zephyr_sources( soc.c + soc_cache.c loader.c ) @@ -58,14 +59,6 @@ if(CONFIG_BOOTLOADER_ESP_IDF) INSTALL_COMMAND "" ) - if(CONFIG_BUILD_OUTPUT_BIN) - set_property(GLOBAL APPEND PROPERTY extra_post_build_commands - COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py - ARGS --chip esp32s3 elf2image --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() - set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) add_dependencies(app EspIdfBootloader EspPartitionTable) @@ -78,6 +71,24 @@ if(CONFIG_BOOTLOADER_ESP_IDF) endif() +if(CONFIG_MCUBOOT OR CONFIG_BOOTLOADER_ESP_IDF) + + if(CONFIG_BUILD_OUTPUT_BIN) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/components/esptool_py/esptool/esptool.py + ARGS --chip esp32s3 elf2image --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() + + if(CONFIG_MCUBOOT) + board_finalize_runner_args(esp32 "--esp-flash-bootloader=${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin") + endif() + +endif() + +set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) + board_finalize_runner_args(esp32 "--esp-boot-address=${boot_off}") board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") diff --git a/soc/xtensa/esp32s3/Kconfig.soc b/soc/xtensa/esp32s3/Kconfig.soc index 31a595b0e36..3860bea328b 100644 --- a/soc/xtensa/esp32s3/Kconfig.soc +++ b/soc/xtensa/esp32s3/Kconfig.soc @@ -8,7 +8,7 @@ config SOC_ESP32S3 select DYNAMIC_INTERRUPTS select ARCH_SUPPORTS_COREDUMP select PINCTRL - select XIP + select XIP if !MCUBOOT select HAS_ESPRESSIF_HAL select CPU_HAS_FPU diff --git a/soc/xtensa/esp32s3/default.ld b/soc/xtensa/esp32s3/default.ld new file mode 100644 index 00000000000..d4996cef2a5 --- /dev/null +++ b/soc/xtensa/esp32s3/default.ld @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file + * + * Linker script for the ESP32S3 platform. + */ + +#include +#include +#include +#include + +#define SRAM_IRAM_START 0x40370000 +#define SRAM_DIRAM_I_START 0x40378000 +#define SRAM_IRAM_END 0x403BA000 +#define I_D_SRAM_OFFSET (SRAM_DIRAM_I_START - SRAM_DRAM_START) + +#define SRAM_DRAM_START 0x3FC88000 +#define SRAM_DRAM_END (SRAM_IRAM_END - I_D_SRAM_OFFSET) +#define I_D_SRAM_SIZE (SRAM_DRAM_END - SRAM_DRAM_START) + +#define ICACHE_SIZE 0x8000 +#define SRAM_IRAM_ORG (SRAM_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) +#define SRAM_IRAM_SIZE (I_D_SRAM_SIZE + ICACHE_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) + +#define DCACHE_SIZE 0x10000 +#define SRAM_DRAM_ORG (SRAM_DRAM_START) + +#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE + +#define FLASH_CODE_REGION irom0_0_seg +#define RODATA_REGION drom0_0_seg +#define IRAM_REGION iram0_0_seg +#define RAMABLE_REGION dram0_0_seg +#define ROMABLE_REGION ROM + +#ifdef CONFIG_FLASH_SIZE +#define FLASH_SIZE CONFIG_FLASH_SIZE +#else +#define FLASH_SIZE 0x800000 +#endif + +#ifdef CONFIG_BOOTLOADER_ESP_IDF + +#define IROM_SEG_ORG 0x42000020 +#define IROM_SEG_LEN FLASH_SIZE-0x20 +#define IROM_SEG_ALIGN 0x4 + +#else + +#define IROM_SEG_ORG 0x42000000 +#define IROM_SEG_LEN FLASH_SIZE +#define IROM_SEG_ALIGN 0x10000 + +#endif + +MEMORY +{ + mcuboot_hdr (RX): org = 0x0, len = 0x20 + metadata (RX): org = 0x20, len = 0x20 + ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 + iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE + irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN + dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN + + /* DROM is the first segment placed in generated binary. + * MCUboot binary for ESP32 has image header of 0x20 bytes. + * Additional load header of 0x20 bytes are appended to the image. + * Hence, an offset of 0x40 is added to DROM segment origin. + */ + drom0_0_seg(R): org = 0x3C000040, len = FLASH_SIZE - 0x40 + + /* RTC fast memory (executable). Persists over deep sleep. + */ + rtc_iram_seg(RWX): org = 0x600fe000, len = 0x2000 + + /* RTC fast memory (same block as above), viewed from data bus + */ + rtc_data_seg(RW): org = 0x600fe000, len = 0x2000 + + /* RTC slow memory (data accessible). Persists over deep sleep. + */ + rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ + /* Reserve space for MCUboot header in the binary */ + .mcuboot_header : + { + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + } > mcuboot_hdr + .metadata : + { + /* Magic byte for load header */ + LONG(0xace637d3) + + /* Application entry point address */ + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * - Destination address (VMA) for IRAM region + * - Flash offset (LMA) for start of IRAM region + * - Size of IRAM region + */ + LONG(ADDR(.iram0.vectors)) + LONG(LOADADDR(.iram0.vectors)) + LONG(LOADADDR(.iram0.text) + SIZEOF(.iram0.text) - LOADADDR(.iram0.vectors)) + + /* DRAM metadata: + * - Destination address (VMA) for DRAM region + * - Flash offset (LMA) for start of DRAM region + * - Size of DRAM region + */ + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - LOADADDR(.dram0.data)) + } > metadata + + #include + + _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); + + /* NOTE: .rodata section should be the first section in the linker script and no + * other section should appear before .rodata section. This is the requirement + * to align ROM section to 64K page offset. + * Adding .rodata as first section helps to reduce size of generated binary by + * few kBs. + */ + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(0x10)) + { + _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(4); + #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.* *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.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + _rodata_reserved_end = ABSOLUTE(.); + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. + * Executing directly from LMA is not possible. */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion + #include + #include + #include + #include + #include + #include + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + /* 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,,ALIGN(0x10)) + { + . = ALIGN(16); + _image_rodata_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + /* Send .iram0 code to iram */ + .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 */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + _invalid_pc_placeholder = ABSOLUTE(.); + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram0.text : ALIGN(4) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *libesp32.a:panic.*(.literal .text .literal.* .text.*) + *librtc.a:(.literal .text .literal.* .text.*) + *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) + *libkernel.a:(.literal .text .literal.* .text.*) + *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) + *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) + *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) + *libzephyr.a:systimer_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) + *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) + *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) + *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *libzephyr.a:loader.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) + *libc.a:*(.literal .text .literal.* .text.*) + *libphy.a:(.phyiram .phyiram.*) + *libgcov.a:(.literal .text .literal.* .text.*) + +#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) +#endif + +#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + . = ALIGN(4) + 16; + + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + /* Marks the end of IRAM code segment */ + .iram0.text_end (NOLOAD) : + { + /* ESP32-S3 memprot requires 16B padding for possible CPU + * prefetch and 256B alignment for PMS split lines */ + . = ALIGN(16); + _iram_text_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + .iram0.data : + { + . = ALIGN(16); + *(.iram.data) + *(.iram.data*) + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram0.bss (NOLOAD) : + { + . = ALIGN(16); + *(.iram.bss) + *(.iram.bss*) + + . = ALIGN(16); + _iram_end = ABSOLUTE(.); + } GROUP_LINK_IN(IRAM_REGION) + + + /* This section is required to skip .iram0.text area because iram0_0_seg and + * dram0_0_seg reflect the same address space on different buses. + */ + .dram0.dummy (NOLOAD): + { + . = ALIGN (8); + . = ORIGIN(dram0_0_seg) + MAX(_iram_end, SRAM_DIRAM_I_START) - SRAM_DIRAM_I_START; + } GROUP_LINK_IN(RAMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); /* required by bluetooth library */ + __bss_start = ABSOLUTE(.); + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_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) + +#include + + .dram0.data : + { + . = ALIGN (8); + __data_start = ABSOLUTE(.); + + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + /* rodata for panic handler(libarch__xtensa__core.a) and all + * dependent functions should be placed in DRAM to avoid issue + * when flash cache is disabled */ + *libarch__xtensa__core.a:(.rodata .rodata.*) + *libkernel.a:fatal.*(.rodata .rodata.*) + *libkernel.a:init.*(.rodata .rodata.*) + *libzephyr.a:cbprintf_complete*(.rodata .rodata.*) + *libzephyr.a:systimer_hal.*(.rodata .rodata.*) + *libzephyr.a:log_core.*(.rodata .rodata.*) + *libzephyr.a:log_backend_uart.*(.rodata .rodata.*) + *libzephyr.a:log_output.*(.rodata .rodata.*) + *libzephyr.a:loader.*(.rodata .rodata.*) + *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*) + *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*) + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_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); + _end = ABSOLUTE(.); + _heap_sentry = .; + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + _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_dummy (NOLOAD): ALIGN(IROM_SEG_ALIGN) + { + . = SIZEOF(_RODATA_SECTION_NAME); + . = ALIGN(IROM_SEG_ALIGN) + 0x20; + _rodata_reserved_start = .; + } GROUP_LINK_IN(FLASH_CODE_REGION) + + .flash.text : ALIGN(IROM_SEG_ALIGN) + { + _stext = .; + _text_start = ABSOLUTE(.); + +#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) +#endif + +#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif + + *(.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. + */ + _flash_cache_start = ABSOLUTE(0); + } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) + + /* RTC fast memory holds RTC wake stub code, + * including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + _rtc_text_start = ABSOLUTE(.); + *(.rtc.literal .rtc.text) + *(.rtc.entry.text) + *rtc_wake_stub*.*(.literal .text .literal.* .text.*) + _rtc_text_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + /* This section is required to skip rtc.text area because rtc_iram_seg and + * rtc_data_seg are reflect the same address space on different buses. + */ + .rtc.dummy : + { + _rtc_dummy_start = ABSOLUTE(.); + _rtc_fast_start = ABSOLUTE(.); + . = SIZEOF(.rtc.text); + _rtc_dummy_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_data_seg, ROMABLE_REGION) + + /* This section located in RTC FAST Memory area. + * It holds data marked with RTC_FAST_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_fast : + { + . = ALIGN(4); + _rtc_force_fast_start = ABSOLUTE(.); + + *(.rtc.force_fast .rtc.force_fast.*) + . = ALIGN(4) ; + _rtc_force_fast_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_data_seg, ROMABLE_REGION) + + /* RTC data section holds RTC wake stub + * data/rodata, including from any source file + * named rtc_wake_stub*.c and the data marked with + * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) + *rtc_wake_stub*.*(COMMON) + + *(.rtc.data) + *(.rtc.rodata) + + _rtc_bss_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.*(.bss .bss.*) + *rtc_wake_stub*.*(COMMON) + + _rtc_bss_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* This section holds data that should not be initialized at power up + * and will be retained during deep sleep. + * User data marked with RTC_NOINIT_ATTR will be placed + * into this section. See the file "esp_attr.h" for more information. + */ + .rtc_noinit (NOLOAD): + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) + + /* Get size of rtc slow data based on rtc_data_location alias */ + _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); + _rtc_fast_length = (_rtc_force_fast_end - _rtc_fast_start); + + ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)), "RTC_SLOW segment data does not fit.") + ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)), "RTC_FAST segment data does not fit.") + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } + +} + +ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32s3/linker.ld b/soc/xtensa/esp32s3/linker.ld index db0c8a6904d..6cfbce9433f 100644 --- a/soc/xtensa/esp32s3/linker.ld +++ b/soc/xtensa/esp32s3/linker.ld @@ -7,662 +7,14 @@ * @file * @brief Linker command/script file * - * Linker script for the Xtensa platform. */ -#include -#include -#include -#include - -#define SRAM_IRAM_START 0x40370000 -#define SRAM_DIRAM_I_START 0x40378000 -#define SRAM_IRAM_END 0x403BA000 -#define I_D_SRAM_OFFSET (SRAM_DIRAM_I_START - SRAM_DRAM_START) - -#define SRAM_DRAM_START 0x3FC88000 -#define SRAM_DRAM_END (SRAM_IRAM_END - I_D_SRAM_OFFSET) -#define I_D_SRAM_SIZE (SRAM_DRAM_END - SRAM_DRAM_START) - -#define ICACHE_SIZE 0x8000 -#define SRAM_IRAM_ORG (SRAM_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) -#define SRAM_IRAM_SIZE (I_D_SRAM_SIZE + ICACHE_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) - -#define DCACHE_SIZE 0x10000 -#define SRAM_DRAM_ORG (SRAM_DRAM_START) - -#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE - -#define FLASH_CODE_REGION irom0_0_seg -#define RODATA_REGION drom0_0_seg -#define IRAM_REGION iram0_0_seg -#define RAMABLE_REGION dram0_0_seg -#define ROMABLE_REGION ROM - -#ifdef CONFIG_FLASH_SIZE -#define FLASH_SIZE CONFIG_FLASH_SIZE -#else -#define FLASH_SIZE 0x800000 -#endif - -#ifdef CONFIG_BOOTLOADER_ESP_IDF - -#define IROM_SEG_ORG 0x42000020 -#define IROM_SEG_LEN FLASH_SIZE-0x20 -#define IROM_SEG_ALIGN 0x4 +#if defined(CONFIG_MCUBOOT) + /* Using mcuboot as ESP32S3 2nd stage bootloader */ + #include "mcuboot.ld" #else + /* Application default linker script */ + #include "default.ld" -#define IROM_SEG_ORG 0x42000000 -#define IROM_SEG_LEN FLASH_SIZE -#define IROM_SEG_ALIGN 0x10000 - -#endif - -MEMORY -{ - mcuboot_hdr (RX): org = 0x0, len = 0x20 - metadata (RX): org = 0x20, len = 0x20 - ROM (RX): org = 0x40, len = FLASH_SIZE - 0x40 - iram0_0_seg(RX): org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE - irom0_0_seg(RX): org = IROM_SEG_ORG, len = IROM_SEG_LEN - dram0_0_seg(RW): org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN - - /* DROM is the first segment placed in generated binary. - * MCUboot binary for ESP32 has image header of 0x20 bytes. - * Additional load header of 0x20 bytes are appended to the image. - * Hence, an offset of 0x40 is added to DROM segment origin. - */ - drom0_0_seg(R): org = 0x3C000040, len = FLASH_SIZE - 0x40 - - /** - * RTC fast memory (executable). Persists over deep sleep. - */ - rtc_iram_seg(RWX): org = 0x600fe000, len = 0x2000 - - /** - * RTC fast memory (same block as above), viewed from data bus - */ - rtc_data_seg(RW): org = 0x600fe000, len = 0x2000 - - /** - * RTC slow memory (data accessible). Persists over deep sleep. - */ - rtc_slow_seg(RW): org = 0x50000000, len = 0x2000 - -#ifdef CONFIG_GEN_ISR_TABLES - IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 -#endif -} - -/* Default entry point: */ -ENTRY(CONFIG_KERNEL_ENTRY) - -_diram_i_start = 0x40378000; - -SECTIONS -{ - /* Reserve space for MCUboot header in the binary */ - .mcuboot_header : - { - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - QUAD(0x0) - } > mcuboot_hdr - .metadata : - { - /* Magic byte for load header */ - LONG(0xace637d3) - - /* Application entry point address */ - KEEP(*(.entry_addr)) - - /* IRAM metadata: - * - Destination address (VMA) for IRAM region - * - Flash offset (LMA) for start of IRAM region - * - Size of IRAM region - */ - LONG(ADDR(.iram0.vectors)) - LONG(LOADADDR(.iram0.vectors)) - LONG(LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - LOADADDR(.iram0.vectors)) - - /* DRAM metadata: - * - Destination address (VMA) for DRAM region - * - Flash offset (LMA) for start of DRAM region - * - Size of DRAM region - */ - LONG(ADDR(.dram0.data)) - LONG(LOADADDR(.dram0.data)) - LONG(LOADADDR(.dram0.end) + SIZEOF(.dram0.end) - LOADADDR(.dram0.data)) - } > metadata - -#include - - /* RTC fast memory holds RTC wake stub code, - including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - . = ALIGN(4); - _rtc_text_start = ABSOLUTE(.); - *(.rtc.literal .rtc.text) - *(.rtc.entry.text) - *rtc_wake_stub*.*(.literal .text .literal.* .text.*) - _rtc_text_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) - - /** - * This section is required to skip rtc.text area because rtc_iram_seg and - * rtc_data_seg are reflect the same address space on different buses. - */ - .rtc.dummy : - { - _rtc_dummy_start = ABSOLUTE(.); - _rtc_fast_start = ABSOLUTE(.); - . = SIZEOF(.rtc.text); - _rtc_dummy_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_data_seg, ROMABLE_REGION) - - /** - * This section located in RTC FAST Memory area. - * It holds data marked with RTC_FAST_ATTR attribute. - * See the file "esp_attr.h" for more information. - */ - .rtc.force_fast : - { - . = ALIGN(4); - _rtc_force_fast_start = ABSOLUTE(.); - - *(.rtc.force_fast .rtc.force_fast.*) - . = ALIGN(4) ; - _rtc_force_fast_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_data_seg, ROMABLE_REGION) - - /** - * RTC data section holds RTC wake stub - * data/rodata, including from any source file - * named rtc_wake_stub*.c and the data marked with - * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. - */ - .rtc.data : - { - _rtc_data_start = ABSOLUTE(.); - *(.rtc.data) - *(.rtc.rodata) - *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) - _rtc_data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - *rtc_wake_stub*.*(.bss .bss.*) - *rtc_wake_stub*.*(COMMON) - - *(.rtc.data) - *(.rtc.rodata) - - _rtc_bss_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - *rtc_wake_stub*.*(.bss .bss.*) - *rtc_wake_stub*.*(COMMON) - - _rtc_bss_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /** - * This section holds data that should not be initialized at power up - * and will be retained during deep sleep. - * User data marked with RTC_NOINIT_ATTR will be placed - * into this section. See the file "esp_attr.h" for more information. - */ - .rtc_noinit (NOLOAD): - { - . = ALIGN(4); - _rtc_noinit_start = ABSOLUTE(.); - *(.rtc_noinit .rtc_noinit.*) - . = ALIGN(4) ; - _rtc_noinit_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /** - * This section located in RTC SLOW Memory area. - * It holds data marked with RTC_SLOW_ATTR attribute. - * See the file "esp_attr.h" for more information. - */ - .rtc.force_slow : - { - . = ALIGN(4); - _rtc_force_slow_start = ABSOLUTE(.); - *(.rtc.force_slow .rtc.force_slow.*) - . = ALIGN(4) ; - _rtc_force_slow_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(rtc_slow_seg, ROMABLE_REGION) - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); - _rtc_fast_length = (_rtc_force_fast_end - _rtc_fast_start); - - ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)), "RTC_SLOW segment data does not fit.") - ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)), "RTC_FAST segment data does not fit.") - -/* Send .iram0 code to iram */ - .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 */ - . = 0x0; - KEEP(*(.WindowVectors.text)); - . = 0x180; - KEEP(*(.Level2InterruptVector.text)); - . = 0x1c0; - KEEP(*(.Level3InterruptVector.text)); - . = 0x200; - KEEP(*(.Level4InterruptVector.text)); - . = 0x240; - KEEP(*(.Level5InterruptVector.text)); - . = 0x280; - KEEP(*(.DebugExceptionVector.text)); - . = 0x2c0; - KEEP(*(.NMIExceptionVector.text)); - . = 0x300; - KEEP(*(.KernelExceptionVector.text)); - . = 0x340; - KEEP(*(.UserExceptionVector.text)); - . = 0x3C0; - KEEP(*(.DoubleExceptionVector.text)); - . = 0x400; - _invalid_pc_placeholder = ABSOLUTE(.); - *(.*Vector.literal) - - *(.UserEnter.literal); - *(.UserEnter.text); - . = ALIGN (16); - *(.entry.text) - *(.init.literal) - *(.init) - _init_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) - { - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - *(.iram1 .iram1.*) - *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) - *libesp32.a:panic.*(.literal .text .literal.* .text.*) - *librtc.a:(.literal .text .literal.* .text.*) - *libarch__xtensa__core.a:(.literal .text .literal.* .text.*) - *libkernel.a:(.literal .text .literal.* .text.*) - *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) - *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) - *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) - *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) - *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) - *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*) - *libzephyr.a:systimer_hal.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) - *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) - *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) - *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) - *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) - *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) - *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) - *libzephyr.a:loader.*(.literal .text .literal.* .text.*) - *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) - *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) - *libc.a:*(.literal .text .literal.* .text.*) - *libphy.a:(.phyiram .phyiram.*) - *libgcov.a:(.literal .text .literal.* .text.*) - -#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) -#endif - -#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - } GROUP_DATA_LINK_IN(IRAM_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); - - /** - * This section is required to skip .iram0.text area because iram0_0_seg and - * dram0_0_seg reflect the same address space on different buses. - */ - .dram0.dummy (NOLOAD): - { - . = ORIGIN(dram0_0_seg) + MAX(_iram_end - _iram_start, 0); - } GROUP_LINK_IN(RAMABLE_REGION) - - #include - - .dram0.data : - { - __data_start = ABSOLUTE(.); - - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - /* rodata for panic handler(libarch__xtensa__core.a) and all - * dependent functions should be placed in DRAM to avoid issue - * when flash cache is disabled */ - *libarch__xtensa__core.a:(.rodata .rodata.*) - *libkernel.a:fatal.*(.rodata .rodata.*) - *libkernel.a:init.*(.rodata .rodata.*) - *libzephyr.a:cbprintf_complete*(.rodata .rodata.*) - *libzephyr.a:log_core.*(.rodata .rodata.*) - *libzephyr.a:systimer_hal.*(.rodata .rodata.*) - *libzephyr.a:log_backend_uart.*(.rodata .rodata.*) - *libzephyr.a:log_output.*(.rodata .rodata.*) - *libzephyr.a:loader.*(.rodata .rodata.*) - *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*) - *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*) - - KEEP(*(.jcr)) - *(.dram1 .dram1.*) - . = ALIGN(4); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_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); - _end = ABSOLUTE(.); - _heap_sentry = .; - __data_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - SECTION_DATA_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD),) - { - . = ALIGN(4); - *(.noinit .noinit.*) - . = ALIGN(4) ; - } GROUP_LINK_IN(RAMABLE_REGION) - -/* Shared RAM */ - SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); /* required by bluetooth library */ - __bss_start = ABSOLUTE(.); - - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.share.mem) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - __bss_end = ABSOLUTE(.); - } GROUP_LINK_IN(RAMABLE_REGION) - - ASSERT(((__bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - _text_start = ABSOLUTE(.); - -#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*) -#endif - -#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif - - *(.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. - */ - _flash_cache_start = ABSOLUTE(0); - } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) - - /** - * This dummy section represents the .flash.text section but in default_rodata_seg. - * Thus, it must have its alignment and (at least) its size. - */ - .flash_rodata_dummy (NOLOAD): - { - _flash_rodata_dummy_start = .; - /* Start at the same alignment constraint than .flash.text */ - . = ALIGN(ALIGNOF(.flash.text)); - /* Create an empty gap as big as .flash.text section */ - . = . + SIZEOF(.flash.text); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(0x10000) + 0x20; - _rodata_reserved_start = .; - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - .flash.appdesc : ALIGN(0x10) - { - _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! */ - - /* Create an empty gap within this section. Thanks to this, the end of this - * section will match .flah.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. */ - . = ALIGN(ALIGNOF(_RODATA_SECTION_NAME)); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - -SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(0x10)) - { - __rodata_region_start = ABSOLUTE(.); - - . = ALIGN(4); - #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.* *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.*) - *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - *(.gnu.version_r) - . = (. + 3) & ~ 3; - __eh_frame = ABSOLUTE(.); - KEEP(*(.eh_frame)) - . = (. + 7) & ~ 3; - - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - . = ALIGN(4); - __rodata_region_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _thread_local_start = ABSOLUTE(.); - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - *(.rodata_wlog) - *(.rodata_wlog*) - _thread_local_end = ABSOLUTE(.); - _rodata_reserved_end = ABSOLUTE(.); - . = ALIGN(4); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - /* Flash segments (rodata and text) should be mapped in virtual address space by providing VMA. - * Executing directly from LMA is not possible. */ - #pragma push_macro("GROUP_ROM_LINK_IN") - #undef GROUP_ROM_LINK_IN - #define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion - #include - #include - #include - #include - #include - #include - #include - #pragma pop_macro("GROUP_ROM_LINK_IN") - - /* 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,,ALIGN(0x10)) - { - . = ALIGN(4); - _image_rodata_end = ABSOLUTE(.); - } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) - - _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); - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and 256B alignment for PMS split lines */ - . = ALIGN(16); - _iram_text_end = ABSOLUTE(.); - } GROUP_LINK_IN(IRAM_REGION) - - .iram0.data : - { - . = ALIGN(16); - *(.iram.data) - *(.iram.data*) - } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) - - .iram0.bss (NOLOAD) : - { - . = ALIGN(16); - *(.iram.bss) - *(.iram.bss*) - - . = ALIGN(16); - _iram_end = ABSOLUTE(.); - } GROUP_LINK_IN(IRAM_REGION) - - _image_irom_start = LOADADDR(.flash.text); - _image_irom_size = LOADADDR(.flash.text) + SIZEOF(.flash.text) - _image_irom_start; - _image_irom_vaddr = ADDR(.flash.text); - -#include - - .xtensa.info 0 : { *(.xtensa.info) } - .xt.insn 0 : - { - KEEP (*(.xt.insn)) - KEEP (*(.gnu.linkonce.x.*)) - } - .xt.prop 0 : - { - KEEP (*(.xt.prop)) - KEEP (*(.xt.prop.*)) - KEEP (*(.gnu.linkonce.prop.*)) - } - .xt.lit 0 : - { - KEEP (*(.xt.lit)) - KEEP (*(.xt.lit.*)) - KEEP (*(.gnu.linkonce.p.*)) - } - .xt.profile_range 0 : - { - KEEP (*(.xt.profile_range)) - KEEP (*(.gnu.linkonce.profile_range.*)) - } - .xt.profile_ranges 0 : - { - KEEP (*(.xt.profile_ranges)) - KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) - } - .xt.profile_files 0 : - { - 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)), - "IRAM0 segment data does not fit.") +#endif /* CONFIG_MCUBOOT */ diff --git a/soc/xtensa/esp32s3/loader.c b/soc/xtensa/esp32s3/loader.c index cf3fafc5317..d6530764f96 100644 --- a/soc/xtensa/esp32s3/loader.c +++ b/soc/xtensa/esp32s3/loader.c @@ -8,12 +8,20 @@ #include #include #include +#include #include +#include "esp32s3/dport_access.h" +#include "soc/cache_memory.h" #include +#include "soc/extmem_reg.h" #include #ifdef CONFIG_BOOTLOADER_MCUBOOT + +#define BOOT_LOG_INF(_fmt, ...) \ + ets_printf("[" CONFIG_SOC "] [INF] " _fmt "\n\r", ##__VA_ARGS__) + #define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used)) extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr; @@ -27,60 +35,54 @@ static int map_rom_segments(void) { int rc = 0; size_t _partition_offset = FIXED_PARTITION_OFFSET(slot0_partition); - uint32_t _app_irom_start = _partition_offset + - (uint32_t)&_image_irom_start; + uint32_t _app_irom_start = _partition_offset + (uint32_t)&_image_irom_start; uint32_t _app_irom_size = (uint32_t)&_image_irom_size; uint32_t _app_irom_vaddr = (uint32_t)&_image_irom_vaddr; - uint32_t _app_drom_start = _partition_offset + - (uint32_t)&_image_drom_start; + uint32_t _app_drom_start = _partition_offset + (uint32_t)&_image_drom_start; uint32_t _app_drom_size = (uint32_t)&_image_drom_size; uint32_t _app_drom_vaddr = (uint32_t)&_image_drom_vaddr; - Cache_Read_Disable(0); - Cache_Flush(0); + uint32_t autoload = Cache_Suspend_DCache(); + + Cache_Invalidate_DCache_All(); + /* Clear the MMU entries that are already set up, * so the new app only has the mappings it creates. */ - for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) { - DPORT_PRO_FLASH_MMU_TABLE[i] = - DPORT_FLASH_MMU_TABLE_INVALID_VAL; + for (size_t i = 0; i < FLASH_MMU_TABLE_SIZE; i++) { + FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL; } - uint32_t drom_vaddr_addr_aligned = _app_drom_vaddr & MMU_FLASH_MASK; - uint32_t drom_page_count = bootloader_cache_pages_to_map(_app_drom_size, - _app_drom_vaddr); - rc = cache_flash_mmu_set(0, 0, drom_vaddr_addr_aligned, _app_drom_start - & MMU_FLASH_MASK, 64, drom_page_count); - rc |= cache_flash_mmu_set(1, 0, drom_vaddr_addr_aligned, _app_drom_start - & MMU_FLASH_MASK, 64, drom_page_count); + uint32_t drom_page_count = bootloader_cache_pages_to_map(_app_drom_size, _app_drom_vaddr); - uint32_t irom_vaddr_addr_aligned = _app_irom_vaddr & MMU_FLASH_MASK; - uint32_t irom_page_count = bootloader_cache_pages_to_map(_app_irom_size, - _app_irom_vaddr); - rc |= cache_flash_mmu_set(0, 0, irom_vaddr_addr_aligned, _app_irom_start - & MMU_FLASH_MASK, 64, irom_page_count); - rc |= cache_flash_mmu_set(1, 0, irom_vaddr_addr_aligned, _app_irom_start - & MMU_FLASH_MASK, 64, irom_page_count); + rc |= esp_rom_Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, + _app_drom_vaddr & MMU_FLASH_MASK, + _app_drom_start & MMU_FLASH_MASK, + 64, drom_page_count, 0); - DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, - (DPORT_PRO_CACHE_MASK_IRAM0) | - (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | - (DPORT_PRO_CACHE_MASK_IROM0 & 0) | - DPORT_PRO_CACHE_MASK_DROM0 | - DPORT_PRO_CACHE_MASK_DRAM1); + uint32_t irom_page_count = bootloader_cache_pages_to_map(_app_irom_size, _app_irom_vaddr); - DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, - (DPORT_APP_CACHE_MASK_IRAM0) | - (DPORT_APP_CACHE_MASK_IRAM1 & 0) | - (DPORT_APP_CACHE_MASK_IROM0 & 0) | - DPORT_APP_CACHE_MASK_DROM0 | - DPORT_APP_CACHE_MASK_DRAM1); + rc |= esp_rom_Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, + _app_irom_vaddr & MMU_FLASH_MASK, + _app_irom_start & MMU_FLASH_MASK, + 64, irom_page_count, 0); + + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS); + REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS); + + Cache_Resume_DCache(autoload); + + /* Show map segments continue using same log format as during MCUboot phase */ + BOOT_LOG_INF("DROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map", + _app_drom_start, _app_drom_vaddr, _app_drom_size, _app_drom_size); + BOOT_LOG_INF("IROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map\r\n", + _app_irom_start, _app_irom_vaddr, _app_irom_size, _app_irom_size); + esp_rom_uart_tx_wait_idle(0); - esp_rom_Cache_Read_Enable(0); return rc; } -#endif +#endif /* CONFIG_BOOTLOADER_MCUBOOT */ void __start(void) { diff --git a/soc/xtensa/esp32s3/mcuboot.ld b/soc/xtensa/esp32s3/mcuboot.ld new file mode 100644 index 00000000000..3d1049506ca --- /dev/null +++ b/soc/xtensa/esp32s3/mcuboot.ld @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2023 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 + +#ifdef CONFIG_XIP +#error "Xtensa bootloader cannot use XIP" +#endif /* CONFIG_XIP */ + +/* Disable all romable LMA */ +#undef GROUP_DATA_LINK_IN +#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion + +#define RAMABLE_REGION dram_seg +#define RAMABLE_REGION_1 dram_seg + +#define RODATA_REGION dram_seg +#define ROMABLE_REGION dram_seg + +#define IRAM_REGION iram_seg +#define FLASH_CODE_REGION iram_seg + +#define IROM_SEG_ALIGN 16 + +MEMORY +{ + iram_seg(RWX) : org = 0x403B6000, len = 0x8000 + iram_loader_seg(RWX) : org = 0x403BE000, len = 0x2000 + dram_seg(RW) : org = 0x3FCD0000, len = 0x6000 + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ + + SECTION_PROLOGUE(_RODATA_SECTION_NAME,,ALIGN(0x10)) + { + __rodata_region_start = ABSOLUTE(.); + + . = ALIGN(4); + #include + + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); + __rodata_region_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + /* _rodata_reserved_end = ABSOLUTE(.); */ + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + + .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.*) + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + + .dram0.end : + { + . = ALIGN(4); + #include + . = ALIGN(4); + _end = ABSOLUTE(.); + _heap_sentry = .; + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + /* Send .iram0 code to iram */ + .iram0.vectors : ALIGN(4) + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + _invalid_pc_placeholder = ABSOLUTE(.); + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.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); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + .iram_loader.text : + { + . = ALIGN (16); + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash_config_esp32s3.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_init_common.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) + *libzephyr.a:bootloader_efuse_esp32s3.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_partitions.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + *libzephyr.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_fields.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api_key_esp32xx.*(.literal .text .literal.* .text.*) + *libzephyr.a:app_cpu_start.*(.literal .text .literal.* .text.*) + *esp_mcuboot.*(.literal .text .literal.* .text.*) + *esp_loader.*(.literal .text .literal.* .text.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _loader_text_end = ABSOLUTE(.); + } > iram_loader_seg + + SECTION_PROLOGUE(_TEXT_SECTION_NAME, , ALIGN(4)) + { + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + + . = ALIGN(16); + _iram_text_end = ABSOLUTE(.); */ + _iram_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION) + + /* Shared RAM */ + SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); /* required by bluetooth library */ + __bss_start = ABSOLUTE(.); + + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _btdm_bss_end = ABSOLUTE(.); + + /* Buffer for system heap should be placed in dram_seg */ + *libkernel.a:mempool.*(.noinit.kheap_buf__system_heap .noinit.*.kheap_buf__system_heap) + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + _bss_end = ABSOLUTE(.); + _end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + ASSERT(((__bss_end - ORIGIN(dram_seg)) <= LENGTH(dram_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) + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + + *(.literal .text .literal.* .text.*) + . = ALIGN(4); + + *(.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) + + /* 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. + */ + _flash_cache_start = ABSOLUTE(0); + } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) + +#include + + .xtensa.info 0 : { *(.xtensa.info) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } + +#ifdef CONFIG_GEN_ISR_TABLES +#include +#endif + +} + +ASSERT(((_iram_end - ORIGIN(IRAM_REGION)) <= LENGTH(IRAM_REGION)), + "IRAM0 segment data does not fit.") diff --git a/soc/xtensa/esp32s3/soc.c b/soc/xtensa/esp32s3/soc.c index b8a5d5d8c86..691750d0404 100644 --- a/soc/xtensa/esp32s3/soc.c +++ b/soc/xtensa/esp32s3/soc.c @@ -33,16 +33,21 @@ #include "esp_timer.h" #include "esp_app_format.h" #include "esp_clk_internal.h" + +#ifdef CONFIG_MCUBOOT +#include "bootloader_init.h" +#endif /* CONFIG_MCUBOOT */ #include extern void z_cstart(void); -extern void rom_config_instruction_cache_mode(uint32_t cfg_cache_size, - uint8_t cfg_cache_ways, uint8_t cfg_cache_line_size); -extern void rom_config_data_cache_mode(uint32_t cfg_cache_size, - uint8_t cfg_cache_ways, uint8_t cfg_cache_line_size); -extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, - uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off); +extern void rom_config_instruction_cache_mode(uint32_t cfg_cache_size, uint8_t cfg_cache_ways, + uint8_t cfg_cache_line_size); +extern void rom_config_data_cache_mode(uint32_t cfg_cache_size, uint8_t cfg_cache_ways, + uint8_t cfg_cache_line_size); extern uint32_t Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size); +extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, + uint32_t rodata_start, uint32_t rodata_end, int i_off, + int ro_off); extern int _rodata_reserved_start; extern int _rodata_reserved_end; @@ -53,54 +58,16 @@ extern int _rodata_reserved_end; */ void IRAM_ATTR __esp_platform_start(void) { + volatile soc_reset_reason_t rst_reas[SOC_CPU_CORES_NUM]; 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(); - /* - * Configure the mode of instruction cache : - * cache size, cache associated ways, cache line size. - */ - rom_config_instruction_cache_mode(CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE, - CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS, - CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE); - - /* configure the mode of data: cache size, cache line size.*/ - Cache_Suspend_DCache(); - rom_config_data_cache_mode(CONFIG_ESP32S3_DATA_CACHE_SIZE, - CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS, - CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE); - Cache_Resume_DCache(0); - - /* Configure the Cache MMU size for instruction and rodata in flash. */ - uint32_t rodata_start_align = (uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1); - uint32_t cache_mmu_irom_size = ((rodata_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) - * sizeof(uint32_t); - uint32_t cache_mmu_drom_size = DIV_ROUND_UP( - (uint32_t)&_rodata_reserved_end - rodata_start_align, - MMU_PAGE_SIZE) * sizeof(uint32_t); - - Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); - Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size / sizeof(uint32_t), - cache_mmu_drom_size / sizeof(uint32_t), (uint32_t)&_rodata_reserved_start, - (uint32_t)&_rodata_reserved_end, 0, 0); - -#if CONFIG_ESP32S3_DATA_CACHE_16KB - Cache_Invalidate_DCache_All(); - Cache_Occupy_Addr(SOC_DROM_LOW, 0x4000); -#endif - /* 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 _current before @@ -108,6 +75,47 @@ void IRAM_ATTR __esp_platform_start(void) */ __asm__ volatile("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0])); +#ifdef CONFIG_MCUBOOT + /* MCUboot early initialisation. */ + if (bootloader_init()) { + abort(); + } +#else + /* Configure the mode of instruction cache : cache size, cache line size. */ + rom_config_instruction_cache_mode(CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE, + CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS, + CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE); + + /* If we need use SPIRAM, we should use data cache. + * Configure the mode of data : cache size, cache line size. + */ + Cache_Suspend_DCache(); + rom_config_data_cache_mode(CONFIG_ESP32S3_DATA_CACHE_SIZE, + CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS, + CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE); + Cache_Resume_DCache(0); + /* Configure the Cache MMU size for instruction and rodata in flash. */ + uint32_t rodata_reserved_start_align = + (uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1); + uint32_t cache_mmu_irom_size = + ((rodata_reserved_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) * sizeof(uint32_t); + uint32_t cache_mmu_drom_size = + (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1) + / MMU_PAGE_SIZE) * sizeof(uint32_t); + Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); + + REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN); + /* The clock gating signal of the App core is invalid. We use RUNSTALL and RESETTING + * signals to ensure that the App core stops running in single-core mode. + */ + REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL); + REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETTING); + +#if CONFIG_ESP32S3_DATA_CACHE_16KB + Cache_Invalidate_DCache_All(); + Cache_Occupy_Addr(SOC_DROM_LOW, 0x4000); +#endif + /* ESP-IDF/MCUboot 2nd stage bootloader enables RTC WDT to check on startup sequence * related issues in application. Hence disable that as we are about to start * Zephyr environment. @@ -116,7 +124,6 @@ void IRAM_ATTR __esp_platform_start(void) wdt_hal_write_protect_disable(&rtc_wdt_ctx); wdt_hal_disable(&rtc_wdt_ctx); - wdt_hal_feed(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx); esp_clk_init(); @@ -126,6 +133,7 @@ void IRAM_ATTR __esp_platform_start(void) #if CONFIG_SOC_FLASH_ESP32 spi_flash_guard_set(&g_flash_guard_default_ops); #endif +#endif /* CONFIG_MCUBOOT */ esp_intr_initialize(); @@ -209,16 +217,15 @@ void IRAM_ATTR esp_restart_noos(void) /* Reset wifi/bluetooth/ethernet/sdio (bb/mac) */ SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, - SYSTEM_BB_RST | SYSTEM_FE_RST | SYSTEM_MAC_RST | - SYSTEM_BT_RST | SYSTEM_BTMAC_RST | SYSTEM_SDIO_RST | - SYSTEM_SDIO_HOST_RST | SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST | - SYSTEM_RW_BTMAC_RST | SYSTEM_RW_BTLP_RST | - SYSTEM_BLE_REG_RST | SYSTEM_PWR_REG_RST); + SYSTEM_BB_RST | SYSTEM_FE_RST | SYSTEM_MAC_RST | SYSTEM_BT_RST | + SYSTEM_BTMAC_RST | SYSTEM_SDIO_RST | SYSTEM_SDIO_HOST_RST | + SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST | SYSTEM_RW_BTMAC_RST | + SYSTEM_RW_BTLP_RST | SYSTEM_BLE_REG_RST | SYSTEM_PWR_REG_RST); REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0); /* Reset timer/spi/uart */ - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, - SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); + SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | + SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); /* Reset DMA */ diff --git a/soc/xtensa/esp32s3/soc.h b/soc/xtensa/esp32s3/soc.h index 7643d2a027b..e45b10cac2f 100644 --- a/soc/xtensa/esp32s3/soc.h +++ b/soc/xtensa/esp32s3/soc.h @@ -65,8 +65,17 @@ extern void esp_rom_uart_set_clock_baudrate(uint8_t uart_no, uint32_t clock_hz, extern void esp_rom_ets_set_appcpu_boot_addr(void *addr); void esp_appcpu_start(void *entry_point); +extern int esp_rom_Cache_Dbus_MMU_Set(uint32_t ext_ram, uint32_t vaddr, uint32_t paddr, + uint32_t psize, uint32_t num, uint32_t fixed); +extern int esp_rom_Cache_Ibus_MMU_Set(uint32_t ext_ram, uint32_t vaddr, uint32_t paddr, + uint32_t psize, uint32_t num, uint32_t fixed); + /* ROM functions which read/write internal i2c control bus for PLL, APLL */ extern uint8_t esp_rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); extern void esp_rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); +/* cache initialization functions */ +void esp_config_instruction_cache_mode(void); +void esp_config_data_cache_mode(void); + #endif /* __SOC_H__ */ diff --git a/soc/xtensa/esp32s3/soc_cache.c b/soc/xtensa/esp32s3/soc_cache.c new file mode 100644 index 00000000000..e4034257d62 --- /dev/null +++ b/soc/xtensa/esp32s3/soc_cache.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc.h" + +/* + * Instruction Cache definitions + */ +#if defined(CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB) +#define ESP32S3_ICACHE_SIZE ICACHE_SIZE_16KB +#else +#define ESP32S3_ICACHE_SIZE ICACHE_SIZE_32KB +#endif + +#if defined(CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B) +#define ESP32S3_ICACHE_LINE_SIZE CACHE_LINE_SIZE_16B +#else +#define ESP32S3_ICACHE_LINE_SIZE CACHE_LINE_SIZE_32B +#endif + +/* + * Data Cache definitions + */ +#if defined(CONFIG_ESP32S3_DATA_CACHE_16KB) || defined(CONFIG_ESP32S3_DATA_CACHE_32KB) +#define ESP32S3_DCACHE_SIZE DCACHE_SIZE_32KB +#else +#define ESP32S3_DCACHE_SIZE DCACHE_SIZE_64KB +#endif + +#if defined(CONFIG_ESP32S3_DATA_CACHE_LINE_16B) +#define ESP32S3_DCACHE_LINE_SIZE CACHE_LINE_SIZE_16B +#elif defined(CONFIG_ESP32S3_DATA_CACHE_LINE_32B) +#define ESP32S3_DCACHE_LINE_SIZE CACHE_LINE_SIZE_32B +#else +#define ESP32S3_DCACHE_LINE_SIZE CACHE_LINE_SIZE_32B +#endif + +#define CACHE_MEMORY_ICACHE_LOW CACHE_ICACHE0 + +#ifndef CONFIG_MCUBOOT +extern void Cache_Enable_ICache(uint32_t autoload); + +void IRAM_ATTR esp_config_instruction_cache_mode(void) +{ + cache_size_t cache_size; + cache_ways_t cache_ways; + cache_line_size_t cache_line_size; + +#if CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB + Cache_Occupy_ICache_MEMORY(CACHE_MEMORY_IBANK0, CACHE_MEMORY_INVALID); + cache_size = CACHE_SIZE_HALF; +#else + Cache_Occupy_ICache_MEMORY(CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1); + cache_size = CACHE_SIZE_FULL; +#endif +#if CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS + cache_ways = CACHE_4WAYS_ASSOC; +#else + cache_ways = CACHE_8WAYS_ASSOC; +#endif +#if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B + cache_line_size = CACHE_LINE_SIZE_16B; +#elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B + cache_line_size = CACHE_LINE_SIZE_32B; +#else + cache_line_size = CACHE_LINE_SIZE_64B; +#endif + Cache_Set_ICache_Mode(cache_size, cache_ways, cache_line_size); + Cache_Invalidate_ICache_All(); + Cache_Enable_ICache(0); +} + +void IRAM_ATTR esp_config_data_cache_mode(void) +{ + cache_size_t cache_size; + cache_ways_t cache_ways; + cache_line_size_t cache_line_size; + +#if CONFIG_ESP32S3_DATA_CACHE_32KB + Cache_Occupy_DCache_MEMORY(CACHE_MEMORY_DBANK1, CACHE_MEMORY_INVALID); + cache_size = CACHE_SIZE_HALF; +#else + Cache_Occupy_DCache_MEMORY(CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1); + cache_size = CACHE_SIZE_FULL; +#endif +#if CONFIG_ESP32S3_DATA_CACHE_4WAYS + cache_ways = CACHE_4WAYS_ASSOC; +#else + cache_ways = CACHE_8WAYS_ASSOC; +#endif +#if CONFIG_ESP32S3_DATA_CACHE_LINE_16B + cache_line_size = CACHE_LINE_SIZE_16B; +#elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B + cache_line_size = CACHE_LINE_SIZE_32B; +#else + cache_line_size = CACHE_LINE_SIZE_64B; +#endif + Cache_Set_DCache_Mode(cache_size, cache_ways, cache_line_size); + Cache_Invalidate_DCache_All(); +} +#endif /* CONFIG_MCUBOOT */