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 */