8000 ports/rp2: PSRAM linker script. · pimoroni/micropython@888f52f · GitHub
[go: up one dir, main page]

Skip to content

Commit 888f52f

Browse files
MichaelBellGadgetoid
authored andcommitted
ports/rp2: PSRAM linker script.
1 parent cc1e8db commit 888f52f

File tree

4 files changed

+339
-6
lines changed

4 files changed

+339
-6
lines changed

ports/rp2/CMakeLists.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,13 @@ set(MICROPY_SOURCE_PORT
173173
${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c
174174
)
175175

176-
if(PICO_RP2350)
176+
if(MICROPY_HW_ENABLE_PSRAM)
177177
list(APPEND MICROPY_SOURCE_PORT
178178
rp2_psram.c
179179
)
180+
target_compile_definitions(${MICROPY_TARGET} PRIVATE
181+
MICROPY_HW_ENABLE_PSRAM=1
182+
)
180183
endif()
181184

182185
set(MICROPY_SOURCE_QSTR
@@ -598,7 +601,11 @@ if (PICO_ON_DEVICE AND NOT PICO_NO_FLASH AND NOT PICO_COPY_TO_RAM)
598601
if(PICO_RP2040)
599602
pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp_rp2040.ld)
600603
elseif(PICO_RP2350)
601-
pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp_rp2350.ld)
604+
if (MICROPY_HW_ENABLE_PSRAM)
605+
pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp_rp2350_psram.ld)
606+
else()
607+
pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp_rp2350.ld)
608+
endif()
602609
endif()
603610
endif()
604611

ports/rp2/main.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070

7171
extern uint8_t __StackTop, __StackBottom;
7272
extern uint8_t __GcHeapStart, __GcHeapEnd;
73+
extern uint8_t __PsramGcHeapStart, __PsramGcHeapEnd;
7374

7475
// Embed version info in the binary in machine readable form
7576
bi_decl(bi_program_version_string(MICROPY_GIT_TAG));
@@ -132,11 +133,16 @@ int main(int argc, char **argv) {
132133

133134
#if defined(MICROPY_HW_PSRAM_CS_PIN) && MICROPY_HW_ENABLE_PSRAM
134135
if (psram_size) {
136+
// Linker script assumes a 2MB PSRAM, increase the size accordingly.
137+
size_t psram_additional_size = 0;
138+
if (psram_size > 2 * 1024 * 1024) {
139+
psram_additional_size = psram_size - 2 * 1024 * 1024;
140+
}
135141
#if MICROPY_GC_SPLIT_HEAP
136142
gc_init(&__GcHeapStart, &__GcHeapEnd);
137-
gc_add((void *)PSRAM_LOCATION, (void *)(PSRAM_LOCATION + psram_size));
143+
gc_add(&__PsramGcHeapStart, &__PsramGcHeapEnd + psram_additional_size);
138144
#else
139-
gc_init((void *)PSRAM_LOCATION, (void *)(PSRAM_LOCATION + psram_size));
145+
gc_init(&__PsramGcHeapStart, &__PsramGcHeapEnd + psram_additional_size);
140146
#endif
141147
} else {
142148
gc_init(&__GcHeapStart, &__GcHeapEnd);

ports/rp2/memmap_mp_rp2350_psram.ld

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
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+
24+
MEMORY
25+
{
26+
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 4096k
27+
RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k
28+
SCRATCH_X(rwx) : ORIGIN = 0x20080000, LENGTH = 4k
29+
SCRATCH_Y(rwx) : ORIGIN = 0x20081000, LENGTH = 4k
30+
PSRAM(rw) : ORIGIN = 0x11000000, LENGTH = 2048k
31+
}
32+
33+
ENTRY(_entry_point)
34+
35+
SECTIONS
36+
{
37+
.flash_begin : {
38+
__flash_binary_start = .;
39+
} > FLASH
40+
41+
/* The bootrom will enter the image at the point indicated in your
42+
IMAGE_DEF, which is usually the reset handler of your vector table.
43+
44+
The debugger will use the ELF entry point, which is the _entry_point
45+
symbol, and in our case is *different from the bootrom's entry point.*
46+
This is used to go back through the bootrom on debugger launches only,
47+
to perform the same initial flash setup that would be performed on a
48+
cold boot.
49+
*/
50+
51+
.text : {
52+
__logical_binary_start = .;
53+
KEEP (*(.vectors))
54+
KEEP (*(.binary_info_header))
55+
__binary_info_header_end = .;
56+
KEEP (*(.embedded_block))
57+
__embedded_block_end = .;
58+
KEEP (*(.reset))
59+
/* TODO revisit this now memset/memcpy/float in ROM */
60+
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
61+
* FLASH ... we will include any thing excluded here in .data below by default */
62+
*(.init)
63+
*libgcc.a:cmse_nonsecure_call.o
64+
/* Change for MicroPython... exclude gc.c, parse.c, vm.c from flash */
65+
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a: *gc.c.obj *vm.c.obj *parse.c.obj) .text*)
66+
*(.fini)
67+
/* Pull all c'tors into .text */
68+
*crtbegin.o(.ctors)
69+
*crtbegin?.o(.ctors)
70+
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
71+
*(SORT(.ctors.*))
72+
*(.ctors)
73+
/* Followed by destructors */
74+
*crtbegin.o(.dtors)
75+
*crtbegin?.o(.dtors)
76+
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
77+
*(SORT(.dtors.*))
78+
*(.dtors)
79+
80+
. = ALIGN(4);
81+
/* preinit data */
82+
PROVIDE_HIDDEN (__preinit_array_start = .);
83+
KEEP(*(SORT(.preinit_array.*)))
84+
KEEP(*(.preinit_array))
85+
PROVIDE_HIDDEN (__preinit_array_end = .);
86+
87+
. = ALIGN(4);
88+
/* init data */
89+
PROVIDE_HIDDEN (__init_array_start = .);
90+
KEEP(*(SORT(.init_array.*)))
91+
KEEP(*(.init_array))
92+
PROVIDE_HIDDEN (__init_array_end = .);
93+
94+
. = ALIGN(4);
95+
/* finit data */
96+
PROVIDE_HIDDEN (__fini_array_start = .);
97+
*(SORT(.fini_array.*))
98+
*(.fini_array)
99+
PROVIDE_HIDDEN (__fini_array_end = .);
100+
*(.eh_frame*)
101+
. = ALIGN(4);
102+
} > FLASH
103+
104+
/* Note the boot2 section is optional, and should be discarded if there is
105+
no reference to it *inside* the binary, as it is not called by the
106+
bootrom. (The bootrom performs a simple best-effort XIP setup and
107+
leaves it to the binary to do anything more sophisticated.) However
108+
there is still a size limit of 256 bytes, to ensure the boot2 can be
109+
stored in boot RAM.
110+
111+
Really this is a "XIP setup function" -- the name boot2 is historic and
112+
refers to its dual-purpose on RP2040, where it also handled vectoring
113+
from the bootrom into the user image.
114+
*/
115+
116+
.boot2 : {
117+
__boot2_start__ = .;
118+
*(.boot2)
119+
__boot2_end__ = .;
120+
} > FLASH
121+
122+
ASSERT(__boot2_end__ - __boot2_start__ <= 256,
123+
"ERROR: Pico second stage bootloader must be no more than 256 bytes in size")
124+
125+
.rodata : {
126+
*(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)
127+
*(.srodata*)
128+
. = ALIGN(4);
129+
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
130+
. = ALIGN(4);
131+
} > FLASH
132+
133+
.ARM.extab :
134+
{
135+
*(.ARM.extab* .gnu.linkonce.armextab.*)
136+
} > FLASH
137+
138+
__exidx_start = .;
139+
.ARM.exidx :
140+
{
141+
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
142+
} > FLASH
143+
__exidx_end = .;
144+
145+
/* Machine inspectable binary information */
146+
. = ALIGN(4);
147+
__binary_info_start = .;
148+
.binary_info :
149+
{
150+
KEEP(*(.binary_info.keep.*))
151+
*(.binary_info.*)
152+
} > FLASH
153+
__binary_info_end = .;
154+
. = ALIGN(4);
155+
156+
.ram_vector_table (NOLOAD): {
157+
*(.ram_vector_table)
158+
} > RAM
159+
160+
.uninitialized_data (NOLOAD): {
161+
. = ALIGN(4);
162+
*(.uninitialized_data*)
163+
} > RAM
164+
165+
.data : {
166+
__data_start__ = .;
167+
*(vtable)
168+
169+
*(.time_critical*)
170+
171+
/* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */
172+
*(.text*)
173+
. = ALIGN(4);
174+
*(.rodata*)
175+
. = ALIGN(4);
176+
177+
*(.data*)
178+
*(.sdata*)
179+
180+
. = ALIGN(4);
181+
*(.after_data.*)
182+
. = ALIGN(4);
183+
/* preinit data */
184+
PROVIDE_HIDDEN (__mutex_array_start = .);
185+
KEEP(*(SORT(.mutex_array.*)))
186+
KEEP(*(.mutex_array))
187+
PROVIDE_HIDDEN (__mutex_array_end = .);
188+
189+
*(.jcr)
190+
. = ALIGN(4);
191+
} > RAM AT> FLASH
192+
193+
.tdata : {
194+
. = ALIGN(4);
195+
*(.tdata .tdata.* .gnu.linkonce.td.*)
196+
/* All data end */
197+
__tdata_end = .;
198+
} > RAM AT> FLASH
199+
PROVIDE(__data_end__ = .);
200+
201+
/* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
202+
__etext = LOADADDR(.data);
203+
204+
.tbss (NOLOAD) : {
205+
. = ALIGN(4);
206+
__bss_start__ = .;
207+
__tls_base = .;
208+
*(.tbss .tbss.* .gnu.linkonce.tb.*)
209+
*(.tcommon)
210+
211+
__tls_end = .;
212+
} > RAM
213+
214+
.bss (NOLOAD) : {
215+
. = ALIGN(4);
216+
__tbss_end = .;
217+
218+
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
219+
*(COMMON)
220+
PROVIDE(__global_pointer$ = . + 2K);
221+
*(.sbss*)
222+
. = ALIGN(4);
223+
__bss_end__ = .;
224+
} > RAM
225+
226+
.heap (NOLOAD):
227+
{
228+
__end__ = .;
229+
end = __end__;
230+
KEEP(*(.heap*))
231+
/* historically on GCC sbrk was growing past __HeapLimit to __StackLimit, however
232+
to be more compatible, we now set __HeapLimit explicitly to where the end of the heap is */
233+
/* Change for MicroPython: don't include this, it increases reported firmware size.
234+
/* . = ORIGIN(RAM) + LENGTH(RAM); */
235+
__HeapLimit = .;
236+
} > RAM
237+
238+
/* Start and end symbols must be word-aligned */
239+
.scratch_x : {
240+
__scratch_x_start__ = .;
241+
*(.scratch_x.*)
242+
. = ALIGN(4);
243+
__scratch_x_end__ = .;
244+
} > SCRATCH_X AT > FLASH
245+
__scratch_x_source__ = LOADADDR(.scratch_x);
246+
247+
.scratch_y : {
248+
__scratch_y_start__ = .;
249+
*(.scratch_y.*)
250+
. = ALIGN(4);
251+
__scratch_y_end__ = .;
252+
} > SCRATCH_Y AT > FLASH
253+
__scratch_y_source__ = LOADADDR(.scratch_y);
254+
255+
/* .stack*_dummy section doesn't contains any symbols. It is only
256+
* used for linker to calculate size of stack sections, and assign
257+
* values to stack symbols later
258+
*
259+
* stack1 section may be empty/missing if platform_launch_core1 is not used */
260+
261+
/* by default we put core 0 stack at the end of scratch Y, so that if core 1
262+
* stack is not used then all of SCRATCH_X is free.
263+
*/
264+
.stack1_dummy (NOLOAD):
265+
{
266+
*(.stack1*)
267+
} > SCRATCH_X
268+
.stack_dummy (NOLOAD):
269+
{
270+
KEEP(*(.stack*))
271+
} > SCRATCH_Y
272+
273+
.flash_end : {
274+
KEEP(*(.embedded_end_block*))
275+
PROVIDE(__flash_binary_end = .);
276+
} > FLASH =0xaa
277+
278+
/* PSRAM data section */
279+
.psram_data (NOLOAD): {
280+
. = ALIGN(4);
281+
*(.psram_data*)
282+
PROVIDE(__psram_data_end = .);
283+
} > PSRAM
284+
285+
/* stack limit is poorly named, but historically is maximum heap ptr */
286+
__StackLimit = __bss_end__ + __micropy_c_heap_size__;
287+
288+
/* Define start and end of internal RAM GC heap */
289+
__GcHeapStart = __StackLimit; /* after the C heap (sbrk limit) */
290+
__GcHeapEnd = ORIGIN(RAM) + LENGTH(RAM) - __micropy_extra_stack__;
291+
292+
/* Define start and end of PSRAM GC heap */
293+
__PsramGcHeapStart = __psram_data_end; /* after the C heap (sbrk limit) */
294+
__PsramGcHeapEnd = ORIGIN(PSRAM) + LENGTH(PSRAM);
295+
296+
/* Define start and end of C stack */
297+
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
298+
__StackBottom = __GcHeapEnd;
299+
PROVIDE(__stack = __StackTop);
300+
301+
/* picolibc and LLVM */
302+
PROVIDE (__heap_start = __end__);
303+
PROVIDE (__heap_end = __HeapLimit);
304+
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
305+
PROVIDE( __tls_size_align = (__tls_size + __tls_align - 1) & ~(__tls_align - 1));
306+
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
307+
308+
/* llvm-libc */
309+
PROVIDE (_end = __end__);
310+
PROVIDE (__llvm_libc_heap_limit = __HeapLimit);
311+
312+
/* Ensure internal RAM didn't overflow */
313+
ASSERT((__GcHeapEnd - __GcHeapStart) > 0, "Main RAM overflow")
314+
315+
/* Check GC heap is at least 128kB */
316+
ASSERT((__PsramGcHeapEnd - __PsramGcHeapStart) > 128*1024, "GcHeap is too small")
317+
318+
ASSERT( __binary_info_header_end - __logical_binary_start <= 1024, "Binary info must be in first 1024 bytes of the binary")
319+
ASSERT( __embedded_block_end - __logical_binary_start <= 4096, "Embedded block must be in first 4096 bytes of the binary")
320+
321+
/* todo assert on extra code */
322+
}

ports/rp2/rp2_psram.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#ifndef MICROPY_INCLUDED_RP2_MACHINE_PSRAM_H
44
#define MICROPY_INCLUDED_RP2_MACHINE_PSRAM_H
55

6-
#define PSRAM_LOCATION _u(0x11000000)
7-
86
extern size_t psram_init(uint cs_pin);
97

108
#endif

0 commit comments

Comments
 (0)
0