2019-05-27 02:29:43 -04:00
|
|
|
/* 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(4);
|
|
|
|
|
|
|
|
mapping[rtc_text]
|
|
|
|
|
|
|
|
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
|
|
|
|
_rtc_text_end = ABSOLUTE(.);
|
|
|
|
} > rtc_iram_seg
|
2019-06-05 22:57:29 -04:00
|
|
|
|
2019-05-27 02:29:43 -04:00
|
|
|
/*
|
2019-06-05 22:57:29 -04:00
|
|
|
This section is required to skip rtc.text area because rtc_iram_seg and
|
2019-05-27 02:29:43 -04:00
|
|
|
rtc_data_seg are reflect the same address space on different buses.
|
|
|
|
*/
|
|
|
|
.rtc.dummy :
|
|
|
|
{
|
|
|
|
_rtc_dummy_start = ABSOLUTE(.);
|
|
|
|
_rtc_fast_start = ABSOLUTE(.);
|
|
|
|
. = SIZEOF(.rtc.text);
|
|
|
|
_rtc_dummy_end = ABSOLUTE(.);
|
|
|
|
} > rtc_data_seg
|
|
|
|
|
2019-06-05 22:57:29 -04:00
|
|
|
/* This section located in RTC FAST Memory area.
|
|
|
|
It holds data marked with RTC_FAST_ATTR attribute.
|
2019-05-27 02:29:43 -04:00
|
|
|
See the file "esp_attr.h" for more information.
|
|
|
|
*/
|
|
|
|
.rtc.force_fast :
|
|
|
|
{
|
|
|
|
. = ALIGN(4);
|
|
|
|
_rtc_force_fast_start = ABSOLUTE(.);
|
|
|
|
*(.rtc.force_fast .rtc.force_fast.*)
|
|
|
|
. = ALIGN(4) ;
|
|
|
|
_rtc_force_fast_end = ABSOLUTE(.);
|
|
|
|
} > 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.
|
2019-06-05 22:57:29 -04:00
|
|
|
The memory location of the data is dependent on
|
2020-04-19 02:19:44 -04:00
|
|
|
CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option.
|
2019-05-27 02:29:43 -04:00
|
|
|
*/
|
|
|
|
.rtc.data :
|
|
|
|
{
|
|
|
|
_rtc_data_start = ABSOLUTE(.);
|
|
|
|
|
|
|
|
mapping[rtc_data]
|
|
|
|
|
|
|
|
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
|
|
|
|
_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.*)
|
|
|
|
*rtc_wake_stub*.*(COMMON)
|
|
|
|
|
|
|
|
mapping[rtc_bss]
|
|
|
|
|
|
|
|
_rtc_bss_end = ABSOLUTE(.);
|
|
|
|
} > rtc_data_location
|
|
|
|
|
2019-06-05 22:57:29 -04:00
|
|
|
/* This section holds data that should not be initialized at power up
|
2019-05-27 02:29:43 -04:00
|
|
|
and will be retained during deep sleep.
|
|
|
|
User data marked with RTC_NOINIT_ATTR will be placed
|
2019-06-05 22:57:29 -04:00
|
|
|
into this section. See the file "esp_attr.h" for more information.
|
|
|
|
The memory location of the data is dependent on
|
2020-04-19 02:19:44 -04:00
|
|
|
CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM option.
|
2019-05-27 02:29:43 -04:00
|
|
|
*/
|
|
|
|
.rtc_noinit (NOLOAD):
|
|
|
|
{
|
|
|
|
. = ALIGN(4);
|
|
|
|
_rtc_noinit_start = ABSOLUTE(.);
|
|
|
|
*(.rtc_noinit .rtc_noinit.*)
|
|
|
|
. = ALIGN(4) ;
|
|
|
|
_rtc_noinit_end = ABSOLUTE(.);
|
|
|
|
} > rtc_data_location
|
|
|
|
|
2019-06-05 22:57:29 -04:00
|
|
|
/* This section located in RTC SLOW Memory area.
|
|
|
|
It holds data marked with RTC_SLOW_ATTR attribute.
|
2019-05-27 02:29:43 -04:00
|
|
|
See the file "esp_attr.h" for more information.
|
|
|
|
*/
|
|
|
|
.rtc.force_slow :
|
|
|
|
{
|
|
|
|
. = ALIGN(4);
|
|
|
|
_rtc_force_slow_start = ABSOLUTE(.);
|
|
|
|
*(.rtc.force_slow .rtc.force_slow.*)
|
|
|
|
. = ALIGN(4) ;
|
|
|
|
_rtc_force_slow_end = ABSOLUTE(.);
|
|
|
|
} > rtc_slow_seg
|
|
|
|
|
|
|
|
/* Get size of rtc slow data based on rtc_data_location alias */
|
2019-06-05 22:57:29 -04:00
|
|
|
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
|
|
|
|
? (_rtc_force_slow_end - _rtc_data_start)
|
2019-05-27 02:29:43 -04:00
|
|
|
: (_rtc_force_slow_end - _rtc_force_slow_start);
|
|
|
|
|
2019-06-05 22:57:29 -04:00
|
|
|
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
|
|
|
|
? (_rtc_force_fast_end - _rtc_fast_start)
|
2019-05-27 02:29:43 -04:00
|
|
|
: (_rtc_noinit_end - _rtc_fast_start);
|
2019-06-05 22:57:29 -04:00
|
|
|
|
2019-05-27 02:29:43 -04:00
|
|
|
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
|
|
|
|
"RTC_SLOW segment data does not fit.")
|
2019-06-05 22:57:29 -04:00
|
|
|
|
2019-05-27 02:29:43 -04:00
|
|
|
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
|
|
|
|
"RTC_FAST segment data does not fit.")
|
|
|
|
|
|
|
|
/* Send .iram0 code to iram */
|
|
|
|
.iram0.vectors :
|
|
|
|
{
|
|
|
|
_iram_start = ABSOLUTE(.);
|
|
|
|
/* Vectors go to IRAM */
|
|
|
|
_init_start = ABSOLUTE(.);
|
|
|
|
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
|
|
|
|
. = 0x0;
|
|
|
|
KEEP(*(.WindowVectors.text));
|
|
|
|
. = 0x180;
|
|
|
|
KEEP(*(.Level2InterruptVector.text));
|
|
|
|
. = 0x1c0;
|
|
|
|
KEEP(*(.Level3InterruptVector.text));
|
|
|
|
. = 0x200;
|
|
|
|
KEEP(*(.Level4InterruptVector.text));
|
|
|
|
. = 0x240;
|
|
|
|
KEEP(*(.Level5InterruptVector.text));
|
|
|
|
. = 0x280;
|
|
|
|
KEEP(*(.DebugExceptionVector.text));
|
|
|
|
. = 0x2c0;
|
|
|
|
KEEP(*(.NMIExceptionVector.text));
|
|
|
|
. = 0x300;
|
|
|
|
KEEP(*(.KernelExceptionVector.text));
|
|
|
|
. = 0x340;
|
|
|
|
KEEP(*(.UserExceptionVector.text));
|
|
|
|
. = 0x3C0;
|
|
|
|
KEEP(*(.DoubleExceptionVector.text));
|
|
|
|
. = 0x400;
|
2020-04-17 09:36:26 -04:00
|
|
|
_invalid_pc_placeholder = ABSOLUTE(.);
|
2019-05-27 02:29:43 -04:00
|
|
|
*(.*Vector.literal)
|
|
|
|
|
|
|
|
*(.UserEnter.literal);
|
|
|
|
*(.UserEnter.text);
|
|
|
|
. = ALIGN (16);
|
|
|
|
*(.entry.text)
|
|
|
|
*(.init.literal)
|
|
|
|
*(.init)
|
|
|
|
_init_end = ABSOLUTE(.);
|
|
|
|
} > iram0_0_seg
|
|
|
|
|
|
|
|
.iram0.text :
|
|
|
|
{
|
|
|
|
/* Code marked as runnning out of IRAM */
|
|
|
|
_iram_text_start = ABSOLUTE(.);
|
|
|
|
|
|
|
|
mapping[iram0_text]
|
|
|
|
|
2020-03-10 11:46:10 -04:00
|
|
|
/* align + add 16B for the possibly overlapping instructions */
|
|
|
|
. = ALIGN(4) + 16;
|
2019-05-27 02:29:43 -04:00
|
|
|
_iram_text_end = ABSOLUTE(.);
|
|
|
|
_iram_end = ABSOLUTE(.);
|
|
|
|
} > iram0_0_seg
|
|
|
|
|
2020-01-21 13:56:33 -05:00
|
|
|
.dram0_reserved_for_iram (NOLOAD):
|
|
|
|
{
|
|
|
|
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
|
|
|
|
} > dram0_0_seg
|
2019-05-27 02:29:43 -04:00
|
|
|
|
|
|
|
.dram0.data :
|
|
|
|
{
|
|
|
|
_data_start = ABSOLUTE(.);
|
|
|
|
_bt_data_start = ABSOLUTE(.);
|
|
|
|
*libbt.a:(.data .data.*)
|
|
|
|
. = ALIGN (4);
|
|
|
|
_bt_data_end = ABSOLUTE(.);
|
|
|
|
_btdm_data_start = ABSOLUTE(.);
|
|
|
|
*libbtdm_app.a:(.data .data.*)
|
|
|
|
. = ALIGN (4);
|
|
|
|
_btdm_data_end = ABSOLUTE(.);
|
|
|
|
*(.gnu.linkonce.d.*)
|
|
|
|
*(.data1)
|
|
|
|
*(.sdata)
|
|
|
|
*(.sdata.*)
|
|
|
|
*(.gnu.linkonce.s.*)
|
|
|
|
*(.sdata2)
|
|
|
|
*(.sdata2.*)
|
|
|
|
*(.gnu.linkonce.s2.*)
|
|
|
|
*(.jcr)
|
|
|
|
|
|
|
|
mapping[dram0_data]
|
|
|
|
|
|
|
|
_data_end = ABSOLUTE(.);
|
|
|
|
. = ALIGN(4);
|
|
|
|
} > 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):
|
|
|
|
{
|
|
|
|
. = ALIGN(4);
|
|
|
|
_noinit_start = ABSOLUTE(.);
|
2019-06-05 22:57:29 -04:00
|
|
|
*(.noinit .noinit.*)
|
2019-05-27 02:29:43 -04:00
|
|
|
. = ALIGN(4) ;
|
|
|
|
_noinit_end = ABSOLUTE(.);
|
|
|
|
} > dram0_0_seg
|
|
|
|
|
|
|
|
/* Shared RAM */
|
|
|
|
.dram0.bss (NOLOAD) :
|
|
|
|
{
|
|
|
|
. = ALIGN (8);
|
|
|
|
_bss_start = ABSOLUTE(.);
|
|
|
|
*(.ext_ram.bss*)
|
|
|
|
_bt_bss_start = ABSOLUTE(.);
|
|
|
|
*libbt.a:(.bss .bss.* COMMON)
|
|
|
|
. = ALIGN (4);
|
|
|
|
_bt_bss_end = ABSOLUTE(.);
|
|
|
|
_btdm_bss_start = ABSOLUTE(.);
|
|
|
|
*libbtdm_app.a:(.bss .bss.* COMMON)
|
|
|
|
. = ALIGN (4);
|
|
|
|
_btdm_bss_end = ABSOLUTE(.);
|
|
|
|
|
|
|
|
mapping[dram0_bss]
|
|
|
|
|
|
|
|
*(.dynsbss)
|
|
|
|
*(.sbss)
|
|
|
|
*(.sbss.*)
|
|
|
|
*(.gnu.linkonce.sb.*)
|
|
|
|
*(.scommon)
|
|
|
|
*(.sbss2)
|
|
|
|
*(.sbss2.*)
|
|
|
|
*(.gnu.linkonce.sb2.*)
|
|
|
|
*(.dynbss)
|
|
|
|
*(.share.mem)
|
|
|
|
*(.gnu.linkonce.b.*)
|
|
|
|
|
|
|
|
. = ALIGN (8);
|
|
|
|
_bss_end = ABSOLUTE(.);
|
|
|
|
/* The heap starts right after end of this section */
|
|
|
|
_heap_start = ABSOLUTE(.);
|
|
|
|
} > dram0_0_seg
|
|
|
|
|
esp32s2: fix THREADPTR calculation, re-enable FreeRTOS TLS tests
1. Clarify THREADPTR calculation in FreeRTOS code, explaining where
the constant 0x10 offset comes from.
2. On the ESP32-S2, .flash.rodata section had different default
alignment (8 bytes instead of 16), which resulted in different offset
of the TLS sections. Unfortunately I haven’t found a way to query
section alignment from C code, or to use a constant value to define
section alignment in the linker script. The linker scripts are
modified to force a fixed 16 byte alignment for .flash.rodata on the
ESP32 and ESP32-S2beta. Note that the base address of .flash.rodata
was already 16 byte aligned, so this has not changed the actual
memory layout of the application.
Full explanation of the calculation below.
Assume we have the TLS template section base address
(tls_section_vma), the address of a TLS variable in the template
(address), and the final relocation value (offset). The linker
calculates:
offset = address - tls_section_vma + align_up(TCB_SIZE, alignment).
At run time, the TLS section gets copied from _thread_local_start
(in .rodata) to task_thread_local_start. Let’s assume that an address
of a variable in the runtime TLS section is runtime_address.
Access to this address will happen by calculating THREADPTR + offset.
So, by a series of substitutions:
THREADPTR + offset = runtime_address THREADPTR = runtime_address - offset
THREADPTR = runtime_address - (address - tls_section_vma + align_up(TCB_SIZE, alignment)) THREADPTR = (runtime_address - address) + tls_section_vma - align_up(TCB_SIZE, alignment)
The difference between runtime_address and address is same as the
difference between task_thread_local_start and _thread_local_start.
And tls_section_vma is the address of .rodata section, i.e.
_rodata_start. So we arrive to
THREADPTR = task_thread_local_start - _thread_local_start + _rodata_start - align_up(TCB_SIZE, alignment).
The idea with TCB_SIZE being added to the THREADPTR when computing
the relocation was to let the OS save TCB pointer in the TREADPTR
register. The location of the run-time TLS section was assumed to be
immediately after the TCB, aligned to whatever the section alignment
was. However in our case the problem is that the run-time TLS section
is stored not next to the TCB, but at the top of the stack. Plus,
even if it was stored next to the TCB, the size of a FreeRTOS TCB is
not equal to 8 bytes (TCB_SIZE hardcoded in the linker). So we have
to calculate THREADPTR in a slightly obscure way, to compensate for
these differences.
Closes IDF-1239
2020-01-20 08:20:02 -05:00
|
|
|
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
|
|
|
.flash.rodata : ALIGN(0x10)
|
2019-05-27 02:29:43 -04:00
|
|
|
{
|
2020-04-20 07:35:16 -04:00
|
|
|
_rodata_reserved_start = ABSOLUTE(.);
|
2019-05-27 02:29:43 -04:00
|
|
|
_rodata_start = ABSOLUTE(.);
|
|
|
|
|
|
|
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
|
|
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
|
|
|
|
|
|
|
mapping[flash_rodata]
|
|
|
|
|
|
|
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
|
|
|
*(.gnu.linkonce.r.*)
|
|
|
|
*(.rodata1)
|
|
|
|
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
|
|
|
*(.xt_except_table)
|
|
|
|
*(.gcc_except_table .gcc_except_table.*)
|
|
|
|
*(.gnu.linkonce.e.*)
|
|
|
|
*(.gnu.version_r)
|
|
|
|
. = (. + 3) & ~ 3;
|
|
|
|
__eh_frame = ABSOLUTE(.);
|
|
|
|
KEEP(*(.eh_frame))
|
|
|
|
. = (. + 7) & ~ 3;
|
2019-11-21 05:44:45 -05:00
|
|
|
/* C++ constructor and destructor tables
|
|
|
|
|
|
|
|
Make a point of not including anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt
|
|
|
|
*/
|
2019-05-27 02:29:43 -04:00
|
|
|
__init_array_start = ABSOLUTE(.);
|
2020-04-07 00:55:17 -04:00
|
|
|
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*)))
|
2019-05-27 02:29:43 -04:00
|
|
|
__init_array_end = ABSOLUTE(.);
|
|
|
|
KEEP (*crtbegin.*(.dtors))
|
|
|
|
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
|
|
|
KEEP (*(SORT(.dtors.*)))
|
|
|
|
KEEP (*(.dtors))
|
|
|
|
/* C++ exception handlers table: */
|
|
|
|
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
|
|
|
*(.xt_except_desc)
|
|
|
|
*(.gnu.linkonce.h.*)
|
|
|
|
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
|
|
|
*(.xt_except_desc_end)
|
|
|
|
*(.dynamic)
|
|
|
|
*(.gnu.version_d)
|
|
|
|
/* Addresses of memory regions reserved via
|
|
|
|
SOC_RESERVE_MEMORY_REGION() */
|
|
|
|
soc_reserved_memory_region_start = ABSOLUTE(.);
|
|
|
|
KEEP (*(.reserved_memory_address))
|
|
|
|
soc_reserved_memory_region_end = ABSOLUTE(.);
|
|
|
|
_rodata_end = ABSOLUTE(.);
|
|
|
|
/* Literals are also RO data. */
|
|
|
|
_lit4_start = ABSOLUTE(.);
|
|
|
|
*(*.lit4)
|
|
|
|
*(.lit4.*)
|
|
|
|
*(.gnu.linkonce.lit4.*)
|
|
|
|
_lit4_end = ABSOLUTE(.);
|
|
|
|
. = ALIGN(4);
|
|
|
|
_thread_local_start = ABSOLUTE(.);
|
|
|
|
*(.tdata)
|
|
|
|
*(.tdata.*)
|
|
|
|
*(.tbss)
|
|
|
|
*(.tbss.*)
|
|
|
|
_thread_local_end = ABSOLUTE(.);
|
2020-04-20 07:35:16 -04:00
|
|
|
_rodata_reserved_end = ABSOLUTE(.);
|
2019-05-27 02:29:43 -04:00
|
|
|
. = ALIGN(4);
|
2020-01-21 12:07:02 -05:00
|
|
|
} >default_rodata_seg
|
2019-05-27 02:29:43 -04:00
|
|
|
|
|
|
|
.flash.text :
|
|
|
|
{
|
|
|
|
_stext = .;
|
2020-04-20 07:35:16 -04:00
|
|
|
_instruction_reserved_start = ABSOLUTE(.);
|
2019-05-27 02:29:43 -04:00
|
|
|
_text_start = ABSOLUTE(.);
|
|
|
|
|
|
|
|
mapping[flash_text]
|
|
|
|
|
|
|
|
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
|
|
|
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
|
|
|
|
*(.fini.literal)
|
|
|
|
*(.fini)
|
|
|
|
*(.gnu.version)
|
|
|
|
_text_end = ABSOLUTE(.);
|
2020-04-20 07:35:16 -04:00
|
|
|
_instruction_reserved_end = ABSOLUTE(.);
|
2019-05-27 02:29:43 -04:00
|
|
|
_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);
|
2020-01-21 12:07:02 -05:00
|
|
|
} >default_code_seg
|
|
|
|
|
|
|
|
/* Marks the end of IRAM code segment */
|
|
|
|
.iram0.text_end (NOLOAD) :
|
|
|
|
{
|
|
|
|
. = ALIGN (4);
|
|
|
|
_iram_end = ABSOLUTE(.);
|
|
|
|
} > iram0_0_seg
|
|
|
|
|
|
|
|
/* Marks the end of data, bss and possibly rodata */
|
|
|
|
.dram0.heap_start (NOLOAD) :
|
|
|
|
{
|
|
|
|
. = ALIGN (8);
|
|
|
|
_heap_start = ABSOLUTE(.);
|
|
|
|
} > dram0_0_seg
|
2019-05-27 02:29:43 -04:00
|
|
|
}
|
2020-01-21 12:07:02 -05:00
|
|
|
|
|
|
|
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
|
|
|
"IRAM0 segment data does not fit.")
|
|
|
|
|
2020-01-21 13:56:33 -05:00
|
|
|
ASSERT(((_heap_start - _data_start) <= LENGTH(dram0_0_seg)),
|
2020-01-21 12:07:02 -05:00
|
|
|
"DRAM segment data does not fit.")
|