feat(esp_system): riscv: refactor linker scripts to reduce duplicated code

This commit is contained in:
Alexey Lapshin
2026-01-28 18:57:11 +07:00
committed by BOT
parent 799c800494
commit 6bd63cc577
30 changed files with 952 additions and 4882 deletions
+13 -21
View File
@@ -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;
+6 -355
View File
@@ -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.")
+14 -25
View File
@@ -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;
+7 -470
View File
@@ -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.")
+15 -28
View File
@@ -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;
+8 -531
View File
@@ -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.")
+14 -27
View File
@@ -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;
+7 -477
View File
@@ -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"
}
+10 -22
View File
@@ -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;
@@ -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.")
+14 -27
View File
@@ -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;
+7 -479
View File
@@ -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"
}
+13 -27
View File
@@ -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;
@@ -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"
}
+8 -21
View File
@@ -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;
+6 -318
View File
@@ -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.")
+27 -30
View File
@@ -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;
+9 -566
View File
@@ -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"
}
@@ -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"
}
+1 -5
View File
@@ -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")
+5
View File
@@ -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]
@@ -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.*) }
@@ -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
}
+116
View File
@@ -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
@@ -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
+260
View File
@@ -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
@@ -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.")
+97
View File
@@ -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.")
+170
View File
@@ -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
+15
View File
@@ -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