Description
I'm not sure this pertains just to RP2, but I have little experience with other platforms so I'm going to keep the scope narrow unless anyone wants to chime in. That said I think this approach is pretty generic and should be - SDK's willing - portable to other platforms.
The long and short of it is that ports/rp2/boards/PICO/mpconfigboard.h
specifies MICROPY_HW_FLASH_STORAGE_BYTES
which - at runtime - is the region allocated to the user-facing filesystem on an RP2-based MicroPython board.
This is configurable since boards can have 2MB, 4MB, 8MB and 16MB (and maybe beyond?) of Flash storage.
However this region is not enforced by the memmap_mp.ld
linker script used to build the RP2 ports.
The practical upshot of this is that you can build a MicroPython port with too much stuff baked into it (and oh my do we bake in a lot of stuff) which will happily link and flash but then immediately soft-brick the board it's flashed to. (Turns out MicroPython has some pretty important stuff at the high-end of its binary.)
My proposal is either:
- To pre-process the port's memmap_mp.ld in order to configure the flash size correctly (I don't know how we'd do this, but it prevents duplication)
or
- To introduce the concept of board-specific
memmap_mp.ld
files that are auto-detected and used in place of the port one.
The latter would be achieved something like so:
diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt
index a5e421734..2db097364 100644
--- a/ports/rp2/CMakeLists.txt
+++ b/ports/rp2/CMakeLists.txt
@@ -296,7 +296,11 @@ endif()
# a linker script modification) until we explicitly add macro calls around the function
# defs to move them into RAM.
if (PICO_ON_DEVICE AND NOT PICO_NO_FLASH AND NOT PICO_COPY_TO_RAM)
- pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp.ld)
+ if(EXISTS ${MICROPY_BOARD_DIR}/memmap_mp.ld)
+ pico_set_linker_script(${MICROPY_TARGET} ${MICROPY_BOARD_DIR}/memmap_mp.ld)
+ else()
+ pico_set_linker_script(${MICROPY_TARGET} ${CMAKE_CURRENT_LIST_DIR}/memmap_mp.ld)
+ endif()
endif()
pico_add_extra_outputs(${MICROPY_TARGET})
And then boards/PICO/memmap_mp.ld
would correctly configure the flash size:
FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 640k
This ensures that an oversized build (for whatever reason) will fail something like this:
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: firmware.elf section `.rodata' will not fit in region `FLASH'
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: region `FLASH' overflowed by 90736 bytes
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/firmware.dir/build.make:9088: firmware.elf] Error 1
make[2]: *** [CMakeFiles/Makefile2:1553: CMakeFiles/firmware.dir/all] Error 2
make[1]: *** [Makefile:91: all] Error 2
make: *** [Makefile:23: all] Error 2
Rather than failing when it's flashed, run and inevitably overwrites something important!