From 6bd63cc57725e44cd03f8809e6e926c23419e22e Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Wed, 28 Jan 2026 18:57:11 +0700 Subject: [PATCH 1/3] feat(esp_system): riscv: refactor linker scripts to reduce duplicated code --- components/esp_system/ld/esp32c2/memory.ld.in | 34 +- .../esp_system/ld/esp32c2/sections.ld.in | 361 +---------- components/esp_system/ld/esp32c3/memory.ld.in | 39 +- .../esp_system/ld/esp32c3/sections.ld.in | 477 +-------------- components/esp_system/ld/esp32c5/memory.ld.in | 43 +- .../esp_system/ld/esp32c5/sections.ld.in | 539 +--------------- components/esp_system/ld/esp32c6/memory.ld.in | 41 +- .../esp_system/ld/esp32c6/sections.ld.in | 484 +-------------- .../esp_system/ld/esp32c61/memory.ld.in | 32 +- .../esp_system/ld/esp32c61/sections.ld.in | 384 +----------- components/esp_system/ld/esp32h2/memory.ld.in | 41 +- .../esp_system/ld/esp32h2/sections.ld.in | 486 +-------------- .../esp_system/ld/esp32h21/memory.ld.in | 40 +- .../esp_system/ld/esp32h21/sections.ld.in | 473 +------------- components/esp_system/ld/esp32h4/memory.ld.in | 29 +- .../esp_system/ld/esp32h4/sections.ld.in | 324 +--------- components/esp_system/ld/esp32p4/memory.ld.in | 57 +- .../esp_system/ld/esp32p4/sections.ld.in | 575 +----------------- .../esp_system/ld/esp32p4/sections.rev3.ld.in | 572 ----------------- components/esp_system/ld/ld.cmake | 6 +- components/esp_system/ld/ld.common | 5 + .../ld/{elf_misc.ld.in => ld.debug.sections} | 57 +- components/esp_system/ld/ld.discard.sections | 26 + components/esp_system/ld/ld.dram.sections | 116 ++++ components/esp_system/ld/ld.ext_ram.sections | 43 ++ components/esp_system/ld/ld.flash.sections | 260 ++++++++ components/esp_system/ld/ld.heap.sections | 8 + components/esp_system/ld/ld.iram.sections | 97 +++ components/esp_system/ld/ld.rtc.sections | 170 ++++++ components/esp_system/ld/ld.tcm.sections | 15 + 30 files changed, 952 insertions(+), 4882 deletions(-) delete mode 100644 components/esp_system/ld/esp32p4/sections.rev3.ld.in rename components/esp_system/ld/{elf_misc.ld.in => ld.debug.sections} (72%) create mode 100644 components/esp_system/ld/ld.discard.sections create mode 100644 components/esp_system/ld/ld.dram.sections create mode 100644 components/esp_system/ld/ld.ext_ram.sections create mode 100644 components/esp_system/ld/ld.flash.sections create mode 100644 components/esp_system/ld/ld.heap.sections create mode 100644 components/esp_system/ld/ld.iram.sections create mode 100644 components/esp_system/ld/ld.rtc.sections create mode 100644 components/esp_system/ld/ld.tcm.sections diff --git a/components/esp_system/ld/esp32c2/memory.ld.in b/components/esp_system/ld/esp32c2/memory.ld.in index ec02e05b65..c534d2af20 100644 --- a/components/esp_system/ld/esp32c2/memory.ld.in +++ b/components/esp_system/ld/esp32c2/memory.ld.in @@ -9,6 +9,12 @@ #include "sdkconfig.h" #include "ld.common" +/** + * physical memory is mapped twice to the virtual address (IRAM and DRAM). + * `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory + */ +_iram_dram_shared = 1; + #define SRAM_IRAM_START 0x4037C000 #define SRAM_DRAM_START 0x3FCA0000 #define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C2 */ @@ -64,29 +70,15 @@ MEMORY /* Heap ends at top of dram0_0_seg */ _heap_end = 0x40000000; +REGION_ALIAS("iram_text_seg", iram0_0_seg); +REGION_ALIAS("dram_seg", dram0_0_seg); #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", iram0_2_seg); + REGION_ALIAS("flash_text_seg", iram0_2_seg); + REGION_ALIAS("flash_rodata_seg", drom0_0_seg); #else - REGION_ALIAS("default_code_seg", iram0_0_seg); + REGION_ALIAS("flash_text_seg", iram0_0_seg); + REGION_ALIAS("flash_rodata_seg", dram0_0_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom0_0_seg); -#else - REGION_ALIAS("default_rodata_seg", dram0_0_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; diff --git a/components/esp_system/ld/esp32c2/sections.ld.in b/components/esp_system/ld/esp32c2/sections.ld.in index 4db9c8e5fc..6a8a68b707 100644 --- a/components/esp_system/ld/esp32c2/sections.ld.in +++ b/components/esp_system/ld/esp32c2/sections.ld.in @@ -4,368 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); +#include "ld.iram.sections" - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); +#include "ld.dram.sections" - mapping[iram0_text] +#include "ld.flash.sections" - } > iram0_0_seg +#include "ld.heap.sections" - /** - * 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) + _iram_end - _iram_start; - } > dram0_0_seg - - /** - * This section MUST be placed at the beginning of the DRAM0, which will be - * released along with iram0_bt.text when Bluetooth is no longer in use. - */ - .dram0.bt.data : - { - _data_start = ABSOLUTE(.); - mapping[dram0_bt_data] - } > dram0_0_seg - - .dram0.bt.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_bt_start) - - mapping[dram0_bt_bss] - - _bss_bt_end = ABSOLUTE(.); - } > dram0_0_seg - - .dram0.data : - { - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > dram0_0_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > dram0_0_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > dram0_0_seg - - ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), - "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - ALIGNED_SYMBOL(4, _iram_text_end) - } > iram0_0_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > iram0_0_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - } > iram0_0_seg - - /** - * This section needs to be placed at the end of the IRAM0, which will be - * released along with dram0_bt_data and dram0_bt_bss when Bluetooth is no - * longer in use. - */ - .iram0.bt.text : - { - ALIGNED_SYMBOL(16, _iram_bt_text_start) - - mapping[iram0_bt_text] - - ALIGNED_SYMBOL(16, _iram_end) - } > iram0_0_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > dram0_0_seg - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } - -ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), - "IRAM0 segment data does not fit.") - -ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), - "DRAM segment data does not fit.") diff --git a/components/esp_system/ld/esp32c3/memory.ld.in b/components/esp_system/ld/esp32c3/memory.ld.in index 4c62313833..8dc87d84aa 100644 --- a/components/esp_system/ld/esp32c3/memory.ld.in +++ b/components/esp_system/ld/esp32c3/memory.ld.in @@ -16,9 +16,11 @@ #include "ld.common" /** - * physical memory is mapped twice to the vritual address (IRAM and DRAM). + * physical memory is mapped twice to the virtual address (IRAM and DRAM). * `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory */ +_iram_dram_shared = 1; + #define SRAM_IRAM_START 0x4037C000 #define SRAM_DRAM_START 0x3FC7C000 #define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */ @@ -87,38 +89,25 @@ MEMORY /* Heap ends at top of dram0_0_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /** * The lines below define location alias for .rtc.data section * As C3 only has RTC fast memory, this is not configurable like on other targets */ +REGION_ALIAS("rtc_text_seg", rtc_iram_seg); REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_force_fast_seg", rtc_iram_seg); +REGION_ALIAS("rtc_force_slow_seg", rtc_iram_seg); + +REGION_ALIAS("iram_text_seg", iram0_0_seg); +REGION_ALIAS("dram_seg", dram0_0_seg); #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", iram0_2_seg); + REGION_ALIAS("flash_text_seg", iram0_2_seg); + REGION_ALIAS("flash_rodata_seg", drom0_0_seg); #else - REGION_ALIAS("default_code_seg", iram0_0_seg); + REGION_ALIAS("flash_text_seg", iram0_0_seg); + REGION_ALIAS("flash_rodata_seg", dram0_0_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom0_0_seg); -#else - REGION_ALIAS("default_rodata_seg", dram0_0_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index 2bd4bcfa1e..7e9194b284 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -4,484 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - ALIGNED_SYMBOL(4, _rtc_fast_start) +#include "ld.rtc.sections" - HIDDEN(_rtc_code_start = .); +#include "ld.iram.sections" - mapping[rtc_text] +#include "ld.dram.sections" - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) +#include "ld.flash.sections" - HIDDEN(_rtc_code_end = .); +#include "ld.heap.sections" - /* Padding for possible CPU prefetch + 4B alignment for PMS split lines. */ - . = ((_rtc_code_end - _rtc_code_start) == 0) ? - ALIGN(0) : _esp_memprot_prefetch_pad_size + ALIGN(4); - - _rtc_text_end = ABSOLUTE(.); - } > rtc_iram_seg - - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) - - mapping[rtc_force_fast] - - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > rtc_data_seg - - /** - * 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(.); - - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > rtc_data_location - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > rtc_data_location - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > rtc_data_location - - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > rtc_slow_seg - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the end of the segment and code is relied - * on it. - * >> put new data here << - */ - - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - mapping[iram0_text] - - } > iram0_0_seg - - /** - * 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) + _iram_end - _iram_start; - } > dram0_0_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > dram0_0_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > dram0_0_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > dram0_0_seg - - ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), - "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Padding for possible CPU prefetch + alignment for PMS split lines */ - . += _esp_memprot_prefetch_pad_size; - . = ALIGN(_esp_memprot_align_size); - - /* iram_end_test section exists for use by memprot unit tests only */ - *(.iram_end_test) - - _iram_text_end = ABSOLUTE(.); - } > iram0_0_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > iram0_0_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - ALIGNED_SYMBOL(16, _iram_end) - } > iram0_0_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > dram0_0_seg - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } - -ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), - "IRAM0 segment data does not fit.") - -ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), - "DRAM segment data does not fit.") diff --git a/components/esp_system/ld/esp32c5/memory.ld.in b/components/esp_system/ld/esp32c5/memory.ld.in index 160b3232a4..180998cb40 100644 --- a/components/esp_system/ld/esp32c5/memory.ld.in +++ b/components/esp_system/ld/esp32c5/memory.ld.in @@ -96,47 +96,34 @@ MEMORY lp_reserved_seg(RW) : org = 0x50000000 + 0x4000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM /* PSRAM seg */ - extern_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 + ext_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 } /* Heap ends at top of sram_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /** * The lines below define location alias for .rtc.data section * C5 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section * Thus, the following region segments are not configurable like on other targets */ -REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); -REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_text_seg", lp_ram_seg); +REGION_ALIAS("rtc_data_seg", lp_ram_seg ); +REGION_ALIAS("rtc_slow_seg", lp_ram_seg ); +REGION_ALIAS("rtc_force_fast_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_slow_seg", lp_ram_seg); REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); +REGION_ALIAS("iram_text_seg", sram_seg); +REGION_ALIAS("dram_seg", sram_seg); + #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", irom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else - REGION_ALIAS("default_code_seg", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom_seg); -#else - REGION_ALIAS("default_rodata_seg", sram_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; +OFFSET_TEE = 0x2b0; diff --git a/components/esp_system/ld/esp32c5/sections.ld.in b/components/esp_system/ld/esp32c5/sections.ld.in index b865acd4e0..ac9ad9508a 100644 --- a/components/esp_system/ld/esp32c5/sections.ld.in +++ b/components/esp_system/ld/esp32c5/sections.ld.in @@ -4,546 +4,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - /* Align the start of RTC code region as per PMP granularity - * this ensures we do not overwrite the permissions for the previous - * region (ULP mem) regardless of its end alignment - */ - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) +#include "ld.rtc.sections" - *(.rtc.entry.text) +#include "ld.iram.sections" - mapping[rtc_text] +#include "ld.dram.sections" - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) +#include "ld.flash.sections" - /* Align the end of RTC code region as per PMP granularity */ - . = ALIGN(_esp_pmp_align_size); +#include "ld.ext_ram.sections" - _rtc_text_end = ABSOLUTE(.); - } > lp_ram_seg +#include "ld.heap.sections" - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) - - mapping[rtc_force_fast] - - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > lp_ram_seg - - /** - * 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(.); - - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > lp_ram_seg - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > lp_ram_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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > lp_ram_seg - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the end of the segment and code is relied - * on it. - * >> put new data here << - */ - - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - _vector_table_start = ABSOLUTE(.); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - ALIGNED_SYMBOL(4, _invalid_pc_placeholder) - - /* esp_tee_config_t structure: used to share information between the TEE and REE - * (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.) - * This symbol is expected by the TEE at an offset of 0x2b0 from the vector table start. - */ -#if CONFIG_SECURE_ENABLE_TEE - ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) - ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2b0, "esp_tee_app_cfg must be at an offset 0x2b0 from the vector table start"); - *libesp_tee.a:(.esp_tee_app_cfg); -#endif - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - mapping[iram0_text] - - } > sram_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - /** - * This section is required to skip .iram0.text area because sram_seg and - * sram_seg reflect the same address space on different buses. - */ - .dram0.dummy (NOLOAD): - { - . = ORIGIN(sram_seg) + _iram_end - _iram_start; - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > sram_seg - - ASSERT(((_bss_end - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash text region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - - /* External RAM */ - /** - * This section is required to skip flash sections, because `extern_ram_seg` - * and `drom_seg` / `irom_seg` are on the same bus when app build use flash sections - */ - .ext_ram.dummy (NOLOAD): - { - . = ORIGIN(extern_ram_seg); - . = . + (_rodata_reserved_end - _flash_rodata_dummy_start); - . = ALIGN (_esp_mmu_page_size); - } > extern_ram_seg - -#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - /* This section holds .ext_ram.bss data, and will be put in PSRAM */ - .ext_ram.bss (NOLOAD) : - { - _ext_ram_bss_start = ABSOLUTE(.); - - mapping[extern_ram] - - ALIGNED_SYMBOL(4, _ext_ram_bss_end) - } > extern_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - -#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - /** - * This section holds data that won't be initialised when startup. - * This section locates in External RAM region. - */ - .ext_ram_noinit (NOLOAD) : - { - _ext_ram_noinit_start = ABSOLUTE(.); - - *(.ext_ram_noinit*) - - ALIGNED_SYMBOL(4, _ext_ram_noinit_end) - } > extern_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } - -ASSERT(((_iram_end - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), - "IRAM0 segment data does not fit.") - -ASSERT(((_heap_start - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), - "DRAM segment data does not fit.") diff --git a/components/esp_system/ld/esp32c6/memory.ld.in b/components/esp_system/ld/esp32c6/memory.ld.in index 4345cd201f..130b57d918 100644 --- a/components/esp_system/ld/esp32c6/memory.ld.in +++ b/components/esp_system/ld/esp32c6/memory.ld.in @@ -101,41 +101,28 @@ MEMORY /* Heap ends at top of sram_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /** * The lines below define location alias for .rtc.data section * C6 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section * Thus, the following region segments are not configurable like on other targets */ -REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); -REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_text_seg", lp_ram_seg); +REGION_ALIAS("rtc_data_seg", lp_ram_seg); +REGION_ALIAS("rtc_slow_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_fast_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_slow_seg", lp_ram_seg); REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); +REGION_ALIAS("iram_text_seg", sram_seg); +REGION_ALIAS("dram_seg", sram_seg); + #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", irom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else - REGION_ALIAS("default_code_seg", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom_seg); -#else - REGION_ALIAS("default_rodata_seg", sram_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; +OFFSET_TEE = 0x2e0; diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index ed1841e2a7..82a54cdc52 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -4,491 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - /* Align the start of RTC code region as per PMP granularity - * this ensures we do not overwrite the permissions for the previous - * region (ULP mem) regardless of its end alignment - */ - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) +#include "ld.rtc.sections" - *(.rtc.entry.text) +#include "ld.iram.sections" - mapping[rtc_text] +#include "ld.dram.sections" - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) +#include "ld.flash.sections" - /* Align the end of RTC code region as per PMP granularity */ - . = ALIGN(_esp_pmp_align_size); +#include "ld.heap.sections" - _rtc_text_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) - - mapping[rtc_force_fast] - - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > lp_ram_seg - - /** - * 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(.); - - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > lp_ram_seg - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > lp_ram_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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > lp_ram_seg - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the end of the segment and code is relied - * on it. - * >> put new data here << - */ - - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - -#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS - /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ - KEEP(*(.ocd_stub.code)); - KEEP(*(.ocd_stub.tramp)); - . = ALIGN(0x800); - KEEP(*(.ocd_stub.data)); - KEEP(*(.ocd_stub.bss)); - KEEP(*(.ocd_stub.stack)); - KEEP(*(.ocd_stub.params)); - . = ALIGN(0x1000); - KEEP(*(.ocd_stub.scratchmem)); - ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); -#endif - - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - _vector_table_start = ABSOLUTE(.); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - /* esp_tee_config_t structure: used to share information between the TEE and REE - * (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.) - * This symbol is expected by the TEE at an offset of 0x300 from the vector table start. - */ -#if CONFIG_SECURE_ENABLE_TEE - ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) - ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2e0, "esp_tee_app_cfg must be at an offset 0x2e0 from the vector table start"); - *libesp_tee.a:(.esp_tee_app_cfg); -#endif - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - mapping[iram0_text] - - } > sram_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > sram_seg - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } diff --git a/components/esp_system/ld/esp32c61/memory.ld.in b/components/esp_system/ld/esp32c61/memory.ld.in index 1d2137e899..c5b947b49b 100644 --- a/components/esp_system/ld/esp32c61/memory.ld.in +++ b/components/esp_system/ld/esp32c61/memory.ld.in @@ -59,34 +59,22 @@ MEMORY #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS /* PSRAM seg */ - extern_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 + ext_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 } /* Heap ends at top of sram_seg */ _heap_end = 0x40000000; +REGION_ALIAS("iram_text_seg", sram_seg); +REGION_ALIAS("dram_seg", sram_seg); + #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", irom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else - REGION_ALIAS("default_code_seg", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom_seg); -#else - REGION_ALIAS("default_rodata_seg", sram_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; +OFFSET_TEE = 0x2b0; diff --git a/components/esp_system/ld/esp32c61/sections.ld.in b/components/esp_system/ld/esp32c61/sections.ld.in index 40b7d82740..fa08689924 100644 --- a/components/esp_system/ld/esp32c61/sections.ld.in +++ b/components/esp_system/ld/esp32c61/sections.ld.in @@ -4,391 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); +#include "ld.iram.sections" - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); +#include "ld.dram.sections" - mapping[iram0_text] +#include "ld.flash.sections" - } > sram_seg +#include "ld.ext_ram.sections" - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); +#include "ld.heap.sections" - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - /** - * This section is required to skip .iram0.text area because sram_seg and - * sram_seg reflect the same address space on different buses. - */ - .dram0.dummy (NOLOAD): - { - . = ORIGIN(sram_seg) + _iram_end - _iram_start; - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > sram_seg - - ASSERT(((_bss_end - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash text region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - - /* External RAM */ - /** - * This section is required to skip flash sections, because `extern_ram_seg` - * and `drom_seg` / `irom_seg` are on the same bus when app build use flash sections - */ - .ext_ram.dummy (NOLOAD): - { - . = ORIGIN(extern_ram_seg); - . = . + (_rodata_reserved_end - _flash_rodata_dummy_start); - . = ALIGN (_esp_mmu_page_size); - } > extern_ram_seg - -#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - /* This section holds .ext_ram.bss data, and will be put in PSRAM */ - .ext_ram.bss (NOLOAD) : - { - _ext_ram_bss_start = ABSOLUTE(.); - - mapping[extern_ram] - - ALIGNED_SYMBOL(4, _ext_ram_bss_end) - } > extern_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - -#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - /** - * This section holds data that won't be initialized when startup. - * This section locates in External RAM region. - */ - .ext_ram_noinit (NOLOAD) : - { - _ext_ram_noinit_start = ABSOLUTE(.); - - *(.ext_ram_noinit*) - - ALIGNED_SYMBOL(4, _ext_ram_noinit_end) - } > extern_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } - -ASSERT(((_iram_end - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), - "IRAM0 segment data does not fit.") - -ASSERT(((_heap_start - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), - "DRAM segment data does not fit.") diff --git a/components/esp_system/ld/esp32h2/memory.ld.in b/components/esp_system/ld/esp32h2/memory.ld.in index ba1e5d9960..c78b842214 100644 --- a/components/esp_system/ld/esp32h2/memory.ld.in +++ b/components/esp_system/ld/esp32h2/memory.ld.in @@ -97,40 +97,27 @@ MEMORY /* Heap ends at top of sram_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /** * The lines below define location alias for .rtc.data section * As H2 only has RTC fast memory, this is not configurable like on other targets */ -REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); -REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_text_seg", lp_ram_seg); +REGION_ALIAS("rtc_data_seg", lp_ram_seg); +REGION_ALIAS("rtc_slow_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_fast_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_slow_seg", lp_ram_seg); REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); +REGION_ALIAS("iram_text_seg", sram_seg); +REGION_ALIAS("dram_seg", sram_seg); + #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", irom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else - REGION_ALIAS("default_code_seg", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom_seg); -#else - REGION_ALIAS("default_rodata_seg", sram_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; +OFFSET_TEE = 0x2e0; diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index 09dd47ed2e..82a54cdc52 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -4,493 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - /* Align the start of RTC code region as per PMP granularity - * this ensures we do not overwrite the permissions for any potential previous - * region regardless of its end alignment - */ - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) +#include "ld.rtc.sections" - *(.rtc.entry.text) +#include "ld.iram.sections" - mapping[rtc_text] +#include "ld.dram.sections" - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) +#include "ld.flash.sections" - /* Align the end of RTC code region as per PMP granularity */ - . = ALIGN(_esp_pmp_align_size); +#include "ld.heap.sections" - _rtc_text_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) - - mapping[rtc_force_fast] - - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > lp_ram_seg - - /** - * 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(.); - - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > lp_ram_seg - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > lp_ram_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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > lp_ram_seg - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the end of the segment and code is relied - * on it. - * >> put new data here << - */ - - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - -#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS - /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ - KEEP(*(.ocd_stub.code)); - KEEP(*(.ocd_stub.tramp)); - . = ALIGN(0x800); - KEEP(*(.ocd_stub.data)); - KEEP(*(.ocd_stub.bss)); - KEEP(*(.ocd_stub.stack)); - KEEP(*(.ocd_stub.params)); - . = ALIGN(0x1000); - KEEP(*(.ocd_stub.scratchmem)); - ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); -#endif - - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - _vector_table_start = ABSOLUTE(.); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - ALIGNED_SYMBOL(4, _invalid_pc_placeholder) - - /* esp_tee_config_t structure: used to share information between the TEE and REE - * (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.) - * This symbol is expected by the TEE at an offset of 0x300 from the vector table start. - */ -#if CONFIG_SECURE_ENABLE_TEE - ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) - ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2e0, "esp_tee_app_cfg must be at an offset 0x2e0 from the vector table start"); - *libesp_tee.a:(.esp_tee_app_cfg); -#endif - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - mapping[iram0_text] - - } > sram_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > sram_seg - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } diff --git a/components/esp_system/ld/esp32h21/memory.ld.in b/components/esp_system/ld/esp32h21/memory.ld.in index e8d8e8c2ce..9f54f20d17 100644 --- a/components/esp_system/ld/esp32h21/memory.ld.in +++ b/components/esp_system/ld/esp32h21/memory.ld.in @@ -80,41 +80,27 @@ MEMORY /* Heap ends at top of sram_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /** * The lines below define location alias for .rtc.data section * H21 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section * Thus, the following region segments are not configurable like on other targets */ -REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); -REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_text_seg", lp_ram_seg); +REGION_ALIAS("rtc_data_seg", lp_ram_seg); +REGION_ALIAS("rtc_slow_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_fast_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_slow_seg", lp_ram_seg); REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); +REGION_ALIAS("iram_text_seg", sram_seg); +REGION_ALIAS("dram_seg", sram_seg); + #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", irom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else - REGION_ALIAS("default_code_seg", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom_seg); -#else - REGION_ALIAS("default_rodata_seg", sram_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x100; diff --git a/components/esp_system/ld/esp32h21/sections.ld.in b/components/esp_system/ld/esp32h21/sections.ld.in index cb7b93517c..41b565df28 100644 --- a/components/esp_system/ld/esp32h21/sections.ld.in +++ b/components/esp_system/ld/esp32h21/sections.ld.in @@ -6,480 +6,21 @@ /* TODO: [ESP32H21] IDF-11900, IDF-11908 */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - /* Align the start of RTC code region as per PMP granularity - * this ensures we do not overwrite the permissions for any potential previous - * region regardless of its end alignment - */ - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) +#include "ld.rtc.sections" - *(.rtc.entry.text) +#include "ld.iram.sections" - mapping[rtc_text] +#include "ld.dram.sections" - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) +#include "ld.flash.sections" - /* Align the end of RTC code region as per PMP granularity */ - . = ALIGN(_esp_pmp_align_size); +#include "ld.heap.sections" - _rtc_text_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) - - mapping[rtc_force_fast] - - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > lp_ram_seg - - /** - * 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(.); - - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > lp_ram_seg - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > lp_ram_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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > lp_ram_seg - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the end of the segment and code is relied - * on it. - * >> put new data here << - */ - - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - -#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS - /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ - KEEP(*(.ocd_stub.code)); - KEEP(*(.ocd_stub.tramp)); - . = ALIGN(0x800); - KEEP(*(.ocd_stub.data)); - KEEP(*(.ocd_stub.bss)); - KEEP(*(.ocd_stub.stack)); - KEEP(*(.ocd_stub.params)); - . = ALIGN(0x1000); - KEEP(*(.ocd_stub.scratchmem)); - ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); -#endif - - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - mapping[iram0_text] - - } > sram_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > sram_seg - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } diff --git a/components/esp_system/ld/esp32h4/memory.ld.in b/components/esp_system/ld/esp32h4/memory.ld.in index ac79824bb4..9d3cb3c865 100644 --- a/components/esp_system/ld/esp32h4/memory.ld.in +++ b/components/esp_system/ld/esp32h4/memory.ld.in @@ -69,28 +69,15 @@ MEMORY /* Heap ends at top of sram_seg */ _heap_end = 0x40000000; +REGION_ALIAS("iram_text_seg", sram_seg); +REGION_ALIAS("dram_seg", sram_seg); + #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_code_seg", irom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else - REGION_ALIAS("default_code_seg", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("default_rodata_seg", drom_seg); -#else - REGION_ALIAS("default_rodata_seg", sram_seg); -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS - -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x40; diff --git a/components/esp_system/ld/esp32h4/sections.ld.in b/components/esp_system/ld/esp32h4/sections.ld.in index 3dbf9aa964..27062100e5 100644 --- a/components/esp_system/ld/esp32h4/sections.ld.in +++ b/components/esp_system/ld/esp32h4/sections.ld.in @@ -6,331 +6,19 @@ /* TODO: [ESP32H4] IDF-12305 inherited from verification branch, need check */ -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { +#include "ld.iram.sections" - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x40 == 0, "vector address must be 64 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); +#include "ld.dram.sections" - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); +#include "ld.flash.sections" - mapping[iram0_text] +#include "ld.heap.sections" - } > sram_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(8, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(8, _bss_end) - } > sram_seg - - ASSERT(((_bss_end - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > default_code_seg - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > default_rodata_seg - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > default_rodata_seg - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - mapping[rodata_noload] - } > default_rodata_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } - -ASSERT(((_iram_end - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), - "IRAM0 segment data does not fit.") - -ASSERT(((_heap_start - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), - "DRAM segment data does not fit.") diff --git a/components/esp_system/ld/esp32p4/memory.ld.in b/components/esp_system/ld/esp32p4/memory.ld.in index 37b5f0f8f1..ede8e20542 100644 --- a/components/esp_system/ld/esp32p4/memory.ld.in +++ b/components/esp_system/ld/esp32p4/memory.ld.in @@ -120,37 +120,46 @@ MEMORY /* Heap ends at top of dram0_0_seg */ _heap_end = 0x50000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /** * The lines below define location alias for .rtc.data section * P4 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section * Thus, the following region segments are not configurable like on other targets */ -REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); -REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); -REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_text_seg", lp_ram_seg); +REGION_ALIAS("rtc_data_seg", lp_ram_seg); +REGION_ALIAS("rtc_slow_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_fast_seg", lp_ram_seg); +REGION_ALIAS("rtc_force_slow_seg", lp_ram_seg); REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("text_seg_low", irom_seg); -#else #if CONFIG_ESP32P4_SELECTS_REV_LESS_V3 - REGION_ALIAS("text_seg_low", sram_low); + REGION_ALIAS("iram_text_seg", sram_low); + REGION_ALIAS("dram_seg", sram_low); + REGION_ALIAS("dram_high_seg", sram_high); + ASSERT(((_heap_start_high - ORIGIN(dram_high_seg)) <= LENGTH(dram_high_seg)), + "DRAM_HIGH segment data does not fit.") + + /* define X_low symbols */ + _data_start_low = _data_start; + _data_end_low = _data_end; + _bss_start_low = _bss_start; + _bss_end_low = _bss_end; + _heap_start_low = _heap_start; #else - REGION_ALIAS("text_seg_low", sram_seg); -#endif //CONFIG_ESP32P4_SELECTS_REV_LESS_V3 -#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS + REGION_ALIAS("iram_text_seg", sram_seg); + REGION_ALIAS("dram_seg", sram_seg); +#endif #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - REGION_ALIAS("rodata_seg_low", drom_seg); + REGION_ALIAS("flash_text_seg", irom_seg); + REGION_ALIAS("flash_rodata_seg", drom_seg); #else #if CONFIG_ESP32P4_SELECTS_REV_LESS_V3 - REGION_ALIAS("rodata_seg_low", sram_low); - REGION_ALIAS("rodata_seg_high", sram_high); + REGION_ALIAS("flash_text_seg", sram_low); + REGION_ALIAS("flash_rodata_seg", sram_low); #else - REGION_ALIAS("rodata_seg_low", sram_seg); + REGION_ALIAS("flash_text_seg", sram_seg); + REGION_ALIAS("flash_rodata_seg", sram_seg); #endif //CONFIG_ESP32P4_SELECTS_REV_LESS_V3 #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS @@ -160,16 +169,4 @@ REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); REGION_ALIAS("ext_ram_seg", extern_ram_seg); #endif //#if CONFIG_SPIRAM_XIP_FROM_PSRAM -/** - * If rodata default segment is placed in `drom_seg`, then flash's first rodata section must - * also be first in the segment. - */ -#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS - ASSERT(_flash_rodata_dummy_start == ORIGIN(rodata_seg_low), - ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") -#endif - -#if CONFIG_ESP_SYSTEM_USE_EH_FRAME - ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!"); - ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!"); -#endif +ALIGN_VECTOR_TABLE = 0x40; diff --git a/components/esp_system/ld/esp32p4/sections.ld.in b/components/esp_system/ld/esp32p4/sections.ld.in index d3a97e8124..61be839fc6 100644 --- a/components/esp_system/ld/esp32p4/sections.ld.in +++ b/components/esp_system/ld/esp32p4/sections.ld.in @@ -4,582 +4,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "sdkconfig.h" -#include "ld.common" - /* Default entry point */ ENTRY(call_start_cpu0); SECTIONS { - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - /* Align the start of RTC code region as per PMP granularity - * this ensures we do not overwrite the permissions for the previous - * region (ULP mem/RTC reserved) regardless of their end alignment - */ - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) +#include "ld.rtc.sections" - arrays[rtc_text] - mapping[rtc_text] +#include "ld.tcm.sections" - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) +#include "ld.iram.sections" - /* Align the end of RTC code region as per PMP granularity */ - . = ALIGN(_esp_pmp_align_size); +#include "ld.dram.sections" - ALIGNED_SYMBOL(4, _rtc_text_end) - } > lp_ram_seg +#include "ld.flash.sections" - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) +#include "ld.ext_ram.sections" - arrays[rtc_force_fast] - mapping[rtc_force_fast] +#include "ld.heap.sections" - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > lp_ram_seg - - /** - * 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(.); - - arrays[rtc_data] - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > lp_ram_seg - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - arrays[rtc_bss] - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > lp_ram_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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > lp_ram_seg - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the beginning of the segment and code is relied - * on it. - * >> put new data here << - */ - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - _rtc_ulp_memory_start = _rtc_reserved_start + LENGTH(rtc_reserved_seg); - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .tcm.text : - { - /* Code marked as running out of TCM */ - _tcm_text_start = ABSOLUTE(.); - - arrays[tcm_text] - mapping[tcm_text] - - _tcm_text_end = ABSOLUTE(.); - } > tcm_idram_seg - - .tcm.data : - { - _tcm_data_start = ABSOLUTE(.); - - arrays[tcm_data] - mapping[tcm_data] - - _tcm_data_end = ABSOLUTE(.); - } > tcm_idram_seg - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x40 == 0, "vector address must be 64 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - arrays[iram0_text] - mapping[iram0_text] - - } > sram_low - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_low - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - arrays[iram0_data] - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_low - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - arrays[iram0_bss] - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(16, _iram_end) - } > sram_low - - .dram0.data : - { - _data_start_low = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - arrays[dram0_data] - mapping[dram0_data] - - _data_end_low = ABSOLUTE(.); - } > sram_low - - .dram1.data : - { - _data_start_high = ABSOLUTE(.); - - mapping[dram0_data] - - _data_end_high = ABSOLUTE(.); - } > sram_high - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_low - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - arrays[flash_text] - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash text region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > text_seg_low - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > rodata_seg_low - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - arrays[flash_rodata] - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - . = ALIGN(ALIGNOF(.flash.init_array)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.init_array) - - .flash.init_array : - { - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - * - * RISC-V gcc is configured with --enable-initfini-array so it emits - * .init_array section instead. But the init_priority sections will be - * sorted for iteration in ascending order during startup. - * The rest of the init_array sections is sorted for iteration in descending - * order during startup, however. Hence a different section is generated for - * the init_priority functions which is iterated in ascending order during - * startup. The corresponding code can be found in startup.c. - */ - ALIGNED_SYMBOL(4, __init_priority_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*)) - __init_priority_array_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.init_array, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > rodata_seg_low - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - arrays[rodata_noload] - mapping[rodata_noload] - } > rodata_seg_low - -#if CONFIG_SPIRAM_XIP_FROM_PSRAM - /** - * This section is required to skip flash sections, because `extern_ram_seg` - * and `drom_seg` / `irom_seg` are on the same bus when xip on psram - */ - .ext_ram.dummy (NOLOAD): - { - . = ORIGIN(ext_ram_seg) + (_rodata_reserved_end - _flash_rodata_dummy_start); - . = ALIGN (_esp_mmu_page_size); - } > ext_ram_seg -#endif //CONFIG_SPIRAM_XIP_FROM_PSRAM - -#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - /* This section holds .ext_ram.bss data, and will be put in PSRAM */ - .ext_ram.bss (NOLOAD) : - { - _ext_ram_bss_start = ABSOLUTE(.); - arrays[extern_ram] - mapping[extern_ram] - ALIGNED_SYMBOL(4, _ext_ram_bss_end) - } > ext_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - -#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - /** - * This section holds data that won't be initialised when startup. - * This section locates in External RAM region. - */ - .ext_ram_noinit (NOLOAD) : - { - _ext_ram_noinit_start = ABSOLUTE(.); - - *(.ext_ram_noinit*) - - ALIGNED_SYMBOL(4, _ext_ram_noinit_end) - } > ext_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(4, _bss_start_low) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - arrays[dram0_bss] - mapping[dram0_bss] - - ALIGNED_SYMBOL(4, _bss_end_low) - } > sram_low - - .dram1.bss (NOLOAD) : - { - ALIGNED_SYMBOL(4, _bss_start_high) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(4, _bss_end_high) - } > sram_high - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start_low (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start_low) - } > sram_low - - /* Marks the end of data, bss and possibly rodata */ - .dram1.heap_start_high (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start_high) - } > sram_high - -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } diff --git a/components/esp_system/ld/esp32p4/sections.rev3.ld.in b/components/esp_system/ld/esp32p4/sections.rev3.ld.in deleted file mode 100644 index 3ff1254a5b..0000000000 --- a/components/esp_system/ld/esp32p4/sections.rev3.ld.in +++ /dev/null @@ -1,572 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "sdkconfig.h" -#include "ld.common" - -/* Default entry point */ -ENTRY(call_start_cpu0); - -SECTIONS -{ - /** - * RTC fast memory holds RTC wake stub code, - * including from any source file named rtc_wake_stub*.c - */ - .rtc.text : - { - /* Align the start of RTC code region as per PMP granularity - * this ensures we do not overwrite the permissions for the previous - * region (ULP mem/RTC reserved) regardless of their end alignment - */ - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_fast_start) - ALIGNED_SYMBOL(_esp_pmp_align_size, _rtc_text_start) - - arrays[rtc_text] - mapping[rtc_text] - - *rtc_wake_stub*.*(.text .text.*) - *(.rtc_text_end_test) - - /* Align the end of RTC code region as per PMP granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _rtc_text_end) - } > lp_ram_seg - - /** - * 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 : - { - ALIGNED_SYMBOL(4, _rtc_force_fast_start) - - arrays[rtc_force_fast] - mapping[rtc_force_fast] - - *(.rtc.force_fast .rtc.force_fast.*) - - ALIGNED_SYMBOL(4, _rtc_force_fast_end) - } > lp_ram_seg - - /** - * 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(.); - - arrays[rtc_data] - mapping[rtc_data] - - *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) - - _rtc_data_end = ABSOLUTE(.); - } > lp_ram_seg - - /* RTC bss, from any source file named rtc_wake_stub*.c */ - .rtc.bss (NOLOAD) : - { - _rtc_bss_start = ABSOLUTE(.); - - *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) - *rtc_wake_stub*.*(COMMON) - - arrays[rtc_bss] - mapping[rtc_bss] - - _rtc_bss_end = ABSOLUTE(.); - } > lp_ram_seg - - /** - * 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): - { - ALIGNED_SYMBOL(4, _rtc_noinit_start) - - *(.rtc_noinit .rtc_noinit.*) - - ALIGNED_SYMBOL(4, _rtc_noinit_end) - } > lp_ram_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 : - { - ALIGNED_SYMBOL(4, _rtc_force_slow_start) - - *(.rtc.force_slow .rtc.force_slow.*) - - ALIGNED_SYMBOL(4, _rtc_force_slow_end) - } > lp_ram_seg - -#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND - .rtc.p4_rev3_mspi_workaround : - { - ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_start) - KEEP (*(.p4_rev3_mspi_workaround.rtc_text .p4_rev3_mspi_workaround.rtc_text.*)) - ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_end) - } > rev3_mspi_workaround_seg -#endif - - /** - * This section holds RTC data that should have fixed addresses. - * The data are not initialized at power-up and are retained during deep - * sleep. - */ - .rtc_reserved (NOLOAD): - { - ALIGNED_SYMBOL(4, _rtc_reserved_start) - - KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) - *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) - - /** - * New data can only be added here to ensure existing data are not moved. - * Because data have adhered to the beginning of the segment and code is relied - * on it. - * >> put new data here << - */ - - _rtc_reserved_end = ABSOLUTE(.); - } > rtc_reserved_seg - - _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; - _rtc_ulp_memory_start = _rtc_reserved_start + LENGTH(rtc_reserved_seg); - ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), - "RTC reserved segment data does not fit.") - - /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) - : (_rtc_force_slow_end - _rtc_force_slow_start); - - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) - : (_rtc_noinit_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.") - - .tcm.text : - { - /* Code marked as running out of TCM */ - _tcm_text_start = ABSOLUTE(.); - - arrays[tcm_text] - mapping[tcm_text] - - _tcm_text_end = ABSOLUTE(.); - } > tcm_idram_seg - - .tcm.data : - { - _tcm_data_start = ABSOLUTE(.); - - arrays[tcm_data] - mapping[tcm_data] - - _tcm_data_end = ABSOLUTE(.); - } > tcm_idram_seg - - .iram0.text : - { - _iram_start = ABSOLUTE(.); - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x40 == 0, "vector address must be 64 byte aligned"); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - - /* Code marked as running out of IRAM */ - _iram_text_start = ABSOLUTE(.); - - mapping[iram0_text] - - } > sram_seg - - /* Marks the end of IRAM code segment */ - .iram0.text_end (NOLOAD) : - { - /* Align the end of code region as per PMP region granularity */ - . = ALIGN(_esp_pmp_align_size); - - ALIGNED_SYMBOL(4, _iram_text_end) - } > sram_seg - - .iram0.data : - { - ALIGNED_SYMBOL(16, _iram_data_start) - - mapping[iram0_data] - - _iram_data_end = ABSOLUTE(.); - } > sram_seg - - .iram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(16, _iram_bss_start) - - mapping[iram0_bss] - - _iram_bss_end = ABSOLUTE(.); - - ALIGNED_SYMBOL(16, _iram_end) - } > sram_seg - - /** - * This section is required to skip .iram0.text area because sram_seg and - * sram_seg reflect the same address space on different buses. - */ - .dram0.dummy (NOLOAD): - { - . = ORIGIN(sram_seg) + _iram_end - _iram_start; - } > sram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.gnu.linkonce.d.*) - *(.data1) - __global_pointer$ = . + 0x800; - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - - mapping[dram0_data] - - _data_end = ABSOLUTE(.); - } > sram_seg - - /** - * This section holds data that should not be initialized at power up. - * The section located in Internal SRAM memory region. The macro _NOINIT - * can be used as attribute to place data into this section. - * See the "esp_attr.h" file for more information. - */ - .noinit (NOLOAD): - { - ALIGNED_SYMBOL(4, _noinit_start) - - *(.noinit .noinit.*) - - ALIGNED_SYMBOL(4, _noinit_end) - } > sram_seg - - .dram0.bss (NOLOAD) : - { - ALIGNED_SYMBOL(4, _bss_start) - - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] - - ALIGNED_SYMBOL(4, _bss_end) - } > sram_seg - - /* Marks the end of data, bss and possibly rodata */ - .dram0.heap_start (NOLOAD) : - { - ALIGNED_SYMBOL(16, _heap_start) - } > sram_seg - - ASSERT(((_heap_start - ORIGIN(sram_seg)) <= LENGTH(sram_seg)), "DRAM segment data does not fit.") - - .flash.text : - { - _stext = .; - /** - * Mark the start of flash.text. - * This can be used by the MMU driver to maintain the virtual address. - */ - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - - arrays[flash_text] - mapping[flash_text] - - *(.stub) - *(.gnu.linkonce.t.*) - *(.gnu.warning) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - /** - * 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 - */ - . += _esp_flash_mmap_prefetch_pad_size; - -#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash text region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - - _text_end = ABSOLUTE(.); - /** - * Mark the flash.text end. - * This can be used for MMU driver to maintain virtual address. - */ - _instruction_reserved_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); - } > text_seg_low - - /** - * 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 = .; - - . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); - - /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ - . = ALIGN(_esp_mmu_page_size) + 0x20; - } > rodata_seg_low - - .flash.appdesc : ALIGN(0x10) - { - /** - * Mark flash.rodata start. - * This can be used for mmu driver to maintain virtual address - */ - _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); - - /* !DO NOT PUT ANYTHING BEFORE THIS! */ - - /* Should be the first. App version info. */ - *(.rodata_desc .rodata_desc.*) - /* Should be the second. Custom app version info. */ - *(.rodata_custom_desc .rodata_custom_desc.*) - - /** - * Create an empty gap within this section. Thanks to this, the end of this - * section will match .flash.rodata's begin address. Thus, both sections - * will be merged when creating the final bin image. - */ - . = ALIGN(ALIGNOF(.flash.rodata)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) - - .flash.rodata : ALIGN(0x10) - { - _flash_rodata_start = ABSOLUTE(.); - - arrays[flash_rodata] - mapping[flash_rodata] - -#if CONFIG_LIBC_PICOLIBC - *(.got .got.plt) /* TODO: GCC-439 */ -#endif - *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ - *(.gnu.linkonce.r.*) - *(.rodata1) - *(.gcc_except_table .gcc_except_table.*) - *(.gnu.linkonce.e.*) - . = ALIGN(ALIGNOF(.flash.init_array)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.rodata, .flash.init_array) - - .flash.init_array : - { - /** - * C++ constructor tables. - * - * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. - */ - ALIGNED_SYMBOL(4, __preinit_array_start) - ALIGNED_SYMBOL(4, __bothinit_array_start) - KEEP (*(.preinit_array)) - __preinit_array_end = ABSOLUTE(.); - - . = ALIGN(4); - PROVIDE(__init_priority_array_start = ABSOLUTE(.)); - KEEP (*(SORT_BY_INIT_PRIORITY(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))) - . = ALIGN(4); - PROVIDE(__init_priority_array_end = ABSOLUTE(.)); - - ALIGNED_SYMBOL(4, __init_array_start) - KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) - __init_array_end = ABSOLUTE(.); - __bothinit_array_end = ABSOLUTE(.); - - /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ - ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) - KEEP (*(.reserved_memory_address)) - soc_reserved_memory_region_end = ABSOLUTE(.); - - /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - - _rodata_end = ABSOLUTE(.); - . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.init_array, SECTION_AFTER_FLASH_RODATA) - -#if EH_FRAME_LINKING_ENABLED - .eh_frame_hdr : - { - ALIGNED_SYMBOL(4, __eh_frame_hdr) - - KEEP (*(.eh_frame_hdr)) - - __eh_frame_hdr_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.eh_frame)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) - - .eh_frame : - { - ALIGNED_SYMBOL(4, __eh_frame) - - KEEP (*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); - - __eh_frame_end = ABSOLUTE(.); - - . = ALIGN(ALIGNOF(.flash.tdata)); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) -#endif // EH_FRAME_LINKING_ENABLED - - .flash.tdata : - { - /* Keep tdata and tbss sections contiguous (no gaps between them). - * The TLS runtime code calculates offsets assuming these sections are - * adjacent. Gaps would cause incorrect address calculations, leading - * to accessing wrong memory. - */ - /* tdata sections */ - _thread_local_data_start = ABSOLUTE(.); -#if CONFIG_LIBC_PICOLIBC - _picolibc_reent_stub_start = ABSOLUTE(.); - KEEP(*(.tdata.errno)) -#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - /* Reproduce the public fields from struct _reent. */ - KEEP(*(.tdata.tls_stdin)) - KEEP(*(.tdata.tls_stdout)) - KEEP(*(.tdata.tls_stderr)) -#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY - _picolibc_reent_stub_end = ABSOLUTE(.); -#endif // CONFIG_LIBC_PICOLIBC - *(.tdata .tdata.* .gnu.linkonce.td.*) - . = ALIGN(ALIGNOF(.flash.tbss)); - _thread_local_data_end = ABSOLUTE(.); - } > rodata_seg_low - ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) - ASSERT_PICOLIBC_REENT_STUB() - - .flash.tbss (NOLOAD) : - { - /* tbss sections */ - _thread_local_bss_start = ABSOLUTE(.); - *(.tbss .tbss.* .gnu.linkonce.tb.*) - *(.tcommon .tcommon.*) - _thread_local_bss_end = ABSOLUTE(.); - } > rodata_seg_low - ASSERT(_thread_local_data_end == _thread_local_bss_start, - "tdata and tbss must be contiguous.") - - /** - * This section contains all the rodata that is not used - * at runtime, helping to avoid an increase in binary size. - */ - .flash.rodata_noload (NOLOAD) : - { -#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /* Align the end of flash rodata region as per PMP granularity to allow using the - * page alignment gap created while mapping the flash region into the PSRAM memory. - */ - . = ALIGN(_esp_pmp_align_size); -#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION - /** - * This symbol marks the end of flash.rodata. It can be utilized by the MMU - * driver to maintain the virtual address. - * NOLOAD rodata may not be included in this section. - */ - _rodata_reserved_end = .; - - arrays[rodata_noload] - mapping[rodata_noload] - } > rodata_seg_low - -#if CONFIG_SPIRAM_XIP_FROM_PSRAM - /** - * This section is required to skip flash sections, because `extern_ram_seg` - * and `drom_seg` / `irom_seg` are on the same bus when xip on psram - */ - .ext_ram.dummy (NOLOAD): - { - . = ORIGIN(ext_ram_seg) + (_rodata_reserved_end - _flash_rodata_dummy_start); - . = ALIGN (_esp_mmu_page_size); - } > ext_ram_seg -#endif //CONFIG_SPIRAM_XIP_FROM_PSRAM - -#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - /* This section holds .ext_ram.bss data, and will be put in PSRAM */ - .ext_ram.bss (NOLOAD) : - { - _ext_ram_bss_start = ABSOLUTE(.); - arrays[extern_ram] - mapping[extern_ram] - ALIGNED_SYMBOL(4, _ext_ram_bss_end) - } > ext_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY - -#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - /** - * This section holds data that won't be initialised when startup. - * This section locates in External RAM region. - */ - .ext_ram_noinit (NOLOAD) : - { - _ext_ram_noinit_start = ABSOLUTE(.); - - *(.ext_ram_noinit*) - - ALIGNED_SYMBOL(4, _ext_ram_noinit_end) - } > ext_ram_seg -#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY - -#include "elf_misc.ld.in" -} diff --git a/components/esp_system/ld/ld.cmake b/components/esp_system/ld/ld.cmake index 9464a569ad..5fbb90f6c5 100644 --- a/components/esp_system/ld/ld.cmake +++ b/components/esp_system/ld/ld.cmake @@ -48,10 +48,6 @@ preprocess_linker_file("memory.ld.in" "memory.ld" ld_out_path) target_linker_script(${COMPONENT_LIB} INTERFACE "${ld_out_path}") # Generate sections.ld.in and pass it through linker script generator -if(CONFIG_IDF_TARGET_ESP32P4 AND NOT CONFIG_ESP32P4_SELECTS_REV_LESS_V3) - preprocess_linker_file("sections.rev3.ld.in" "sections.ld.in" ld_out_path) -else() - preprocess_linker_file("sections.ld.in" "sections.ld.in" ld_out_path) -endif() +preprocess_linker_file("sections.ld.in" "sections.ld.in" ld_out_path) target_linker_script(${COMPONENT_LIB} INTERFACE "${ld_out_path}" PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/sections.ld") diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common index f2e2570ef7..4c39566ae2 100644 --- a/components/esp_system/ld/ld.common +++ b/components/esp_system/ld/ld.common @@ -120,3 +120,8 @@ ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \ #else #define ASSERT_PICOLIBC_REENT_STUB() #endif + +#define SECTION_MAPPINGS(SECTION_NAME) \ +\n arrays[SECTION_NAME] \ +\n mapping[SECTION_NAME] \ +\n mutable[SECTION_NAME] diff --git a/components/esp_system/ld/elf_misc.ld.in b/components/esp_system/ld/ld.debug.sections similarity index 72% rename from components/esp_system/ld/elf_misc.ld.in rename to components/esp_system/ld/ld.debug.sections index ce56428853..cd26c00d7f 100644 --- a/components/esp_system/ld/elf_misc.ld.in +++ b/components/esp_system/ld/ld.debug.sections @@ -1,4 +1,5 @@ #include "sdkconfig.h" +#include "ld.common" /** * This section is not included in the binary image; it is only present in the ELF file. @@ -7,20 +8,23 @@ .noload 0 (INFO) : { _noload_keep_in_elf_start = ABSOLUTE(.); + SECTION_MAPPINGS(noload_keep_in_elf) KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*)) - mapping[noload_keep_in_elf] _noload_keep_in_elf_end = ABSOLUTE(.); } /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } @@ -30,18 +34,23 @@ .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_pubtypes 0 : { *(.debug_pubtypes) } + /* DWARF 3 */ .debug_ranges 0 : { *(.debug_ranges) } + /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } + /* GNU DWARF 2 extensions */ .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } + /* DWARF 4 */ .debug_types 0 : { *(.debug_types) } + /* DWARF 5 */ .debug_addr 0 : { *(.debug_addr) } .debug_line_str 0 : { *(.debug_line_str) } @@ -51,30 +60,14 @@ .debug_rnglists 0 : { *(.debug_rnglists) } .debug_str_offsets 0 : { *(.debug_str_offsets) } - .comment 0 : { *(.comment) } - .note.GNU-stack 0: { *(.note.GNU-stack) } + /** + * Miscellaneous sections + */ + .comment 0 : { *(.comment) } + .note.GNU-stack 0 : { *(.note.GNU-stack) } -#if CONFIG_IDF_TARGET_ARCH_RISCV - .riscv.attributes 0: { *(.riscv.attributes) } + .riscv.attributes 0 : { *(.riscv.attributes) } - /DISCARD/ : - { - /** - * Discarding .rela.* sections results in the following mapping: - * .rela.text.* -> .text.* - * .rela.data.* -> .data.* - * And so forth... - */ - *(.rela.*) -#if CONFIG_LIBC_NEWLIB - *(.got .got.plt) /* TODO: GCC-382 */ -#endif -#if !EH_FRAME_LINKING_ENABLED - *(.eh_frame_hdr) - *(.eh_frame) -#endif // !EH_FRAME_LINKING_ENABLED - } -#elif CONFIG_IDF_TARGET_ARCH_XTENSA /** * .xt.prop and .xt.lit sections will be used by the debugger and disassembler * to get more information about raw data present in the code. @@ -85,18 +78,6 @@ * This section will only be present in the ELF file, not in the final binary * For more details, check GCC-212 */ - .xtensa.info 0: { *(.xtensa.info) } - .xt.prop 0 : { *(.xt.prop .xt.prop.* .gnu.linkonce.prop.*) } - .xt.lit 0 : { *(.xt.lit .xt.lit.* .gnu.linkonce.p.*) } - - /DISCARD/ : - { - *(.fini) - *(.eh_frame_hdr) -#if !EH_FRAME_LINKING_ENABLED - *(.eh_frame) -#endif // !EH_FRAME_LINKING_ENABLED - } -#else - #error "Target architecture is not supported!" -#endif + .xtensa.info 0 : { *(.xtensa.info) } + .xt.prop 0 : { *(.xt.prop .xt.prop.* .gnu.linkonce.prop.*) } + .xt.lit 0 : { *(.xt.lit .xt.lit.* .gnu.linkonce.p.*) } diff --git a/components/esp_system/ld/ld.discard.sections b/components/esp_system/ld/ld.discard.sections new file mode 100644 index 0000000000..8851195e68 --- /dev/null +++ b/components/esp_system/ld/ld.discard.sections @@ -0,0 +1,26 @@ +#include "sdkconfig.h" +#include "ld.common" + + /DISCARD/ : + { + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + *(.rela.*) +#if CONFIG_LIBC_NEWLIB + *(.got .got.plt) /* TODO: GCC-382 */ +#endif // CONFIG_LIBC_NEWLIB + + *(.fini) +#if CONFIG_IDF_TARGET_ARCH_XTENSA + *(.eh_frame_hdr) +#endif // CONFIG_IDF_TARGET_ARCH_XTENSA + +#if !EH_FRAME_LINKING_ENABLED + *(.eh_frame_hdr) + *(.eh_frame) +#endif // !EH_FRAME_LINKING_ENABLED + } diff --git a/components/esp_system/ld/ld.dram.sections b/components/esp_system/ld/ld.dram.sections new file mode 100644 index 0000000000..5519139ab1 --- /dev/null +++ b/components/esp_system/ld/ld.dram.sections @@ -0,0 +1,116 @@ +#include "sdkconfig.h" +#include "ld.common" + + .dram0.dummy (NOLOAD) : + { + /** + * Reserve DRAM space for shared D/IRAM memory configuration. + * + * On certain ESP chips, the same physical SRAM is accessible via two + * different virtual address ranges: + * - IRAM: 0x4xxxxxxx + * - DRAM: 0x3Fxxxxxx + * + * While the virtual addresses differ, both ranges map to the same physical + * memory. + * + * When `_iram_dram_shared` is defined, it indicates this configuration exists. + * We must advance the DRAM location counter past the region used by IRAM code + * to prevent DRAM data from physically overwriting executable IRAM code. + */ + . = DEFINED(_iram_dram_shared) ? ORIGIN(dram_seg) + (_iram_end - _iram_start) : .; + } > dram_seg + + .dram0.data_start : + { + _data_start = .; + } > dram_seg + +#if CONFIG_BT_LE_RELEASE_IRAM_SUPPORTED + /** + * This sections MUST be placed at the beginning of the DRAM, which will be + * released along with iram0_bt_text when Bluetooth is no longer in use. + */ + .dram0.bt.data : + { + SECTION_MAPPINGS(dram0_bt_data) + } > dram_seg + + .dram0.bt.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _bss_bt_start) + + SECTION_MAPPINGS(dram0_bt_bss) + + _bss_bt_end = ABSOLUTE(.); + } > dram_seg +#endif + + .dram0.data : + { + *(.gnu.linkonce.d.*) + *(.data1) + __global_pointer$ = . + 0x800; + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + + SECTION_MAPPINGS(dram0_data) + + _data_end = ABSOLUTE(.); + } > dram_seg + + /** + * This section holds data that should not be initialized at power up. + * The section is located in Internal SRAM memory region. The macro _NOINIT + * can be used as attribute to place data into this section. + * See the "esp_attr.h" file for more information. + */ + .noinit (NOLOAD) : + { + ALIGNED_SYMBOL(4, _noinit_start) + + SECTION_MAPPINGS(noinit) + *(.noinit .noinit.*) + + ALIGNED_SYMBOL(4, _noinit_end) + } > dram_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _bss_start) + + SECTION_MAPPINGS(dram0_bss) + + ALIGNED_SYMBOL(8, _bss_end) + } > dram_seg + +#if CONFIG_ESP32P4_SELECTS_REV_LESS_V3 + .dram1.data : + { + _data_start_high = ABSOLUTE(.); + + mapping[dram0_data] + mutable[dram0_data] + + _data_end_high = ABSOLUTE(.); + } > dram_high_seg + + .dram1.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _bss_start_high) + + mapping[dram0_bss] + mutable[dram0_bss] + + ALIGNED_SYMBOL(8, _bss_end_high) + } > dram_high_seg + + .dram1.heap_start (NOLOAD) : + { + ALIGNED_SYMBOL(16, _heap_start_high) + } > dram_high_seg +#endif diff --git a/components/esp_system/ld/ld.ext_ram.sections b/components/esp_system/ld/ld.ext_ram.sections new file mode 100644 index 0000000000..b214e5915b --- /dev/null +++ b/components/esp_system/ld/ld.ext_ram.sections @@ -0,0 +1,43 @@ +#include "sdkconfig.h" +#include "ld.common" + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY || CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * Dummy section to skip flash rodata sections in case `ext_ram_seg` + * and `flash_rodata_seg` are on the same bus. + */ + .ext_ram.dummy (NOLOAD) : + { + HIDDEN(_ext_ram_on_same_bus = ORIGIN(ext_ram_seg) == ORIGIN(flash_rodata_seg)); + . = _ext_ram_on_same_bus ? ORIGIN(ext_ram_seg) + (_rodata_reserved_end - _flash_rodata_dummy_start) : 0; + . = ALIGN(_ext_ram_on_same_bus ? _esp_mmu_page_size : 0); + } > ext_ram_seg + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + /* This section holds .ext_ram.bss data, and will be put in PSRAM */ + .ext_ram.bss (NOLOAD) : + { + _ext_ram_bss_start = ABSOLUTE(.); + + SECTION_MAPPINGS(extern_ram) + + ALIGNED_SYMBOL(4, _ext_ram_bss_end) + } > ext_ram_seg +#endif // CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * This section holds data that won't be initialized at startup. + * This section is located in the External RAM region. + */ + .ext_ram_noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + + SECTION_MAPPINGS(extram_noinit) + *(.ext_ram_noinit*) + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) + } > ext_ram_seg +#endif // CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY +#endif // CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY || CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY diff --git a/components/esp_system/ld/ld.flash.sections b/components/esp_system/ld/ld.flash.sections new file mode 100644 index 0000000000..72cab78373 --- /dev/null +++ b/components/esp_system/ld/ld.flash.sections @@ -0,0 +1,260 @@ +#include "sdkconfig.h" +#include "ld.common" + + .flash.text : + { + _stext = .; + + /** + * Mark the start of flash.text. + * This can be used by the MMU driver to maintain the virtual address. + */ + _instruction_reserved_start = ABSOLUTE(.); + _text_start = ABSOLUTE(.); + + SECTION_MAPPINGS(flash_text) + + *(.stub) + *(.gnu.linkonce.t.*) + *(.gnu.warning) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + + /** + * CPU will try to prefetch up to 16 bytes 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. + */ + . += _esp_flash_mmap_prefetch_pad_size; + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /** + * Align the end of flash text region as per PMP granularity to allow using the + * page alignment gap created while mapping the flash region into the PSRAM memory. + */ + . = ALIGN(_esp_pmp_align_size); +#endif // CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + + _text_end = ABSOLUTE(.); + + /** + * Mark the flash.text end. + * This can be used for MMU driver to maintain virtual address. + */ + _instruction_reserved_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); + } > flash_text_seg + + /** + * Dummy section represents the .flash.text section but in flash_rodata_seg. + * Thus, it must have its alignment and (at least) its size. + */ + .flash_rodata_dummy (NOLOAD) : + { + _flash_rodata_dummy_start = .; + + . = ALIGN(ALIGNOF(.flash.text)) + SIZEOF(.flash.text); + + /* Add alignment of MMU page size + 0x20 bytes for the mapping header */ + . = ALIGN(_esp_mmu_page_size) + 0x20; + } > flash_rodata_seg + + .flash.appdesc : ALIGN(0x10) + { + /** + * Mark flash.rodata start. + * This can be used for MMU driver to maintain virtual address. + */ + _rodata_reserved_start = ABSOLUTE(.); + _rodata_start = ABSOLUTE(.); + + /* !DO NOT PUT ANYTHING BEFORE THIS! */ + + /* Should be the first: App version info */ + *(.rodata_desc .rodata_desc.*) + + /* Should be the second: Custom app version info */ + *(.rodata_custom_desc .rodata_custom_desc.*) + + /** + * Create an empty gap within this section. Thanks to this, the end of this + * section will match .flash.rodata's begin address. Thus, both sections + * will be merged when creating the final bin image. + */ + . = ALIGN(ALIGNOF(.flash.rodata)); + } > flash_rodata_seg + ASSERT_SECTIONS_GAP(.flash.appdesc, .flash.rodata) + + .flash.rodata : ALIGN(0x10) + { + _flash_rodata_start = ABSOLUTE(.); + + SECTION_MAPPINGS(flash_rodata) + +#if CONFIG_LIBC_PICOLIBC + *(.got .got.plt) /* TODO: GCC-439 */ +#endif + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + + . = ALIGN(ALIGNOF(.flash.init_array)); + } > flash_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, .flash.init_array) + + .flash.init_array : + { + /** + * C++ constructor tables. + * + * Excluding crtbegin.o/crtend.o since IDF doesn't use the toolchain crt. + */ + ALIGNED_SYMBOL(4, __preinit_array_start) + ALIGNED_SYMBOL(4, __bothinit_array_start) + KEEP (*(.preinit_array)) + __preinit_array_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_priority_array_start) + KEEP (*(SORT_BY_INIT_PRIORITY(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))) + __init_priority_array_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, __init_array_start) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array)) + __init_array_end = ABSOLUTE(.); + __bothinit_array_end = ABSOLUTE(.); + + /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */ + ALIGNED_SYMBOL(4, soc_reserved_memory_region_start) + KEEP (*(.reserved_memory_address)) + soc_reserved_memory_region_end = ABSOLUTE(.); + + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); + + _rodata_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > flash_rodata_seg + ASSERT_SECTIONS_GAP(.flash.init_array, SECTION_AFTER_FLASH_RODATA) + +#if EH_FRAME_LINKING_ENABLED + .eh_frame_hdr : + { + ALIGNED_SYMBOL(4, __eh_frame_hdr) + + KEEP (*(.eh_frame_hdr)) + + __eh_frame_hdr_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.eh_frame)); + } > flash_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame_hdr, .eh_frame) + + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > flash_rodata_seg + ASSERT_SECTIONS_GAP(.eh_frame, .flash.tdata) +#if CONFIG_ESP_SYSTEM_USE_EH_FRAME + ASSERT((__eh_frame_hdr_end > __eh_frame_hdr), "eh_frame_hdr size is 0") + ASSERT((__eh_frame_end > __eh_frame), "eh_frame size is 0") +#endif // CONFIG_ESP_SYSTEM_USE_EH_FRAME +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /** + * IMPORTANT: Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + + /* Thread-local data sections */ + _thread_local_data_start = ABSOLUTE(.); + +#if CONFIG_LIBC_PICOLIBC + _picolibc_reent_stub_start = ABSOLUTE(.); + KEEP(*(.tdata.errno)) + +#if CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + /* Reproduce the public fields from struct _reent */ + KEEP(*(.tdata.tls_stdin)) + KEEP(*(.tdata.tls_stdout)) + KEEP(*(.tdata.tls_stderr)) +#endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY + + _picolibc_reent_stub_end = ABSOLUTE(.); +#endif // CONFIG_LIBC_PICOLIBC + + *(.tdata .tdata.* .gnu.linkonce.td.*) + + . = ALIGN(ALIGNOF(.flash.tbss)); + _thread_local_data_end = ABSOLUTE(.); + } > flash_rodata_seg + ASSERT_SECTIONS_GAP(.flash.tdata, .flash.tbss) + ASSERT_PICOLIBC_REENT_STUB() + + .flash.tbss (NOLOAD) : + { + /* Thread-local BSS sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); + } > flash_rodata_seg + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") + + /** + * This section contains all the rodata that is not used at runtime, + * helping to avoid an increase in binary size. + */ + .flash.rodata_noload (NOLOAD) : + { +#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /** + * Align the end of flash rodata region as per PMP granularity to allow using the + * page alignment gap created while mapping the flash region into the PSRAM memory. + */ + . = ALIGN(_esp_pmp_align_size); +#endif // CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION + /** + * This symbol marks the end of flash.rodata. It can be utilized by the MMU + * driver to maintain the virtual address. + * NOLOAD rodata may not be included in this section. + */ + _rodata_reserved_end = .; + + SECTION_MAPPINGS(rodata_noload) + } > flash_rodata_seg + +#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS + /** + * If rodata default segment is placed in `flash_rodata_seg`, then flash's first + * rodata section must also be first in the segment. + */ + ASSERT(_flash_rodata_dummy_start == ORIGIN(flash_rodata_seg), + ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.") +#endif diff --git a/components/esp_system/ld/ld.heap.sections b/components/esp_system/ld/ld.heap.sections new file mode 100644 index 0000000000..a9841c33ce --- /dev/null +++ b/components/esp_system/ld/ld.heap.sections @@ -0,0 +1,8 @@ +#include "sdkconfig.h" + + .dram0.heap_start (NOLOAD) : + { + ALIGNED_SYMBOL(16, _heap_start) + } > dram_seg + ASSERT(((_heap_start - ORIGIN(dram_seg)) <= LENGTH(dram_seg)), + "DRAM segment data does not fit.") diff --git a/components/esp_system/ld/ld.iram.sections b/components/esp_system/ld/ld.iram.sections new file mode 100644 index 0000000000..5a44f0c87f --- /dev/null +++ b/components/esp_system/ld/ld.iram.sections @@ -0,0 +1,97 @@ +#include "sdkconfig.h" +#include "ld.common" + + .iram0.text : + { + _iram_start = ABSOLUTE(.); + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS + /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ + KEEP(*(.ocd_stub.code)); + KEEP(*(.ocd_stub.tramp)); + . = ALIGN(0x800); + KEEP(*(.ocd_stub.data)); + KEEP(*(.ocd_stub.bss)); + KEEP(*(.ocd_stub.stack)); + KEEP(*(.ocd_stub.params)); + . = ALIGN(0x1000); + KEEP(*(.ocd_stub.scratchmem)); + ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); +#endif + + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % ALIGN_VECTOR_TABLE == 0, "vector address must be ALIGN_VECTOR_TABLE byte aligned"); + _vector_table_start = ABSOLUTE(.); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + +#if CONFIG_SECURE_ENABLE_TEE + /* esp_tee_config_t structure: used to share information between the TEE and REE + * (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.) + */ + ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) + ASSERT(ABSOLUTE(.) == _vector_table_start + OFFSET_TEE, "esp_tee_app_cfg must be at an offset OFFSET_TEE from the vector table start"); + *libesp_tee.a:(.esp_tee_app_cfg); +#endif + + /* Code marked as running out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + SECTION_MAPPINGS(iram0_text) + } > iram_text_seg + + /* Marks the end of IRAM code segment */ + .iram0.text_end (NOLOAD) : + { + /* Padding for possible CPU prefetch + alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); + + /* Align the end of code region as per PMP region granularity */ + . = ALIGN(_esp_pmp_align_size); + + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) + + ALIGNED_SYMBOL(4, _iram_text_end) + } > iram_text_seg + + .iram0.data : + { + ALIGNED_SYMBOL(16, _iram_data_start) + + SECTION_MAPPINGS(iram0_data) + + _iram_data_end = ABSOLUTE(.); + } > iram_text_seg + + .iram0.bss (NOLOAD) : + { + ALIGNED_SYMBOL(16, _iram_bss_start) + + SECTION_MAPPINGS(iram0_bss) + + _iram_bss_end = ABSOLUTE(.); + } > iram_text_seg + +#if CONFIG_BT_LE_RELEASE_IRAM_SUPPORTED + /** + * This section needs to be placed at the end of the IRAM0, which will be + * released along with dram0_bt_data and dram0_bt_bss when Bluetooth is no + * longer in use. + */ + .iram0.bt.text : + { + ALIGNED_SYMBOL(16, _iram_bt_text_start) + + SECTION_MAPPINGS(iram0_bt_text) + } > iram_text_seg +#endif + + .iram0.end (NOLOAD) : + { + ALIGNED_SYMBOL(16, _iram_end) + } > iram_text_seg + +ASSERT(((_iram_end - ORIGIN(iram_text_seg)) <= LENGTH(iram_text_seg)), + "IRAM0 segment data does not fit.") diff --git a/components/esp_system/ld/ld.rtc.sections b/components/esp_system/ld/ld.rtc.sections new file mode 100644 index 0000000000..26edbe9daa --- /dev/null +++ b/components/esp_system/ld/ld.rtc.sections @@ -0,0 +1,170 @@ +#include "sdkconfig.h" +#include "ld.common" + +#if CONFIG_SOC_RTC_MEM_SUPPORTED + /** + * RTC fast memory holds RTC wake stub code, + * including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + /** + * Align the start of RTC code region as per PMP granularity. + * This ensures we do not overwrite the permissions for the previous + * region (ULP mem/RTC reserved) regardless of their end alignment. + */ + . = ALIGN(_esp_pmp_align_size); + + _rtc_fast_start = ABSOLUTE(.); + _rtc_text_start = ABSOLUTE(.); + HIDDEN(_rtc_code_start = .); + + *(.rtc.entry.text) + + SECTION_MAPPINGS(rtc_text) + + *rtc_wake_stub*.*(.text .text.*) + *(.rtc_text_end_test) + + /* Align the end of RTC code region as per PMP granularity */ + . = ALIGN(_esp_pmp_align_size); + + HIDDEN(_rtc_code_end = .); + + /* Padding for possible CPU prefetch + 4B alignment for PMS split lines. */ + . = ((_rtc_code_end - _rtc_code_start) == 0) ? + ALIGN(0) : _esp_memprot_prefetch_pad_size + ALIGN(4); + _rtc_text_end = ABSOLUTE(.); + } > rtc_text_seg + + + /** + * This section is 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 : + { + ALIGNED_SYMBOL(4, _rtc_force_fast_start) + + SECTION_MAPPINGS(rtc_force_fast) + *(.rtc.force_fast .rtc.force_fast.*) + + ALIGNED_SYMBOL(4, _rtc_force_fast_end) + } > rtc_force_fast_seg + + /** + * 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(.); + + SECTION_MAPPINGS(rtc_data) + *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*) + + _rtc_data_end = ABSOLUTE(.); + } > rtc_data_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + + *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*) + *rtc_wake_stub*.*(COMMON) + SECTION_MAPPINGS(rtc_bss) + + _rtc_bss_end = ABSOLUTE(.); + } > rtc_data_seg + + /** + * 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) : + { + ALIGNED_SYMBOL(4, _rtc_noinit_start) + + SECTION_MAPPINGS(rtc_noinit) + *(.rtc_noinit .rtc_noinit.*) + + ALIGNED_SYMBOL(4, _rtc_noinit_end) + } > rtc_data_seg + + /** + * This section is 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 : + { + ALIGNED_SYMBOL(4, _rtc_force_slow_start) + + *(.rtc.force_slow .rtc.force_slow.*) + + ALIGNED_SYMBOL(4, _rtc_force_slow_end) + } > rtc_force_slow_seg + + /** + * This section holds RTC data that should have fixed addresses. + * The data are not initialized at power-up and are retained during deep sleep. + */ + .rtc_reserved (NOLOAD) : + { + ALIGNED_SYMBOL(4, _rtc_reserved_start) + + /** + * IMPORTANT: Existing data must not be moved. + * Data have adhered to the beginning or ending of the segment + * (depending on chip) and code relies on it. + */ +#if CONFIG_IDF_TARGET_ESP32P4 + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + /** + * Put new data after this line + * vvvvvvvvvvvvvvvvvvvvvvvvvvvv + */ +#else // CONFIG_IDF_TARGET_ESP32P4 + /** + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Put new data before this line + */ + *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*) + KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*)) +#endif // CONFIG_IDF_TARGET_ESP32P4 + + _rtc_reserved_end = ABSOLUTE(.); + } > rtc_reserved_seg + + _rtc_ulp_memory_start = _rtc_reserved_start + LENGTH(rtc_reserved_seg); + _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start; + ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)), + "RTC reserved segment data does not fit.") + + /* Get size of rtc slow data based on rtc_data_seg alias */ + _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_seg)) + ? (_rtc_force_slow_end - _rtc_data_start) + : (_rtc_force_slow_end - _rtc_force_slow_start); + _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_seg)) + ? (_rtc_force_fast_end - _rtc_fast_start) + : (_rtc_noinit_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.") + +#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND + .rtc.p4_rev3_mspi_workaround : + { + ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_start) + KEEP (*(.p4_rev3_mspi_workaround.rtc_text .p4_rev3_mspi_workaround.rtc_text.*)) + ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_end) + } > rev3_mspi_workaround_seg +#endif // CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND +#endif // CONFIG_SOC_RTC_MEM_SUPPORTED diff --git a/components/esp_system/ld/ld.tcm.sections b/components/esp_system/ld/ld.tcm.sections new file mode 100644 index 0000000000..625740b1d0 --- /dev/null +++ b/components/esp_system/ld/ld.tcm.sections @@ -0,0 +1,15 @@ +#include "ld.common" + .tcm.text : + { + /* Code marked as running out of TCM */ + _tcm_text_start = ABSOLUTE(.); + SECTION_MAPPINGS(tcm_text) + _tcm_text_end = ABSOLUTE(.); + } > tcm_idram_seg + + .tcm.data : + { + _tcm_data_start = ABSOLUTE(.); + SECTION_MAPPINGS(tcm_data) + _tcm_data_end = ABSOLUTE(.); + } > tcm_idram_seg From dfafd6fc2a7d8dca21739d6543b3e86f1ee95367 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Wed, 28 Jan 2026 18:57:27 +0700 Subject: [PATCH 2/3] fix(esp_system): xtensa: refactor linker scripts and reduce binary size for C++ apps --- components/esp_system/ld/esp32/memory.ld.in | 3 - components/esp_system/ld/esp32/sections.ld.in | 96 +++++++++++------- components/esp_system/ld/esp32s2/memory.ld.in | 2 - .../esp_system/ld/esp32s2/sections.ld.in | 92 ++++++++++------- components/esp_system/ld/esp32s3/memory.ld.in | 3 - .../esp_system/ld/esp32s3/sections.ld.in | 99 +++++++++++-------- components/esp_system/ld/ld.common | 5 + .../portable/xtensa/port.c | 40 ++++---- .../FreeRTOS-Kernel/portable/xtensa/port.c | 40 ++++---- 9 files changed, 225 insertions(+), 155 deletions(-) diff --git a/components/esp_system/ld/esp32/memory.ld.in b/components/esp_system/ld/esp32/memory.ld.in index df13722b0c..66071e3d13 100644 --- a/components/esp_system/ld/esp32/memory.ld.in +++ b/components/esp_system/ld/esp32/memory.ld.in @@ -141,9 +141,6 @@ _heap_end = ALIGN(0x40000000 - _sram1_iram_len - 3, 4); _heap_end = 0x40000000 - CONFIG_ESP32_TRACEMEM_RESERVE_DRAM; #endif - -_data_seg_org = ORIGIN(rtc_data_seg); - /* The lines below define location alias for .rtc.data section based on Kconfig option. When the option is not defined then use slow memory segment else the data will be placed in fast memory segment */ diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index fd13d6afd8..5dfa4c37fb 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -19,7 +19,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_text_start) - mapping[rtc_text] + SECTION_MAPPINGS(rtc_text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) @@ -49,7 +49,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_force_fast_start) - mapping[rtc_force_fast] + SECTION_MAPPINGS(rtc_force_fast) *(.rtc.force_fast .rtc.force_fast.*) @@ -68,7 +68,7 @@ SECTIONS { _rtc_data_start = ABSOLUTE(.); - mapping[rtc_data] + SECTION_MAPPINGS(rtc_data) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) @@ -83,7 +83,7 @@ SECTIONS *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - mapping[rtc_bss] + SECTION_MAPPINGS(rtc_bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -100,6 +100,8 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_noinit_start) + SECTION_MAPPINGS(rtc_noinit) + *(.rtc_noinit .rtc_noinit.*) ALIGNED_SYMBOL(4, _rtc_noinit_end) @@ -222,8 +224,7 @@ SECTIONS /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); - mapping[iram0_text] - + SECTION_MAPPINGS(iram0_text) } > iram0_0_seg .dram0.data : @@ -237,7 +238,7 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - mapping[dram0_data] + SECTION_MAPPINGS(dram0_data) _data_end = ABSOLUTE(.); } > dram0_0_seg @@ -250,6 +251,7 @@ SECTIONS { _ext_ram_noinit_start = ABSOLUTE(.); + SECTION_MAPPINGS(extram_noinit) *(.ext_ram_noinit*) ALIGNED_SYMBOL(4, _ext_ram_noinit_end) @@ -275,7 +277,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _ext_ram_bss_start) - mapping[extern_ram] + SECTION_MAPPINGS(extern_ram) ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg @@ -285,11 +287,7 @@ SECTIONS { ALIGNED_SYMBOL(8, _bss_start) - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] + SECTION_MAPPINGS(dram0_bss) ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg @@ -326,7 +324,7 @@ SECTIONS { _flash_rodata_start = ABSOLUTE(.); - mapping[flash_rodata] + SECTION_MAPPINGS(flash_rodata) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -344,16 +342,6 @@ SECTIONS __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) -#if EH_FRAME_LINKING_ENABLED - ALIGNED_SYMBOL(4, __eh_frame) - KEEP(*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); -#endif // EH_FRAME_LINKING_ENABLED - /** * C++ constructor tables. * @@ -381,9 +369,37 @@ SECTIONS *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - /* TLS data. */ - ALIGNED_SYMBOL(4, _thread_local_start) +#if EH_FRAME_LINKING_ENABLED + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); #if CONFIG_LIBC_PICOLIBC _picolibc_reent_stub_start = ABSOLUTE(.); KEEP(*(.tdata.errno)) @@ -395,15 +411,18 @@ SECTIONS #endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY _picolibc_reent_stub_end = ABSOLUTE(.); #endif // CONFIG_LIBC_PICOLIBC - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*) + _thread_local_data_end = ABSOLUTE(.); + /* tbss sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + _tls_section_alignment = ALIGNOF(.flash.tdata); ASSERT_PICOLIBC_REENT_STUB() - - _flash_rodata_align = ALIGNOF(.flash.rodata); + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -418,7 +437,7 @@ SECTIONS */ _rodata_reserved_end = ABSOLUTE(.); - mapping[rodata_noload] + SECTION_MAPPINGS(rodata_noload) } > default_rodata_seg .flash.text : @@ -431,7 +450,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); - mapping[flash_text] + SECTION_MAPPINGS(flash_text) *(.stub) *(.gnu.warning) @@ -472,7 +491,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_data_start) - mapping[iram0_data] + SECTION_MAPPINGS(iram0_data) _iram_data_end = ABSOLUTE(.); } > iram0_0_seg @@ -481,7 +500,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_bss_start) - mapping[iram0_bss] + SECTION_MAPPINGS(iram0_bss) _iram_bss_end = ABSOLUTE(.); ALIGNED_SYMBOL(4, _iram_end) @@ -494,7 +513,8 @@ SECTIONS ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index 82fa95625c..55214e7ca9 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -109,8 +109,6 @@ _heap_start = _heap_low_start; _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - /* The lines below define location alias for .rtc.data section based on Kconfig option. When the option is not defined then use slow memory segment else the data will be placed in fast memory segment */ diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index f73da10233..41fa979c92 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -28,7 +28,7 @@ SECTIONS HIDDEN(_rtc_code_start = .); - mapping[rtc_text] + SECTION_MAPPINGS(rtc_text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) @@ -63,7 +63,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_force_fast_start) - mapping[rtc_force_fast] + SECTION_MAPPINGS(rtc_force_fast) *(.rtc.force_fast .rtc.force_fast.*) @@ -82,7 +82,7 @@ SECTIONS { _rtc_data_start = ABSOLUTE(.); - mapping[rtc_data] + SECTION_MAPPINGS(rtc_data) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) @@ -97,7 +97,7 @@ SECTIONS *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - mapping[rtc_bss] + SECTION_MAPPINGS(rtc_bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -114,6 +114,8 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_noinit_start) + SECTION_MAPPINGS(rtc_noinit) + *(.rtc_noinit .rtc_noinit.*) ALIGNED_SYMBOL(4, _rtc_noinit_end) @@ -211,7 +213,7 @@ SECTIONS /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); - mapping[iram0_text] + SECTION_MAPPINGS(iram0_text) /* Padding for possible CPU prefetch + alignment for PMS split lines */ . += _esp_memprot_prefetch_pad_size; @@ -239,7 +241,7 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - mapping[dram0_data] + SECTION_MAPPINGS(dram0_data) _data_end = ABSOLUTE(.); } > dram0_0_seg @@ -265,7 +267,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _ext_ram_bss_start) - mapping[extern_ram] + SECTION_MAPPINGS(extern_ram) ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg @@ -280,6 +282,7 @@ SECTIONS { _ext_ram_noinit_start = ABSOLUTE(.); + SECTION_MAPPINGS(extram_noinit) *(.ext_ram_noinit*) ALIGNED_SYMBOL(4, _ext_ram_noinit_end) @@ -291,11 +294,7 @@ SECTIONS { ALIGNED_SYMBOL(8, _bss_start) - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] + SECTION_MAPPINGS(dram0_bss) ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg @@ -329,7 +328,7 @@ SECTIONS { _flash_rodata_start = ABSOLUTE(.); - mapping[flash_rodata] + SECTION_MAPPINGS(flash_rodata) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -347,16 +346,6 @@ SECTIONS __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) -#if EH_FRAME_LINKING_ENABLED - ALIGNED_SYMBOL(4, __eh_frame) - KEEP(*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); -#endif // EH_FRAME_LINKING_ENABLED - /** * C++ constructor tables. * @@ -384,9 +373,37 @@ SECTIONS *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - /* TLS data. */ - ALIGNED_SYMBOL(4, _thread_local_start) +#if EH_FRAME_LINKING_ENABLED + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); #if CONFIG_LIBC_PICOLIBC _picolibc_reent_stub_start = ABSOLUTE(.); KEEP(*(.tdata.errno)) @@ -398,15 +415,18 @@ SECTIONS #endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY _picolibc_reent_stub_end = ABSOLUTE(.); #endif // CONFIG_LIBC_PICOLIBC - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*) + _thread_local_data_end = ABSOLUTE(.); + /* tbss sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + _tls_section_alignment = ALIGNOF(.flash.tdata); ASSERT_PICOLIBC_REENT_STUB() - - _flash_rodata_align = ALIGNOF(.flash.rodata); + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -421,7 +441,8 @@ SECTIONS */ _rodata_reserved_end = ABSOLUTE(.); - mapping[rodata_noload] + SECTION_MAPPINGS(rodata_noload) + } > default_rodata_seg .flash.text : @@ -434,7 +455,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); - mapping[flash_text] + SECTION_MAPPINGS(flash_text) *(.stub) *(.gnu.warning) @@ -478,7 +499,8 @@ SECTIONS ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index ba229c649b..400efc22df 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -130,9 +130,6 @@ _heap_start = _heap_low_start; /* Heap ends at top of dram0_0_seg */ _heap_end = 0x40000000; -_data_seg_org = ORIGIN(rtc_data_seg); - - /* RTC fast memory shares the same range for both data and instructions */ REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index bf71a95412..7a12ddb7bb 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -24,7 +24,7 @@ SECTIONS *(.rtc.entry.literal .rtc.entry.text) - mapping[rtc_text] + SECTION_MAPPINGS(rtc_text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) *(.rtc_text_end_test) @@ -47,7 +47,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_force_fast_start) - mapping[rtc_force_fast] + SECTION_MAPPINGS(rtc_force_fast) *(.rtc.force_fast .rtc.force_fast.*) @@ -66,7 +66,7 @@ SECTIONS { _rtc_data_start = ABSOLUTE(.); - mapping[rtc_data] + SECTION_MAPPINGS(rtc_data) *rtc_wake_stub*.*(.data .rodata .data.* .rodata.*) @@ -81,7 +81,7 @@ SECTIONS *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - mapping[rtc_bss] + SECTION_MAPPINGS(rtc_bss) _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -98,6 +98,8 @@ SECTIONS { ALIGNED_SYMBOL(4, _rtc_noinit_start) + SECTION_MAPPINGS(rtc_noinit) + *(.rtc_noinit .rtc_noinit.*) ALIGNED_SYMBOL(4, _rtc_noinit_end) @@ -195,8 +197,7 @@ SECTIONS /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); - mapping[iram0_text] - + SECTION_MAPPINGS(iram0_text) } > iram0_0_seg /** @@ -205,8 +206,7 @@ SECTIONS */ .dram0.dummy (NOLOAD): { - /* MAX() uses unsigned long arithmetic. Add offset to prevent underflow when _iram_end < _diram_i_start */ - . = ORIGIN(dram0_0_seg) + MAX(_iram_end - _diram_i_start + (_diram_i_start - ORIGIN(iram0_0_seg)), (_diram_i_start - ORIGIN(iram0_0_seg))) - (_diram_i_start - ORIGIN(iram0_0_seg)); + . = ORIGIN(dram0_0_seg) + ((_iram_end > _diram_i_start) ? (_iram_end - _diram_i_start) : 0); } > dram0_0_seg .dram0.data : @@ -220,7 +220,7 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - mapping[dram0_data] + SECTION_MAPPINGS(dram0_data) _data_end = ABSOLUTE(.); } > dram0_0_seg @@ -245,11 +245,7 @@ SECTIONS { ALIGNED_SYMBOL(8, _bss_start) - /** - * ldgen places all bss-related data to mapping[dram0_bss] - * (See components/esp_system/app.lf). - */ - mapping[dram0_bss] + SECTION_MAPPINGS(dram0_bss) ALIGNED_SYMBOL(8, _bss_end) } > dram0_0_seg @@ -267,7 +263,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); - mapping[flash_text] + SECTION_MAPPINGS(flash_text) *(.stub) *(.gnu.warning) @@ -341,7 +337,7 @@ SECTIONS { _flash_rodata_start = ABSOLUTE(.); - mapping[flash_rodata] + SECTION_MAPPINGS(flash_rodata) *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) @@ -359,16 +355,6 @@ SECTIONS __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); *(.xt_except_desc_end) -#if EH_FRAME_LINKING_ENABLED - ALIGNED_SYMBOL(4, __eh_frame) - KEEP(*(.eh_frame)) - /** - * As we are not linking with crtend.o, which includes the CIE terminator - * (see __FRAME_END__ in libgcc sources), it is manually provided here. - */ - LONG(0); -#endif // EH_FRAME_LINKING_ENABLED - /** * C++ constructor tables. * @@ -396,9 +382,37 @@ SECTIONS *(.lit4.*) *(.gnu.linkonce.lit4.*) _lit4_end = ABSOLUTE(.); + . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); + } > default_rodata_seg + ASSERT_SECTIONS_GAP(.flash.rodata, SECTION_AFTER_FLASH_RODATA) - /* TLS data. */ - ALIGNED_SYMBOL(4, _thread_local_start) +#if EH_FRAME_LINKING_ENABLED + .eh_frame : + { + ALIGNED_SYMBOL(4, __eh_frame) + + KEEP (*(.eh_frame)) + /** + * As we are not linking with crtend.o, which includes the CIE terminator + * (see __FRAME_END__ in libgcc sources), it is manually provided here. + */ + LONG(0); + + __eh_frame_end = ABSOLUTE(.); + + . = ALIGN(ALIGNOF(.flash.tdata)); + } > default_rodata_seg +#endif // EH_FRAME_LINKING_ENABLED + + .flash.tdata : + { + /* Keep tdata and tbss sections contiguous (no gaps between them). + * The TLS runtime code calculates offsets assuming these sections are + * adjacent. Gaps would cause incorrect address calculations, leading + * to accessing wrong memory. + */ + /* tdata sections */ + _thread_local_data_start = ABSOLUTE(.); #if CONFIG_LIBC_PICOLIBC _picolibc_reent_stub_start = ABSOLUTE(.); KEEP(*(.tdata.errno)) @@ -410,15 +424,18 @@ SECTIONS #endif // CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY _picolibc_reent_stub_end = ABSOLUTE(.); #endif // CONFIG_LIBC_PICOLIBC - *(.tdata) - *(.tdata.*) - *(.tbss) - *(.tbss.*) - _thread_local_end = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*) + _thread_local_data_end = ABSOLUTE(.); + /* tbss sections */ + _thread_local_bss_start = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + _thread_local_bss_end = ABSOLUTE(.); } > default_rodata_seg + _tls_section_alignment = ALIGNOF(.flash.tdata); ASSERT_PICOLIBC_REENT_STUB() - - _flash_rodata_align = ALIGNOF(.flash.rodata); + ASSERT(_thread_local_data_end == _thread_local_bss_start, + "tdata and tbss must be contiguous.") /** * This section contains all the rodata that is not used @@ -433,7 +450,7 @@ SECTIONS */ _rodata_reserved_end = ABSOLUTE(.); - mapping[rodata_noload] + SECTION_MAPPINGS(rodata_noload) } > default_rodata_seg /** @@ -453,7 +470,7 @@ SECTIONS { _ext_ram_bss_start = ABSOLUTE(.); - mapping[extern_ram] + SECTION_MAPPINGS(extern_ram) ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg @@ -468,6 +485,7 @@ SECTIONS { _ext_ram_noinit_start = ABSOLUTE(.); + SECTION_MAPPINGS(extram_noinit) *(.ext_ram_noinit*) ALIGNED_SYMBOL(4, _ext_ram_noinit_end) @@ -491,7 +509,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_data_start) - mapping[iram0_data] + SECTION_MAPPINGS(iram0_data) ALIGNED_SYMBOL(4, _iram_data_end) } > iram0_0_seg @@ -500,7 +518,7 @@ SECTIONS { ALIGNED_SYMBOL(4, _iram_bss_start) - mapping[iram0_bss] + SECTION_MAPPINGS(iram0_bss) _iram_bss_end = ABSOLUTE(.); ALIGNED_SYMBOL(4, _iram_end) @@ -513,7 +531,8 @@ SECTIONS ALIGNED_SYMBOL(8, _heap_low_start) } > dram0_0_seg -#include "elf_misc.ld.in" +#include "ld.debug.sections" +#include "ld.discard.sections" } ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)), diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common index 4c39566ae2..51e2d3f2eb 100644 --- a/components/esp_system/ld/ld.common +++ b/components/esp_system/ld/ld.common @@ -105,7 +105,12 @@ ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \ #endif #if EH_FRAME_LINKING_ENABLED +#if CONFIG_IDF_TARGET_ARCH_RISCV #define SECTION_AFTER_FLASH_RODATA .eh_frame_hdr +#endif +#if CONFIG_IDF_TARGET_ARCH_XTENSA +#define SECTION_AFTER_FLASH_RODATA .eh_frame +#endif #else #define SECTION_AFTER_FLASH_RODATA .flash.tdata #endif diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c index a26a41c707..7e799a9d67 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -450,30 +450,36 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u LOW ADDRESS |---------------------------| Linker Symbols | Section | -------------- - | .flash.rodata | - 0x0|---------------------------| <- _flash_rodata_start - ^ | Other Data | - | |---------------------------| <- _thread_local_start - | | .tbss | ^ - V | | | - 0xNNN | int example; | | tls_area_size - | | | - | .tdata | V - |---------------------------| <- _thread_local_end + | .flash.tdata | + 0x0|---------------------------| <- _thread_local_data_start ^ + | .flash.tdata | | + | int var_1 = 1; | | + | | <- _thread_local_data_end | + | | <- _thread_local_bss_start | tls_area_size + | | | + | .flash.tbss (NOLOAD) | | + | int var_2; | | + |---------------------------| <- _thread_local_bss_end V | Other data | | ... | |---------------------------| HIGH ADDRESS */ // Calculate the TLS area's size (rounded up to multiple of 16 bytes). - extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; - const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); + extern int _tls_section_alignment; + extern char _thread_local_data_start, _thread_local_data_end; + extern char _thread_local_bss_start, _thread_local_bss_end; + const uint32_t tls_data_size = (uint32_t)&_thread_local_data_end - (uint32_t)&_thread_local_data_start; + const uint32_t tls_bss_size = (uint32_t)&_thread_local_bss_end - (uint32_t)&_thread_local_bss_start; + const uint32_t tls_area_size = ALIGNUP(16, tls_data_size + tls_bss_size); // TODO: check that TLS area fits the stack // Allocate space for the TLS area on the stack. The area must be allocated at a 16-byte aligned address uxStackPointer = STACKPTR_ALIGN_DOWN(16, uxStackPointer - (UBaseType_t)tls_area_size); - // Initialize the TLS area with the initialization values of each TLS variable - memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size); + // Initialize the TLS data with the initialization values of each TLS variable + memcpy((void *)uxStackPointer, &_thread_local_data_start, tls_data_size); + // Initialize the TLS bss with zeroes + memset((void *)(uxStackPointer + tls_data_size), 0, tls_bss_size); /* Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on @@ -500,10 +506,10 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u - "offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment)" - TCB_SIZE is hardcoded to 8 */ - const uint32_t tls_section_align = (uint32_t)&_flash_rodata_align; // ALIGN value of .flash.rodata section + const uint32_t tls_section_align = (uint32_t)&_tls_section_alignment; // ALIGN value of .flash.tdata section #define TCB_SIZE 8 const uint32_t base = ALIGNUP(tls_section_align, TCB_SIZE); - *ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; + *ret_threadptr_reg_init = (uint32_t)uxStackPointer - base; return uxStackPointer; } diff --git a/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c index 2b5f5aadb0..4364d28f56 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT * - * SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2023-2026 Espressif Systems (Shanghai) CO LTD * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -220,30 +220,36 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u LOW ADDRESS |---------------------------| Linker Symbols | Section | -------------- - | .flash.rodata | - 0x0|---------------------------| <- _flash_rodata_start - ^ | Other Data | - | |---------------------------| <- _thread_local_start - | | .tbss | ^ - V | | | - 0xNNN | int example; | | tls_area_size - | | | - | .tdata | V - |---------------------------| <- _thread_local_end + | .flash.tdata | + 0x0|---------------------------| <- _thread_local_data_start ^ + | .flash.tdata | | + | int var_1 = 1; | | + | | <- _thread_local_data_end | + | | <- _thread_local_bss_start | tls_area_size + | | | + | .flash.tbss (NOLOAD) | | + | int var_2; | | + |---------------------------| <- _thread_local_bss_end V | Other data | | ... | |---------------------------| HIGH ADDRESS */ // Calculate the TLS area's size (rounded up to multiple of 16 bytes). - extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; - const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); + extern int _tls_section_alignment; + extern char _thread_local_data_start, _thread_local_data_end; + extern char _thread_local_bss_start, _thread_local_bss_end; + const uint32_t tls_data_size = (uint32_t)&_thread_local_data_end - (uint32_t)&_thread_local_data_start; + const uint32_t tls_bss_size = (uint32_t)&_thread_local_bss_end - (uint32_t)&_thread_local_bss_start; + const uint32_t tls_area_size = ALIGNUP(16, tls_data_size + tls_bss_size); // TODO: check that TLS area fits the stack // Allocate space for the TLS area on the stack. The area must be allocated at a 16-byte aligned address uxStackPointer = STACKPTR_ALIGN_DOWN(16, uxStackPointer - (UBaseType_t)tls_area_size); - // Initialize the TLS area with the initialization values of each TLS variable - memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size); + // Initialize the TLS data with the initialization values of each TLS variable + memcpy((void *)uxStackPointer, &_thread_local_data_start, tls_data_size); + // Initialize the TLS bss with zeroes + memset((void *)(uxStackPointer + tls_data_size), 0, tls_bss_size); /* Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on @@ -270,10 +276,10 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u - "offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment)" - TCB_SIZE is hardcoded to 8 */ - const uint32_t tls_section_align = (uint32_t)&_flash_rodata_align; // ALIGN value of .flash.rodata section + const uint32_t tls_section_align = (uint32_t)&_tls_section_alignment; // ALIGN value of .flash.tdata section #define TCB_SIZE 8 const uint32_t base = ALIGNUP(tls_section_align, TCB_SIZE); - *ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; + *ret_threadptr_reg_init = (uint32_t)uxStackPointer - base; return uxStackPointer; } From 3c237fcd86d7f1460c9ffec307ce8f84c96feef6 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Mon, 16 Mar 2026 18:12:07 +0700 Subject: [PATCH 3/3] fix(test): fix xfail panic test for esp32s2 --- tools/test_apps/system/panic/pytest_panic.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index b462bd6027..7d3180af94 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -991,9 +991,7 @@ def test_rtc_fast_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) # TODO: IDF-6820: ESP32-S2 -> Fix multiple panic reasons in different runs @pytest.mark.generic -@pytest.mark.xfail( - 'config.getvalue("target") == "esp32s2"', reason='Multiple panic reasons for the same test may surface', run=False -) +@pytest.mark.xfail(targets=['esp32s2'], reason='Multiple panic reasons for the same test may surface', run=False) @idf_parametrize('config, target', CONFIGS_MEMPROT_RTC_FAST_MEM, indirect=['config', 'target']) @pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 rev3 migration, IDF-14348') def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str) -> None: