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