1/*
2 * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/* Default entry point */
8ENTRY(call_start_cpu0);
9
10SECTIONS
11{
12  /**
13   * RTC fast memory holds RTC wake stub code,
14   * including from any source file named rtc_wake_stub*.c
15   */
16  .rtc.text :
17  {
18    . = ALIGN(4);
19    _rtc_fast_start = ABSOLUTE(.);
20    _rtc_text_start = ABSOLUTE(.);
21    *(.rtc.entry.text)
22
23    mapping[rtc_text]
24
25    *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
26    *(.rtc_text_end_test)
27
28    /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */
29    . += _esp_memprot_prefetch_pad_size;
30    . = ALIGN(4);
31
32    _rtc_text_end = ABSOLUTE(.);
33  } > lp_ram_seg
34
35  /**
36   * This section located in RTC FAST Memory area.
37   * It holds data marked with RTC_FAST_ATTR attribute.
38   * See the file "esp_attr.h" for more information.
39   */
40  .rtc.force_fast :
41  {
42    . = ALIGN(4);
43    _rtc_force_fast_start = ABSOLUTE(.);
44
45    mapping[rtc_force_fast]
46
47    *(.rtc.force_fast .rtc.force_fast.*)
48    . = ALIGN(4) ;
49    _rtc_force_fast_end = ABSOLUTE(.);
50  } > lp_ram_seg
51
52  /**
53   * RTC data section holds RTC wake stub
54   * data/rodata, including from any source file
55   * named rtc_wake_stub*.c and the data marked with
56   * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
57   */
58  .rtc.data :
59  {
60    _rtc_data_start = ABSOLUTE(.);
61
62    mapping[rtc_data]
63
64    *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .srodata.*)
65    _rtc_data_end = ABSOLUTE(.);
66  } > lp_ram_seg
67
68  /* RTC bss, from any source file named rtc_wake_stub*.c */
69  .rtc.bss (NOLOAD) :
70  {
71    _rtc_bss_start = ABSOLUTE(.);
72    *rtc_wake_stub*.*(.bss .bss.* .sbss .sbss.*)
73    *rtc_wake_stub*.*(COMMON)
74
75    mapping[rtc_bss]
76
77    _rtc_bss_end = ABSOLUTE(.);
78  } > lp_ram_seg
79
80  /**
81   * This section holds data that should not be initialized at power up
82   * and will be retained during deep sleep.
83   * User data marked with RTC_NOINIT_ATTR will be placed
84   * into this section. See the file "esp_attr.h" for more information.
85   */
86  .rtc_noinit (NOLOAD):
87  {
88    . = ALIGN(4);
89    _rtc_noinit_start = ABSOLUTE(.);
90    *(.rtc_noinit .rtc_noinit.*)
91    . = ALIGN(4) ;
92    _rtc_noinit_end = ABSOLUTE(.);
93  } > lp_ram_seg
94
95  /**
96   * This section located in RTC SLOW Memory area.
97   * It holds data marked with RTC_SLOW_ATTR attribute.
98   * See the file "esp_attr.h" for more information.
99   */
100  .rtc.force_slow :
101  {
102    . = ALIGN(4);
103    _rtc_force_slow_start = ABSOLUTE(.);
104    *(.rtc.force_slow .rtc.force_slow.*)
105    . = ALIGN(4) ;
106    _rtc_force_slow_end = ABSOLUTE(.);
107  } > lp_ram_seg
108
109  /**
110   * This section holds RTC data that should have fixed addresses.
111   * The data are not initialized at power-up and are retained during deep sleep.
112   */
113  .rtc_reserved (NOLOAD):
114  {
115    . = ALIGN(4);
116    _rtc_reserved_start = ABSOLUTE(.);
117    /* New data can only be added here to ensure existing data are not moved.
118       Because data have adhered to the end of the segment and code is relied on it.
119       >> put new data here << */
120
121    *(.rtc_timer_data_in_rtc_mem .rtc_timer_data_in_rtc_mem.*)
122    KEEP(*(.bootloader_data_rtc_mem .bootloader_data_rtc_mem.*))
123    _rtc_reserved_end = ABSOLUTE(.);
124  } > rtc_reserved_seg
125
126  _rtc_reserved_length = _rtc_reserved_end - _rtc_reserved_start;
127  ASSERT((_rtc_reserved_length <= LENGTH(rtc_reserved_seg)),
128          "RTC reserved segment data does not fit.")
129
130  /* Get size of rtc slow data based on rtc_data_location alias */
131  _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
132                        ? (_rtc_force_slow_end - _rtc_data_start)
133                        : (_rtc_force_slow_end - _rtc_force_slow_start);
134
135  _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
136                        ? (_rtc_force_fast_end - _rtc_fast_start)
137                        : (_rtc_noinit_end - _rtc_fast_start);
138
139  ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
140          "RTC_SLOW segment data does not fit.")
141
142  ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
143          "RTC_FAST segment data does not fit.")
144
145  .iram0.text :
146  {
147    _iram_start = ABSOLUTE(.);
148    /* Vectors go to start of IRAM */
149    ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
150    KEEP(*(.exception_vectors.text));
151    . = ALIGN(4);
152
153    _invalid_pc_placeholder = ABSOLUTE(.);
154
155    /* Code marked as running out of IRAM */
156    _iram_text_start = ABSOLUTE(.);
157
158    mapping[iram0_text]
159
160  } > iram0_0_seg
161
162  /* Marks the end of IRAM code segment */
163  .iram0.text_end (NOLOAD) :
164  {
165    /* ESP32-C6 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */
166    . += _esp_memprot_prefetch_pad_size;
167    . = ALIGN(_esp_memprot_align_size);
168    /* iram_end_test section exists for use by memprot unit tests only */
169    *(.iram_end_test)
170    _iram_text_end = ABSOLUTE(.);
171  } > iram0_0_seg
172
173  .iram0.data :
174  {
175    . = ALIGN(16);
176    _iram_data_start = ABSOLUTE(.);
177
178    mapping[iram0_data]
179
180    _iram_data_end = ABSOLUTE(.);
181  } > iram0_0_seg
182
183  .iram0.bss (NOLOAD) :
184  {
185    . = ALIGN(16);
186    _iram_bss_start = ABSOLUTE(.);
187
188    mapping[iram0_bss]
189
190    _iram_bss_end = ABSOLUTE(.);
191    . = ALIGN(16);
192    _iram_end = ABSOLUTE(.);
193  } > iram0_0_seg
194
195  /**
196   * This section is required to skip .iram0.text area because iram0_0_seg and
197   * dram0_0_seg reflect the same address space on different buses.
198   */
199  .dram0.dummy (NOLOAD):
200  {
201    . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
202  } > dram0_0_seg
203
204  .dram0.data :
205  {
206    _data_start = ABSOLUTE(.);
207    *(.gnu.linkonce.d.*)
208    *(.data1)
209    __global_pointer$ = . + 0x800;
210    *(.sdata)
211    *(.sdata.*)
212    *(.gnu.linkonce.s.*)
213    *(.gnu.linkonce.s2.*)
214    *(.jcr)
215
216    mapping[dram0_data]
217
218    _data_end = ABSOLUTE(.);
219    . = ALIGN(4);
220  } > dram0_0_seg
221
222  /**
223   * This section holds data that should not be initialized at power up.
224   * The section located in Internal SRAM memory region. The macro _NOINIT
225   * can be used as attribute to place data into this section.
226   * See the "esp_attr.h" file for more information.
227   */
228  .noinit (NOLOAD):
229  {
230    . = ALIGN(4);
231    _noinit_start = ABSOLUTE(.);
232    *(.noinit .noinit.*)
233    . = ALIGN(4) ;
234    _noinit_end = ABSOLUTE(.);
235  } > dram0_0_seg
236
237  /* Shared RAM */
238  .dram0.bss (NOLOAD) :
239  {
240    . = ALIGN (8);
241    _bss_start = ABSOLUTE(.);
242
243    mapping[dram0_bss]
244
245    *(.dynsbss)
246    *(.sbss)
247    *(.sbss.*)
248    *(.gnu.linkonce.sb.*)
249    *(.scommon)
250    *(.sbss2)
251    *(.sbss2.*)
252    *(.gnu.linkonce.sb2.*)
253    *(.dynbss)
254    *(.share.mem)
255    *(.gnu.linkonce.b.*)
256
257    . = ALIGN (8);
258    _bss_end = ABSOLUTE(.);
259  } > dram0_0_seg
260
261  ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
262
263  .flash.text :
264  {
265    _stext = .;
266    _instruction_reserved_start = ABSOLUTE(.);  /* This is a symbol marking the flash.text start, this can be used for mmu driver to maintain virtual address */
267    _text_start = ABSOLUTE(.);
268
269    mapping[flash_text]
270
271    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
272    *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
273    *(.fini.literal)
274    *(.fini)
275    *(.gnu.version)
276
277    /** CPU will try to prefetch up to 16 bytes of
278      * of instructions. This means that any configuration (e.g. MMU, PMS) must allow
279      * safe access to up to 16 bytes after the last real instruction, add
280      * dummy bytes to ensure this
281      */
282    . += _esp_flash_mmap_prefetch_pad_size;
283
284    _text_end = ABSOLUTE(.);
285    _instruction_reserved_end = ABSOLUTE(.);  /* This is a symbol marking the flash.text end, this can be used for mmu driver to maintain virtual address */
286    _etext = .;
287
288    /**
289     * Similar to _iram_start, this symbol goes here so it is
290     * resolved by addr2line in preference to the first symbol in
291     * the flash.text segment.
292     */
293    _flash_cache_start = ABSOLUTE(0);
294  } > default_code_seg
295
296  /**
297   * This dummy section represents the .flash.text section but in default_rodata_seg.
298   * Thus, it must have its alignment and (at least) its size.
299   */
300  .flash_rodata_dummy (NOLOAD):
301  {
302    _flash_rodata_dummy_start = .;
303    /* Start at the same alignment constraint than .flash.text */
304    . = ALIGN(ALIGNOF(.flash.text));
305    /* Create an empty gap as big as .flash.text section */
306    . = . + SIZEOF(.flash.text);
307    /* Prepare the alignment of the section above. Few bytes (0x20) must be
308     * added for the mapping header. */
309    . = ALIGN(_esp_mmu_block_size) + 0x20;
310  } > default_rodata_seg
311
312  .flash.appdesc : ALIGN(0x10)
313  {
314    _rodata_reserved_start = ABSOLUTE(.);  /* This is a symbol marking the flash.rodata start, this can be used for mmu driver to maintain virtual address */
315    _rodata_start = ABSOLUTE(.);
316
317    *(.rodata_desc .rodata_desc.*)               /* Should be the first.  App version info.        DO NOT PUT ANYTHING BEFORE IT! */
318    *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
319
320    /* Create an empty gap within this section. Thanks to this, the end of this
321     * section will match .flash.rodata's begin address. Thus, both sections
322     * will be merged when creating the final bin image. */
323    . = ALIGN(ALIGNOF(.flash.rodata));
324  } >default_rodata_seg
325
326  .flash.rodata : ALIGN(0x10)
327  {
328    _flash_rodata_start = ABSOLUTE(.);
329
330    mapping[flash_rodata]
331
332    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
333    *(.gnu.linkonce.r.*)
334    *(.rodata1)
335    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
336    *(.xt_except_table)
337    *(.gcc_except_table .gcc_except_table.*)
338    *(.gnu.linkonce.e.*)
339    *(.gnu.version_r)
340    . = (. + 7) & ~ 3;
341    /*
342     * C++ constructor and destructor tables
343     * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt.
344     *
345     * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead.
346     * But the init_priority sections will be sorted for iteration in ascending order during startup.
347     * The rest of the init_array sections is sorted for iteration in descending order during startup, however.
348     * Hence a different section is generated for the init_priority functions which is iterated in
349     * ascending order during startup. The corresponding code can be found in startup.c.
350     */
351    __init_priority_array_start = ABSOLUTE(.);
352    KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
353    __init_priority_array_end = ABSOLUTE(.);
354    __init_array_start = ABSOLUTE(.);
355    KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
356    __init_array_end = ABSOLUTE(.);
357    KEEP (*crtbegin.*(.dtors))
358    KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
359    KEEP (*(SORT(.dtors.*)))
360    KEEP (*(.dtors))
361    /* C++ exception handlers table: */
362    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
363    *(.xt_except_desc)
364    *(.gnu.linkonce.h.*)
365    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
366    *(.xt_except_desc_end)
367    *(.dynamic)
368    *(.gnu.version_d)
369    /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */
370    soc_reserved_memory_region_start = ABSOLUTE(.);
371    KEEP (*(.reserved_memory_address))
372    soc_reserved_memory_region_end = ABSOLUTE(.);
373    /* System init functions registered via ESP_SYSTEM_INIT_FN */
374    _esp_system_init_fn_array_start = ABSOLUTE(.);
375    KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
376    _esp_system_init_fn_array_end = ABSOLUTE(.);
377    _rodata_end = ABSOLUTE(.);
378    /* Literals are also RO data. */
379    _lit4_start = ABSOLUTE(.);
380    *(*.lit4)
381    *(.lit4.*)
382    *(.gnu.linkonce.lit4.*)
383    _lit4_end = ABSOLUTE(.);
384    . = ALIGN(4);
385    _thread_local_start = ABSOLUTE(.);
386    *(.tdata)
387    *(.tdata.*)
388    *(.tbss)
389    *(.tbss.*)
390    _thread_local_end = ABSOLUTE(.);
391    . = ALIGN(ALIGNOF(.eh_frame));
392  } > default_rodata_seg
393
394  /* Keep this section shall be at least aligned on 4 */
395  .eh_frame : ALIGN(8)
396  {
397    __eh_frame = ABSOLUTE(.);
398    KEEP (*(.eh_frame))
399    __eh_frame_end = ABSOLUTE(.);
400    /* Guarantee that this section and the next one will be merged by making
401     * them adjacent. */
402    . = ALIGN(ALIGNOF(.eh_frame_hdr));
403  } > default_rodata_seg
404
405  /* To avoid any exception in C++ exception frame unwinding code, this section
406   * shall be aligned on 8. */
407  .eh_frame_hdr : ALIGN(8)
408  {
409    __eh_frame_hdr = ABSOLUTE(.);
410    KEEP (*(.eh_frame_hdr))
411    __eh_frame_hdr_end = ABSOLUTE(.);
412  } > default_rodata_seg
413
414  /*
415    This section is a place where we dump all the rodata which aren't used at runtime,
416    so as to avoid binary size increase
417  */
418  .flash.rodata_noload (NOLOAD) :
419  {
420    /*
421      This is a symbol marking the flash.rodata end, this can be used for mmu driver to maintain virtual address
422      We don't need to include the noload rodata in this section
423    */
424    _rodata_reserved_end = ABSOLUTE(.);
425    . = ALIGN (4);
426    mapping[rodata_noload]
427  } > default_rodata_seg
428
429  /* Marks the end of data, bss and possibly rodata  */
430  .dram0.heap_start (NOLOAD) :
431  {
432    . = ALIGN (16);
433    _heap_start = ABSOLUTE(.);
434  } > dram0_0_seg
435}
436
437ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
438          "IRAM0 segment data does not fit.")
439
440ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
441          "DRAM segment data does not fit.")
442