Browse Source

custom linker script to keep end of flash clear

Thomas Buck 6 months ago
parent
commit
9b03fe6823
3 changed files with 240 additions and 1 deletions
  1. 2
    0
      CMakeLists.txt
  2. 1
    1
      src/mem.c
  3. 237
    0
      src/memmap_custom.ld

+ 2
- 0
CMakeLists.txt View File

@@ -157,6 +157,8 @@ target_compile_definitions(gadget PUBLIC
157 157
     CYW43_LWIP=0
158 158
 )
159 159
 
160
+pico_set_linker_script(gadget ${CMAKE_CURRENT_SOURCE_DIR}/src/memmap_custom.ld)
161
+
160 162
 # fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
161 163
 target_compile_definitions(gadget PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1)
162 164
 

+ 1
- 1
src/mem.c View File

@@ -31,10 +31,10 @@
31 31
 /*
32 32
  * Last two flash pages are used by BTstack.
33 33
  * So we use the third-last page for our persistent storage.
34
+ * This is kept clear by our custom linker script.
34 35
  */
35 36
 #define FLASH_OFFSET (PICO_FLASH_BANK_STORAGE_OFFSET - FLASH_SECTOR_SIZE)
36 37
 
37
-// TODO make sure last flash page is not filled by compiler
38 38
 // TODO add checksum
39 39
 
40 40
 static struct mem_data data_ram = MEM_DATA_INIT;

+ 237
- 0
src/memmap_custom.ld View File

@@ -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
+

Loading…
Cancel
Save