1/* Based on GCC ARM embedded samples.
2   Defines the following symbols for use by code:
3    __exidx_start
4    __exidx_end
5    __etext
6    __data_start__
7    __preinit_array_start
8    __preinit_array_end
9    __init_array_start
10    __init_array_end
11    __fini_array_start
12    __fini_array_end
13    __data_end__
14    __bss_start__
15    __bss_end__
16    __end__
17    end
18    __HeapLimit
19    __StackLimit
20    __StackTop
21    __stack (== StackTop)
22*/
23
24MEMORY
25{
26    RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k
27    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
28    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
29}
30
31ENTRY(_entry_point)
32
33SECTIONS
34{
35    /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger
36       entry (ELF entry point), are *first* in the image, and the vector table
37       follows immediately afterward. This is because the bootrom enters RAM
38       binaries directly at their lowest address (preferring main RAM over XIP
39       cache-as-SRAM if both are used).
40    */
41
42    .text : {
43        __logical_binary_start = .;
44        __reset_start = .;
45        KEEP (*(.reset))
46        __reset_end = .;
47        KEEP (*(.binary_info_header))
48        __binary_info_header_end = .;
49        KEEP (*(.embedded_block))
50        __embedded_block_end = .;
51        . = ALIGN(256);
52        KEEP (*(.vectors))
53        *(.time_critical*)
54        *(.text*)
55        . = ALIGN(4);
56        *(.init)
57        *(.fini)
58        /* Pull all c'tors into .text */
59        *crtbegin.o(.ctors)
60        *crtbegin?.o(.ctors)
61        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
62        *(SORT(.ctors.*))
63        *(.ctors)
64        /* Followed by destructors */
65        *crtbegin.o(.dtors)
66        *crtbegin?.o(.dtors)
67        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
68        *(SORT(.dtors.*))
69        *(.dtors)
70
71        *(.eh_frame*)
72    } > RAM
73
74    .rodata : {
75        . = ALIGN(4);
76        *(.rodata*)
77        . = ALIGN(4);
78        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
79        . = ALIGN(4);
80    } > RAM
81
82    .ARM.extab :
83    {
84        *(.ARM.extab* .gnu.linkonce.armextab.*)
85    } > RAM
86
87    __exidx_start = .;
88    .ARM.exidx :
89    {
90        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
91    } > RAM
92    __exidx_end = .;
93
94    /* Machine inspectable binary information */
95    . = ALIGN(4);
96    __binary_info_start = .;
97    .binary_info :
98    {
99        KEEP(*(.binary_info.keep.*))
100        *(.binary_info.*)
101    } > RAM
102    __binary_info_end = .;
103    . = ALIGN(4);
104
105    .data : {
106        __data_start__ = .;
107        *(vtable)
108        *(.data*)
109
110        . = ALIGN(4);
111        *(.after_data.*)
112        . = ALIGN(4);
113        /* preinit data */
114        PROVIDE_HIDDEN (__mutex_array_start = .);
115        KEEP(*(SORT(.mutex_array.*)))
116        KEEP(*(.mutex_array))
117        PROVIDE_HIDDEN (__mutex_array_end = .);
118
119        . = ALIGN(4);
120        /* preinit data */
121        PROVIDE_HIDDEN (__preinit_array_start = .);
122        KEEP(*(SORT(.preinit_array.*)))
123        KEEP(*(.preinit_array))
124        PROVIDE_HIDDEN (__preinit_array_end = .);
125
126        . = ALIGN(4);
127        /* init data */
128        PROVIDE_HIDDEN (__init_array_start = .);
129        KEEP(*(SORT(.init_array.*)))
130        KEEP(*(.init_array))
131        PROVIDE_HIDDEN (__init_array_end = .);
132
133        . = ALIGN(4);
134        /* finit data */
135        PROVIDE_HIDDEN (__fini_array_start = .);
136        *(SORT(.fini_array.*))
137        *(.fini_array)
138        PROVIDE_HIDDEN (__fini_array_end = .);
139
140        *(.jcr)
141        . = ALIGN(4);
142   } > RAM
143
144    .tdata : {
145        . = ALIGN(4);
146		*(.tdata .tdata.* .gnu.linkonce.td.*)
147        /* All data end */
148        __tdata_end = .;
149    } > RAM
150    PROVIDE(__data_end__ = .);
151
152    .uninitialized_data (NOLOAD): {
153        . = ALIGN(4);
154        *(.uninitialized_data*)
155    } > RAM
156    /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
157    __etext = LOADADDR(.data);
158
159    .tbss (NOLOAD) : {
160        . = ALIGN(4);
161        __bss_start__ = .;
162        __tls_base = .;
163        *(.tbss .tbss.* .gnu.linkonce.tb.*)
164        *(.tcommon)
165
166        __tls_end = .;
167    } > RAM
168
169    .bss (NOLOAD) : {
170        . = ALIGN(4);
171        __tbss_end = .;
172
173        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
174        *(COMMON)
175        . = ALIGN(4);
176        __bss_end__ = .;
177    } > RAM
178
179    .heap (NOLOAD):
180    {
181        __end__ = .;
182        end = __end__;
183        KEEP(*(.heap*))
184    } > RAM
185    /* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
186       to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
187    __HeapLimit = ORIGIN(RAM) + LENGTH(RAM);
188
189    /* Start and end symbols must be word-aligned */
190    .scratch_x : {
191        __scratch_x_start__ = .;
192        *(.scratch_x.*)
193        . = ALIGN(4);
194        __scratch_x_end__ = .;
195    } > SCRATCH_X
196    __scratch_x_source__ = LOADADDR(.scratch_x);
197
198    .scratch_y : {
199        __scratch_y_start__ = .;
200        *(.scratch_y.*)
201        . = ALIGN(4);
202        __scratch_y_end__ = .;
203    } > SCRATCH_Y
204    __scratch_y_source__ = LOADADDR(.scratch_y);
205
206    /* .stack*_dummy section doesn't contains any symbols. It is only
207     * used for linker to calculate size of stack sections, and assign
208     * values to stack symbols later
209     *
210     * stack1 section may be empty/missing if platform_launch_core1 is not used */
211
212    /* by default we put core 0 stack at the end of scratch Y, so that if core 1
213     * stack is not used then all of SCRATCH_X is free.
214     */
215    .stack1_dummy (NOLOAD):
216    {
217        *(.stack1*)
218    } > SCRATCH_X
219    .stack_dummy (NOLOAD):
220    {
221        KEEP(*(.stack*))
222    } > SCRATCH_Y
223
224    /* stack limit is poorly named, but historically is maximum heap ptr */
225    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
226    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
227    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
228    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
229    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
230    PROVIDE(__stack = __StackTop);
231
232    /* picolibc and LLVM */
233    PROVIDE (__heap_start = __end__);
234    PROVIDE (__heap_end = __HeapLimit);
235    PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
236    PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
237    PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
238
239    /* llvm-libc */
240    PROVIDE (_end = __end__);
241    PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
242
243    /* Check if data + heap + stack exceeds RAM limit */
244    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
245
246    ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
247    /* todo assert on extra code */
248}
249
250