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