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    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
27    RAM(rwx) : ORIGIN =  0x21000000, LENGTH = 256k
28    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
29    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
30}
31
32ENTRY(_entry_point)
33
34SECTIONS
35{
36    /* Second stage bootloader is prepended to the image. It must be 256 bytes big
37       and checksummed. It is usually built by the boot_stage2 target
38       in the Raspberry Pi Pico SDK
39    */
40
41    .flash_begin : {
42        __flash_binary_start = .;
43    } > FLASH
44
45    .boot2 : {
46        __boot2_start__ = .;
47        KEEP (*(.boot2))
48        __boot2_end__ = .;
49    } > FLASH
50
51    ASSERT(__boot2_end__ - __boot2_start__ == 256,
52        "ERROR: Pico second stage bootloader must be 256 bytes in size")
53
54    /* The second stage will always enter the image at the start of .text.
55       The debugger will use the ELF entry point, which is the _entry_point
56       symbol if present, otherwise defaults to start of .text.
57       This can be used to transfer control back to the bootrom on debugger
58       launches only, to perform proper flash setup.
59    */
60
61    .text : {
62        __logical_binary_start = .;
63        KEEP (*(.vectors))
64        KEEP (*(.binary_info_header))
65        __binary_info_header_end = .;
66        KEEP (*(.reset))
67        /* TODO revisit this now memset/memcpy/float in ROM */
68        /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
69         * FLASH ... we will include any thing excluded here in .data below by default */
70        *(.init)
71        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)
72        *(.fini)
73        /* Pull all c'tors into .text */
74        *crtbegin.o(.ctors)
75        *crtbegin?.o(.ctors)
76        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
77        *(SORT(.ctors.*))
78        *(.ctors)
79        /* Followed by destructors */
80        *crtbegin.o(.dtors)
81        *crtbegin?.o(.dtors)
82        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
83        *(SORT(.dtors.*))
84        *(.dtors)
85
86        *(.eh_frame*)
87        . = ALIGN(4);
88    } > FLASH
89
90    .rodata : {
91        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
92        . = ALIGN(4);
93        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
94        . = ALIGN(4);
95    } > FLASH
96
97    .ARM.extab :
98    {
99        *(.ARM.extab* .gnu.linkonce.armextab.*)
100    } > FLASH
101
102    __exidx_start = .;
103    .ARM.exidx :
104    {
105        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
106    } > FLASH
107    __exidx_end = .;
108
109    /* Machine inspectable binary information */
110    . = ALIGN(4);
111    __binary_info_start = .;
112    .binary_info :
113    {
114        KEEP(*(.binary_info.keep.*))
115        *(.binary_info.*)
116    } > FLASH
117    __binary_info_end = .;
118    . = ALIGN(4);
119
120    /* End of .text-like segments */
121    __etext = .;
122
123   .ram_vector_table (COPY): {
124        *(.ram_vector_table)
125    } > RAM
126
127    .data : {
128        __data_start__ = .;
129        *(vtable)
130
131        *(.time_critical*)
132
133        /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
134        *(.text*)
135        . = ALIGN(4);
136        *(.rodata*)
137        . = ALIGN(4);
138
139        *(.data*)
140
141        . = ALIGN(4);
142        *(.after_data.*)
143        . = ALIGN(4);
144        /* preinit data */
145        PROVIDE_HIDDEN (__mutex_array_start = .);
146        KEEP(*(SORT(.mutex_array.*)))
147        KEEP(*(.mutex_array))
148        PROVIDE_HIDDEN (__mutex_array_end = .);
149
150        . = ALIGN(4);
151        /* preinit data */
152        PROVIDE_HIDDEN (__preinit_array_start = .);
153        KEEP(*(SORT(.preinit_array.*)))
154        KEEP(*(.preinit_array))
155        PROVIDE_HIDDEN (__preinit_array_end = .);
156
157        . = ALIGN(4);
158        /* init data */
159        PROVIDE_HIDDEN (__init_array_start = .);
160        KEEP(*(SORT(.init_array.*)))
161        KEEP(*(.init_array))
162        PROVIDE_HIDDEN (__init_array_end = .);
163
164        . = ALIGN(4);
165        /* finit data */
166        PROVIDE_HIDDEN (__fini_array_start = .);
167        *(SORT(.fini_array.*))
168        *(.fini_array)
169        PROVIDE_HIDDEN (__fini_array_end = .);
170
171        *(.jcr)
172        . = ALIGN(4);
173        /* All data end */
174        __data_end__ = .;
175    } > RAM AT> FLASH
176
177    .uninitialized_data (COPY): {
178        . = ALIGN(4);
179        *(.uninitialized_data*)
180    } > RAM
181
182    /* Start and end symbols must be word-aligned */
183    .scratch_x : {
184        __scratch_x_start__ = .;
185        *(.scratch_x.*)
186        . = ALIGN(4);
187        __scratch_x_end__ = .;
188    } > SCRATCH_X AT > FLASH
189    __scratch_x_source__ = LOADADDR(.scratch_x);
190
191    .scratch_y : {
192        __scratch_y_start__ = .;
193        *(.scratch_y.*)
194        . = ALIGN(4);
195        __scratch_y_end__ = .;
196    } > SCRATCH_Y AT > FLASH
197    __scratch_y_source__ = LOADADDR(.scratch_y);
198
199    .bss  : {
200        . = ALIGN(4);
201        __bss_start__ = .;
202        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
203        *(COMMON)
204        . = ALIGN(4);
205        __bss_end__ = .;
206    } > RAM
207
208    .heap (COPY):
209    {
210        __end__ = .;
211        end = __end__;
212        *(.heap*)
213        __HeapLimit = .;
214    } > RAM
215
216    /* .stack*_dummy section doesn't contains any symbols. It is only
217     * used for linker to calculate size of stack sections, and assign
218     * values to stack symbols later
219     *
220     * stack1 section may be empty/missing if platform_launch_core1 is not used */
221
222    /* by default we put core 0 stack at the end of scratch Y, so that if core 1
223     * stack is not used then all of SCRATCH_X is free.
224     */
225    .stack1_dummy (COPY):
226    {
227        *(.stack1*)
228    } > SCRATCH_X
229    .stack_dummy (COPY):
230    {
231        *(.stack*)
232    } > SCRATCH_Y
233
234    .flash_end : {
235        __flash_binary_end = .;
236    } > FLASH
237
238    /* stack limit is poorly named, but historically is maximum heap ptr */
239    __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
240    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
241    __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
242    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
243    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
244    PROVIDE(__stack = __StackTop);
245
246    /* Check if data + heap + stack exceeds RAM limit */
247    ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
248
249    ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
250    /* todo assert on extra code */
251}
252
253