tag:github.com,2008:https://github.com/clockworkpi/PicoCalc/releases Release notes from PicoCalc 2025-11-11T07:28:51Z tag:github.com,2008:Repository/909561369/multi_uf2_bootloader_0.6 2026-03-01T07:47:44Z Multi uf2 bootloader v0.6 <p>This release contains all files in PicoCalc SD card.</p> <h1>PicoCalc SD v0.6</h1> <div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="PicoCalc SD/ ├── BellLabs_Fine.mp3 ├── bifdiag.bas ├── BOOT2040.uf2 ├── bootloader_pico.uf2 ├── cc │   ├── edit.lua │   ├── expect.lua │   ├── internal │   │   ├── menu.lua │   │   └── syntax │   │   ├── errors.lua │   │   ├── init.lua │   │   ├── lexer.lua │   │   └── parser.lua │   └── pretty.lua ├── Chessnovice_johnybot.nes ├── fonts │   ├── 6x10.fnt │   ├── Acer8x8.fnt │   ├── Haxor12.fnt │   ├── HP6x8.fnt │   ├── HP8x8.fnt │   └── ProggyClean.fnt ├── lorenz.bas ├── lua │   ├── asteroids.lua │   ├── boxworld.bmp │   ├── boxworld.lua │   ├── browser.lua │   ├── bubble.lua │   ├── mandelbrot.lua │   └── piano.lua ├── MACHIKAP.INI ├── main.lua ├── mand.bas ├── pico1-apps │   ├── MicroPython_fa8b24c.uf2 │   ├── phyllosoma_kb.uf2 │   ├── PicoCalc_Fuzix_v1.0.uf2 │   ├── PicoCalc_MP3Player_v0.5.uf2 │   ├── PicoCalc_NES_v1.0.uf2 │   ├── PicoCalc_uLisp_v1.1.uf2 │   ├── picolua_daf20a2.uf2 │   ├── PicoMite_v6.02.01b4_beta.uf2 │   └── Picoware_v1.6.9.uf2 ├── picocalc.bmp ├── picoware │   ├── apps │   │   ├── Calculator.mpy │   │   ├── cat-fact.mpy │   │   ├── counter.mpy │   │   ├── flip_social │   │   │   ├── __init__.py │   │   │   ├── password.mpy │   │   │   ├── run.mpy │   │   │   ├── settings.mpy │   │   │   └── username.mpy │   │   ├── FlipSocial.mpy │   │   ├── games │   │   │   ├── 2048.mpy │   │   │   ├── Breakout.mpy │   │   │   ├── example.mpy │   │   │   ├── Flappy Bird.mpy │   │   │   ├── flip_world │   │   │   │   ├── assets.mpy │   │   │   │   ├── general.mpy │   │   │   │   ├── __init__.py │   │   │   │   ├── player.mpy │   │   │   │   ├── run.mpy │   │   │   │   └── sprite.mpy │   │   │   ├── FlipWorld.mpy │   │   │   ├── free_roam │   │   │   │   ├── dynamic_map.mpy │   │   │   │   ├── game.mpy │   │   │   │   ├── __init__.py │   │   │   │   ├── maps.mpy │   │   │   │   ├── player.mpy │   │   │   │   └── sprite.mpy │   │   │   ├── Free Roam.mpy │   │   │   ├── game_of_life.mpy │   │   │   ├── Maze Runner.mpy │   │   │   ├── Minesweeper.mpy │   │   │   ├── Pong.mpy │   │   │   ├── Snake.mpy │   │   │   ├── Soduko.mpy │   │   │   ├── Space Invaders.mpy │   │   │   ├── Tetris.mpy │   │   │   └── Tower Defense.mpy │   │   ├── Graph.mpy │   │   ├── hello_color.mpy │   │   ├── keyboard-simple.mpy │   │   ├── loading-simple.mpy │   │   ├── menu-simple.mpy │   │   ├── random-object.mpy │   │   ├── screensavers │   │   │   ├── Bubble Universe.mpy │   │   │   ├── Clock.mpy │   │   │   ├── Cube.mpy │   │   │   ├── DVI Bounce.mpy │   │   │   ├── Fire Effect.mpy │   │   │   ├── Matrix Rain.mpy │   │   │   ├── Patterns.mpy │   │   │   ├── PicoFlower.mpy │   │   │   ├── Plasma Wave.mpy │   │   │   └── Yin-Yang.mpy │   │   ├── Serial Terminal.mpy │   │   ├── storage-simple.mpy │   │   ├── textbox-simple.mpy │   │   ├── Text Editor.mpy │   │   └── Weather.mpy │   └── settings └── README.md "><pre class="notranslate"><code>PicoCalc SD/ ├── BellLabs_Fine.mp3 ├── bifdiag.bas ├── BOOT2040.uf2 ├── bootloader_pico.uf2 ├── cc │   ├── edit.lua │   ├── expect.lua │   ├── internal │   │   ├── menu.lua │   │   └── syntax │   │   ├── errors.lua │   │   ├── init.lua │   │   ├── lexer.lua │   │   └── parser.lua │   └── pretty.lua ├── Chessnovice_johnybot.nes ├── fonts │   ├── 6x10.fnt │   ├── Acer8x8.fnt │   ├── Haxor12.fnt │   ├── HP6x8.fnt │   ├── HP8x8.fnt │   └── ProggyClean.fnt ├── lorenz.bas ├── lua │   ├── asteroids.lua │   ├── boxworld.bmp │   ├── boxworld.lua │   ├── browser.lua │   ├── bubble.lua │   ├── mandelbrot.lua │   └── piano.lua ├── MACHIKAP.INI ├── main.lua ├── mand.bas ├── pico1-apps │   ├── MicroPython_fa8b24c.uf2 │   ├── phyllosoma_kb.uf2 │   ├── PicoCalc_Fuzix_v1.0.uf2 │   ├── PicoCalc_MP3Player_v0.5.uf2 │   ├── PicoCalc_NES_v1.0.uf2 │   ├── PicoCalc_uLisp_v1.1.uf2 │   ├── picolua_daf20a2.uf2 │   ├── PicoMite_v6.02.01b4_beta.uf2 │   └── Picoware_v1.6.9.uf2 ├── picocalc.bmp ├── picoware │   ├── apps │   │   ├── Calculator.mpy │   │   ├── cat-fact.mpy │   │   ├── counter.mpy │   │   ├── flip_social │   │   │   ├── __init__.py │   │   │   ├── password.mpy │   │   │   ├── run.mpy │   │   │   ├── settings.mpy │   │   │   └── username.mpy │   │   ├── FlipSocial.mpy │   │   ├── games │   │   │   ├── 2048.mpy │   │   │   ├── Breakout.mpy │   │   │   ├── example.mpy │   │   │   ├── Flappy Bird.mpy │   │   │   ├── flip_world │   │   │   │   ├── assets.mpy │   │   │   │   ├── general.mpy │   │   │   │   ├── __init__.py │   │   │   │   ├── player.mpy │   │   │   │   ├── run.mpy │   │   │   │   └── sprite.mpy │   │   │   ├── FlipWorld.mpy │   │   │   ├── free_roam │   │   │   │   ├── dynamic_map.mpy │   │   │   │   ├── game.mpy │   │   │   │   ├── __init__.py │   │   │   │   ├── maps.mpy │   │   │   │   ├── player.mpy │   │   │   │   └── sprite.mpy │   │   │   ├── Free Roam.mpy │   │   │   ├── game_of_life.mpy │   │   │   ├── Maze Runner.mpy │   │   │   ├── Minesweeper.mpy │   │   │   ├── Pong.mpy │   │   │   ├── Snake.mpy │   │   │   ├── Soduko.mpy │   │   │   ├── Space Invaders.mpy │   │   │   ├── Tetris.mpy │   │   │   └── Tower Defense.mpy │   │   ├── Graph.mpy │   │   ├── hello_color.mpy │   │   ├── keyboard-simple.mpy │   │   ├── loading-simple.mpy │   │   ├── menu-simple.mpy │   │   ├── random-object.mpy │   │   ├── screensavers │   │   │   ├── Bubble Universe.mpy │   │   │   ├── Clock.mpy │   │   │   ├── Cube.mpy │   │   │   ├── DVI Bounce.mpy │   │   │   ├── Fire Effect.mpy │   │   │   ├── Matrix Rain.mpy │   │   │   ├── Patterns.mpy │   │   │   ├── PicoFlower.mpy │   │   │   ├── Plasma Wave.mpy │   │   │   └── Yin-Yang.mpy │   │   ├── Serial Terminal.mpy │   │   ├── storage-simple.mpy │   │   ├── textbox-simple.mpy │   │   ├── Text Editor.mpy │   │   └── Weather.mpy │   └── settings └── README.md </code></pre></div> <p>Since PicoCalc SD v0.6 we used <a href="https://github.com/pelrun/uf2loader.git">uf2loader</a> as main loader.</p> <p>All uf2 files in folder <strong>pico1-apps</strong> will be showed up in menu.</p> <p>Once a uf2 got flashed and ran, next time you can use menu item <strong>[Default App]</strong> to directly run it without flashing it again.</p> <p>Important files:</p> <ul> <li>bootloader_pico.uf2<br> uf2loader main program, should be flashed into pico.</li> <li>BOOT2040.uf2<br> uf2loader Menu UI, it is a very important file, do not delete or edit it unless you know what you are doing.</li> </ul> <h2>PicoCalc_Fuzix_v1.0.uf2</h2> <p><a href="https://github.com/EtchedPixels/FUZIX.git">Fuzix</a> is an open-source, lightweight Unix-like operating system specifically designed for 8-bit and other resource-constrained processors.</p> <p>Patches for PicoCalc are <a href="https://github.com/clockworkpi/PicoCalc/tree/master/Code/FUZIX">here</a><br> UF2 Path: /pico1-apps/PicoCalc_Fuzix_v1.0.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>PicoCalc_NES_v1.0.uf2</h2> <p>A simple NES emulator for PicoCalc, it will scan all nes files in the root of SD card.<br> Given the resource constraints of the Pico, it is recommended to only run NES games that are less than <strong>44KB</strong> in size.</p> <p>UF2 Path: /pico1-apps/PicoCalc_NES_v1.0.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>picolua_daf20a2.uf2</h2> <p><a href="https://github.com/Lana-chan/picocalc_lua">https://github.com/Lana-chan/picocalc_lua</a><br> A Lua interpreter for PicoCalc. It contains a REPL, basic API to draw graphics, read keys and access the SD filesystem.</p> <p>UF2 Path: /pico1-apps/picolua_daf20a2.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>Picoware_v1.6.9.uf2</h2> <p><a href="https://github.com/jblanked/Picoware">https://github.com/jblanked/Picoware</a></p> <p>An Open-source custom firmware for the PicoCalc, Video Game Module, and other Raspberry Pi Pico devices.</p> <p>Here is the version based on MicroPython.</p> <p>UF2 Path: /pico1-apps/Picoware_v1.6.9.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>phyllosoma_kb.uf2</h2> <p><a href="https://github.com/machikania/phyllosoma/releases">MachiKania Phyllosoma</a> is a BASIC compiler for ARMv6-M with excellent performance., especially for Raspberry Pi Pico.</p> <p>UF2 Path: /pico1-apps/phyllosoma_kb.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>PicoCalc_MP3Player_v0.5.uf2</h2> <p><a href="https://github.com/clockworkpi/PicoCalc/tree/master/Code/MP3Player">PicoCalc_MP3Player</a> is a simple MP3 playback program based on the [YAHAL](<a href="https://git.fh-aachen.de/Terstegge/YAHAL" rel="nofollow">https://git.fh-aachen.de/Terstegge/YAHAL</a></p> <p>) framework.</p> <p>UF2 Path: /pico1-apps/PicoCalc_MP3Player_v0.5.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>PicoCalc_uLisp_v1.1.uf2</h2> <p><a href="http://www.ulisp.com/show?56ZO" rel="nofollow">http://www.ulisp.com/show?56ZO</a></p> <p>A self-contained Lisp computer for PicoCalc.<br> UF2 Path: /pico1-apps/PicoCalc_uLisp_v1.1.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <h2>PicoMite_v6.02.01b4_beta.uf2</h2> <p><a href="https://geoffg.net/picomite.html" rel="nofollow">The PicoMite</a> is a complete operating system with a Microsoft BASIC compatible interpreter and extensive hardware support including touch sensitive LCD panels, SD Cards, WiFi/Internet and much more.</p> <p>UF2 Path: /pico1-apps/PicoMite_v6.02.01b4_beta.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> <div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Copyright and Acknowledgments The PicoMite firmware and MMBasic is copyright 2011-2025 by Geoff Graham and Peter Mather 2016-2025. 1-Wire Support is copyright 1999-2006 Dallas Semiconductor Corporation and 2012 Gerard Sexton. FatFs (SD Card) driver is copyright 2014, ChaN. WAV, MP3, and FLAC file support is copyright 2019 David Reid. JPG support is thanks to Rich Geldreich The pico-sdk is copyright 2021 Raspberry Pi (Trading) Ltd. TinyUSB is copyright tinyusb.org LittleFS is copyright Christopher Haster Thomas Williams and Gerry Allardice for MMBasic enhancements The VGA driver code was derived from work by Miroslav Nemecek The CRC calculations are copyright Rob Tillaart The compiled object code (the .uf2 file) for the PicoMite firmware is free software: you can use or redistribute it as you please. The source code is on GitHub ( https://github.com/UKTailwind/PicoMiteAllVersions ) and can be freely used subject to some conditions (see the header in the source files). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."><pre class="notranslate"><code>Copyright and Acknowledgments The PicoMite firmware and MMBasic is copyright 2011-2025 by Geoff Graham and Peter Mather 2016-2025. 1-Wire Support is copyright 1999-2006 Dallas Semiconductor Corporation and 2012 Gerard Sexton. FatFs (SD Card) driver is copyright 2014, ChaN. WAV, MP3, and FLAC file support is copyright 2019 David Reid. JPG support is thanks to Rich Geldreich The pico-sdk is copyright 2021 Raspberry Pi (Trading) Ltd. TinyUSB is copyright tinyusb.org LittleFS is copyright Christopher Haster Thomas Williams and Gerry Allardice for MMBasic enhancements The VGA driver code was derived from work by Miroslav Nemecek The CRC calculations are copyright Rob Tillaart The compiled object code (the .uf2 file) for the PicoMite firmware is free software: you can use or redistribute it as you please. The source code is on GitHub ( https://github.com/UKTailwind/PicoMiteAllVersions ) and can be freely used subject to some conditions (see the header in the source files). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. </code></pre></div> <h2>MicroPython_fa8b24c.uf2</h2> <p><a href="https://github.com/zenodante/PicoCalc-micropython-driver">https://github.com/zenodante/PicoCalc-micropython-driver</a></p> <p><a href="https://micropython.org/" rel="nofollow">MicroPython</a> is a lean and efficient implementation of the Python 3 programming language that includes a small subset of the Python standard library and is optimised to run on microcontrollers and in constrained environments.</p> <p>Here is the MicroPython Drivers compatible with PicoCalc.</p> <p>UF2 Path: /pico1-apps/MicroPython_fa8b24c.uf2 (<a href="https://github.com/clockworkpi/PicoCalc/tree/master/Bin/PicoCalc%20SD/pico1-apps">Download</a>)</p> cuu tag:github.com,2008:Repository/909561369/multi_booter_v0.5 2025-11-08T06:19:52Z Multi bootloader v0.5 <div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="├── firmware │   ├── Lua_180a58e.bin │   ├── MicroPython_fa8b24c.bin │   ├── MP3player_v0.5.bin │   ├── PicoCalc_NES_v1.0.bin │   ├── PicoMite_cbf6d71.bin │   └── uLisp_4.8f.bin └── PicoCalc_Bootloader_v0.5.uf2"><pre class="notranslate"><code>├── firmware │   ├── Lua_180a58e.bin │   ├── MicroPython_fa8b24c.bin │   ├── MP3player_v0.5.bin │   ├── PicoCalc_NES_v1.0.bin │   ├── PicoMite_cbf6d71.bin │   └── uLisp_4.8f.bin └── PicoCalc_Bootloader_v0.5.uf2 </code></pre></div> <h2>Lua_180a58e.bin</h2> <p><a href="https://github.com/benob/picocalc_lua">https://github.com/benob/picocalc_lua</a><br> 180a58e6eff857f2106b8ce3fdfa2c3715b9e58c</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="diff --git a/CMakeLists.txt b/CMakeLists.txt index 87f319a..8914485 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ add_executable(picolua ) pico_enable_stdio_usb(picolua 0) -pico_enable_stdio_uart(picolua 0) +pico_enable_stdio_uart(picolua 1) target_link_libraries(picolua pico_stdlib @@ -39,6 +39,17 @@ target_link_libraries(picolua pico_add_extra_outputs(picolua) +function(enable_sdcard_app target) + #pico_set_linker_script(${target} ${CMAKE_SOURCE_DIR}/memmap_sdcard_app.ld) + if(${PICO_PLATFORM} STREQUAL &quot;rp2040&quot;) + pico_set_linker_script(${CMAKE_PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_default_rp2040.ld) + elseif(${PICO_PLATFORM} MATCHES &quot;rp2350&quot;) + pico_set_linker_script(${CMAKE_PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_default_rp2350.ld) + endif() +endfunction() + +enable_sdcard_app(${CMAKE_PROJECT_NAME}) + add_custom_target(flash COMMAND cp picolua.uf2 /run/media/favre/RP2350/ DEPENDS picolua diff --git a/memmap_default_rp2040.ld b/memmap_default_rp2040.ld new file mode 100644 index 0000000..31efe94 --- /dev/null +++ b/memmap_default_rp2040.ld @@ -0,0 +1,219 @@ +MEMORY +{ + FLASH(rx) : ORIGIN = 0x10000000 + 200k, LENGTH = 2048k - 200k + RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k + SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k + SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k +} + +ENTRY(_entry_point) + +SECTIONS +{ + /* Second stage bootloader is prepended to the image. It must be 256 bytes big + and checksummed. It is usually built by the boot_stage2 target + in the Raspberry Pi Pico SDK + */ + + .flash_begin : { + __flash_binary_start = .; + } &gt; FLASH + + /* The second stage will always enter the image at the start of .text. + The debugger will use the ELF entry point, which is the _entry_point + symbol if present, otherwise defaults to start of .text. + This can be used to transfer control back to the bootrom on debugger + launches only, to perform proper flash setup. + */ + + .text : { + __logical_binary_start = .; + KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.reset)) + /* TODO revisit this now memset/memcpy/float in ROM */ + /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from + * FLASH ... we will include any thing excluded here in .data below by default */ + *(.init) + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) + *(.fini) + /* Pull all c'tors into .text */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + /* Followed by destructors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.eh_frame*) + . = ALIGN(4); + } &gt; FLASH + + .rodata : { + *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) + . = ALIGN(4); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) + . = ALIGN(4); + } &gt; FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } &gt; FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } &gt; FLASH + __exidx_end = .; + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } &gt; FLASH + __binary_info_end = .; + . = ALIGN(4); + + .ram_vector_table (NOLOAD): { + *(.ram_vector_table) + } &gt; RAM + + .data : { + __data_start__ = .; + *(vtable) + + *(.time_critical*) + + /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ + *(.text*) + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + + *(.data*) + + . = ALIGN(4); + *(.after_data.*) + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__mutex_array_start = .); + KEEP(*(SORT(.mutex_array.*))) + KEEP(*(.mutex_array)) + PROVIDE_HIDDEN (__mutex_array_end = .); + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(SORT(.preinit_array.*))) + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + *(SORT(.fini_array.*)) + *(.fini_array) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.jcr) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + } &gt; RAM AT&gt; FLASH + /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */ + __etext = LOADADDR(.data); + + .uninitialized_data (NOLOAD): { + . = ALIGN(4); + *(.uninitialized_data*) + } &gt; RAM + + /* Start and end symbols must be word-aligned */ + .scratch_x : { + __scratch_x_start__ = .; + *(.scratch_x.*) + . = ALIGN(4); + __scratch_x_end__ = .; + } &gt; SCRATCH_X AT &gt; FLASH + __scratch_x_source__ = LOADADDR(.scratch_x); + + .scratch_y : { + __scratch_y_start__ = .; + *(.scratch_y.*) + . = ALIGN(4); + __scratch_y_end__ = .; + } &gt; SCRATCH_Y AT &gt; FLASH + __scratch_y_source__ = LOADADDR(.scratch_y); + + .bss : { + . = ALIGN(4); + __bss_start__ = .; + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } &gt; RAM + + .heap (NOLOAD): + { + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } &gt; RAM + + /* .stack*_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later + * + * stack1 section may be empty/missing if platform_launch_core1 is not used */ + + /* by default we put core 0 stack at the end of scratch Y, so that if core 1 + * stack is not used then all of SCRATCH_X is free. + */ + .stack1_dummy (NOLOAD): + { + *(.stack1*) + } &gt; SCRATCH_X + .stack_dummy (NOLOAD): + { + KEEP(*(.stack*)) + } &gt; SCRATCH_Y + + .flash_end : { + PROVIDE(__flash_binary_end = .); + } &gt; FLASH + + /* stack limit is poorly named, but historically is maximum heap ptr */ + __StackLimit = ORIGIN(RAM) + LENGTH(RAM); + __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); + __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); + __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); + __StackBottom = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit &gt;= __HeapLimit, &quot;region RAM overflowed&quot;) + + ASSERT( __binary_info_header_end - __logical_binary_start &lt;= 256, &quot;Binary info must be in first 256 bytes of the binary&quot;) + /* todo assert on extra code */ +} +"><pre><span class="pl-c1">diff --git a/CMakeLists.txt b/CMakeLists.txt</span> index 87f319a..8914485 100644 <span class="pl-md">--- a/CMakeLists.txt</span> <span class="pl-mi1">+++ b/CMakeLists.txt</span> <span class="pl-mdr">@@ -18,7 +18,7 @@</span> add_executable(picolua ) pico_enable_stdio_usb(picolua 0) <span class="pl-md"><span class="pl-md">-</span>pico_enable_stdio_uart(picolua 0)</span> <span class="pl-mi1"><span class="pl-mi1">+</span>pico_enable_stdio_uart(picolua 1)</span> target_link_libraries(picolua pico_stdlib <span class="pl-mdr">@@ -39,6 +39,17 @@</span> target_link_libraries(picolua pico_add_extra_outputs(picolua) <span class="pl-mi1"><span class="pl-mi1">+</span>function(enable_sdcard_app target)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> #pico_set_linker_script(${target} ${CMAKE_SOURCE_DIR}/memmap_sdcard_app.ld)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> if(${PICO_PLATFORM} STREQUAL "rp2040")</span> <span class="pl-mi1"><span class="pl-mi1">+</span> pico_set_linker_script(${CMAKE_PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_default_rp2040.ld)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> elseif(${PICO_PLATFORM} MATCHES "rp2350")</span> <span class="pl-mi1"><span class="pl-mi1">+</span> pico_set_linker_script(${CMAKE_PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_default_rp2350.ld)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> endif()</span> <span class="pl-mi1"><span class="pl-mi1">+</span>endfunction()</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span>enable_sdcard_app(${CMAKE_PROJECT_NAME})</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> add_custom_target(flash COMMAND cp picolua.uf2 /run/media/favre/RP2350/ DEPENDS picolua <span class="pl-c1">diff --git a/memmap_default_rp2040.ld b/memmap_default_rp2040.ld</span> new file mode 100644 index 0000000..31efe94 <span class="pl-md">--- /dev/null</span> <span class="pl-mi1">+++ b/memmap_default_rp2040.ld</span> <span class="pl-mdr">@@ -0,0 +1,219 @@</span> <span class="pl-mi1"><span class="pl-mi1">+</span>MEMORY</span> <span class="pl-mi1"><span class="pl-mi1">+</span>{</span> <span class="pl-mi1"><span class="pl-mi1">+</span> FLASH(rx) : ORIGIN = 0x10000000 + 200k, LENGTH = 2048k - 200k</span> <span class="pl-mi1"><span class="pl-mi1">+</span> RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k</span> <span class="pl-mi1"><span class="pl-mi1">+</span> SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k</span> <span class="pl-mi1"><span class="pl-mi1">+</span> SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k</span> <span class="pl-mi1"><span class="pl-mi1">+</span>}</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span>ENTRY(_entry_point)</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span>SECTIONS</span> <span class="pl-mi1"><span class="pl-mi1">+</span>{</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* Second stage bootloader is prepended to the image. It must be 256 bytes big</span> <span class="pl-mi1"><span class="pl-mi1">+</span> and checksummed. It is usually built by the boot_stage2 target</span> <span class="pl-mi1"><span class="pl-mi1">+</span> in the Raspberry Pi Pico SDK</span> <span class="pl-mi1"><span class="pl-mi1">+</span> */</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .flash_begin : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __flash_binary_start = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* The second stage will always enter the image at the start of .text.</span> <span class="pl-mi1"><span class="pl-mi1">+</span> The debugger will use the ELF entry point, which is the _entry_point</span> <span class="pl-mi1"><span class="pl-mi1">+</span> symbol if present, otherwise defaults to start of .text.</span> <span class="pl-mi1"><span class="pl-mi1">+</span> This can be used to transfer control back to the bootrom on debugger</span> <span class="pl-mi1"><span class="pl-mi1">+</span> launches only, to perform proper flash setup.</span> <span class="pl-mi1"><span class="pl-mi1">+</span> */</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .text : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __logical_binary_start = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP (*(.vectors))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP (*(.binary_info_header))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __binary_info_header_end = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP (*(.reset))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* TODO revisit this now memset/memcpy/float in ROM */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from</span> <span class="pl-mi1"><span class="pl-mi1">+</span> * FLASH ... we will include any thing excluded here in .data below by default */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.init)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.fini)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* Pull all c'tors into .text */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *crtbegin.o(.ctors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *crtbegin?.o(.ctors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(SORT(.ctors.*))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.ctors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* Followed by destructors */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *crtbegin.o(.dtors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *crtbegin?.o(.dtors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(SORT(.dtors.*))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.dtors)</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.eh_frame*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .rodata : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .ARM.extab :</span> <span class="pl-mi1"><span class="pl-mi1">+</span> {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.ARM.extab* .gnu.linkonce.armextab.*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> __exidx_start = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> .ARM.exidx :</span> <span class="pl-mi1"><span class="pl-mi1">+</span> {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.ARM.exidx* .gnu.linkonce.armexidx.*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __exidx_end = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* Machine inspectable binary information */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __binary_info_start = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> .binary_info :</span> <span class="pl-mi1"><span class="pl-mi1">+</span> {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(.binary_info.keep.*))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.binary_info.*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __binary_info_end = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .ram_vector_table (NOLOAD): {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.ram_vector_table)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; RAM</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .data : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __data_start__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(vtable)</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.time_critical*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.text*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.rodata*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.data*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.after_data.*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* preinit data */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__mutex_array_start = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(SORT(.mutex_array.*)))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(.mutex_array))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__mutex_array_end = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* preinit data */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__preinit_array_start = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(SORT(.preinit_array.*)))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(.preinit_array))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__preinit_array_end = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* init data */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__init_array_start = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(SORT(.init_array.*)))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(.init_array))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__init_array_end = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* finit data */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__fini_array_start = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(SORT(.fini_array.*))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.fini_array)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE_HIDDEN (__fini_array_end = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.jcr)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* All data end */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __data_end__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; RAM AT&gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __etext = LOADADDR(.data);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .uninitialized_data (NOLOAD): {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.uninitialized_data*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; RAM</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* Start and end symbols must be word-aligned */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> .scratch_x : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __scratch_x_start__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.scratch_x.*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __scratch_x_end__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; SCRATCH_X AT &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __scratch_x_source__ = LOADADDR(.scratch_x);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .scratch_y : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __scratch_y_start__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.scratch_y.*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __scratch_y_end__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; SCRATCH_Y AT &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __scratch_y_source__ = LOADADDR(.scratch_y);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .bss : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __bss_start__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(COMMON)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> . = ALIGN(4);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __bss_end__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; RAM</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .heap (NOLOAD):</span> <span class="pl-mi1"><span class="pl-mi1">+</span> {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __end__ = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> end = __end__;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(.heap*))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __HeapLimit = .;</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; RAM</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* .stack*_dummy section doesn't contains any symbols. It is only</span> <span class="pl-mi1"><span class="pl-mi1">+</span> * used for linker to calculate size of stack sections, and assign</span> <span class="pl-mi1"><span class="pl-mi1">+</span> * values to stack symbols later</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *</span> <span class="pl-mi1"><span class="pl-mi1">+</span> * stack1 section may be empty/missing if platform_launch_core1 is not used */</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* by default we put core 0 stack at the end of scratch Y, so that if core 1</span> <span class="pl-mi1"><span class="pl-mi1">+</span> * stack is not used then all of SCRATCH_X is free.</span> <span class="pl-mi1"><span class="pl-mi1">+</span> */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> .stack1_dummy (NOLOAD):</span> <span class="pl-mi1"><span class="pl-mi1">+</span> {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> *(.stack1*)</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; SCRATCH_X</span> <span class="pl-mi1"><span class="pl-mi1">+</span> .stack_dummy (NOLOAD):</span> <span class="pl-mi1"><span class="pl-mi1">+</span> {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> KEEP(*(.stack*))</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; SCRATCH_Y</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> .flash_end : {</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE(__flash_binary_end = .);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> } &gt; FLASH</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* stack limit is poorly named, but historically is maximum heap ptr */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __StackLimit = ORIGIN(RAM) + LENGTH(RAM);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> __StackBottom = __StackTop - SIZEOF(.stack_dummy);</span> <span class="pl-mi1"><span class="pl-mi1">+</span> PROVIDE(__stack = __StackTop);</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* Check if data + heap + stack exceeds RAM limit */</span> <span class="pl-mi1"><span class="pl-mi1">+</span> ASSERT(__StackLimit &gt;= __HeapLimit, "region RAM overflowed")</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span> <span class="pl-mi1"><span class="pl-mi1">+</span> ASSERT( __binary_info_header_end - __logical_binary_start &lt;= 256, "Binary info must be in first 256 bytes of the binary")</span> <span class="pl-mi1"><span class="pl-mi1">+</span> /* todo assert on extra code */</span> <span class="pl-mi1"><span class="pl-mi1">+</span>}</span> <span class="pl-mi1"><span class="pl-mi1">+</span></span></pre></div> <h2>MicroPython_fa8b24c.bin</h2> <p><a href="https://github.com/zenodante/PicoCalc-micropython-driver.git">https://github.com/zenodante/PicoCalc-micropython-driver.git</a><br> commit fa8b24c3d7b4b1b6d621b46ceced787dce69f4c1</p> <p>in micropython/micropython/ports/rp2</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="diff --git a/ports/rp2/memmap_mp_rp2040.ld b/ports/rp2/memmap_mp_rp2040.ld index 5c8d9f471..c9a33230f 100644 --- a/ports/rp2/memmap_mp_rp2040.ld +++ b/ports/rp2/memmap_mp_rp2040.ld @@ -23,7 +23,7 @@ MEMORY { - FLASH(rx) : ORIGIN = 0x10000000, LENGTH = __micropy_flash_size__ + FLASH(rx) : ORIGIN = 0x10000000 + 200k, LENGTH = __micropy_flash_size__ - 200k RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k @@ -42,14 +42,6 @@ SECTIONS __flash_binary_start = .; } &gt; FLASH - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } &gt; FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - &quot;ERROR: Pico second stage bootloader must be 256 bytes in size&quot;) /* The second stage will always enter the image at the start of .text. The debugger will use the ELF entry point, which is the _entry_point "><pre><span class="pl-c1">diff --git a/ports/rp2/memmap_mp_rp2040.ld b/ports/rp2/memmap_mp_rp2040.ld</span> index 5c8d9f471..c9a33230f 100644 <span class="pl-md">--- a/ports/rp2/memmap_mp_rp2040.ld</span> <span class="pl-mi1">+++ b/ports/rp2/memmap_mp_rp2040.ld</span> <span class="pl-mdr">@@ -23,7 +23,7 @@</span> MEMORY { <span class="pl-md"><span class="pl-md">-</span> FLASH(rx) : ORIGIN = 0x10000000, LENGTH = __micropy_flash_size__</span> <span class="pl-mi1"><span class="pl-mi1">+</span> FLASH(rx) : ORIGIN = 0x10000000 + 200k, LENGTH = __micropy_flash_size__ - 200k</span> RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k <span class="pl-mdr">@@ -42,14 +42,6 @@</span> SECTIONS __flash_binary_start = .; } &gt; FLASH <span class="pl-md"><span class="pl-md">-</span> .boot2 : {</span> <span class="pl-md"><span class="pl-md">-</span> __boot2_start__ = .;</span> <span class="pl-md"><span class="pl-md">-</span> KEEP (*(.boot2))</span> <span class="pl-md"><span class="pl-md">-</span> __boot2_end__ = .;</span> <span class="pl-md"><span class="pl-md">-</span> } &gt; FLASH</span> <span class="pl-md"><span class="pl-md">-</span></span> <span class="pl-md"><span class="pl-md">-</span> ASSERT(__boot2_end__ - __boot2_start__ == 256,</span> <span class="pl-md"><span class="pl-md">-</span> "ERROR: Pico second stage bootloader must be 256 bytes in size")</span> /* The second stage will always enter the image at the start of .text. The debugger will use the ELF entry point, which is the _entry_point </pre></div> <h2>MP3player_v0.5.bin</h2> <p>apply the <a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player/320dcf025478994c10930c5d6ffccd511d456b0a.patch">https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player/320dcf025478994c10930c5d6ffccd511d456b0a.patch</a><br> based on current code in</p> <p><a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player">https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player</a></p> <p>in YAHAL_DIR<br> replace ${YAHAL_DIR}/cmake/boards/rpi-pico.ld with <a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/rpi-pico.ld">https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/rpi-pico.ld</a></p> <h2>PicoCalc_NES_v1.0.bin</h2> <p><a href="https://github.com/cuu/shapones/tree/for_multi_boot">https://github.com/cuu/shapones/tree/for_multi_boot</a></p> <h2>PicoMite_cbf6d71.bin</h2> <p><a href="https://github.com/cuu/PicoMiteAllVersions/tree/multi_boot">https://github.com/cuu/PicoMiteAllVersions/tree/multi_boot</a><br> cbf6d71d199eccbd0663ef680da07523a0612a57</p> <h2>uLisp_4.8f.bin</h2> <p>replace ~/.arduino15/packages/rp2040/hardware/rp2040/4.4.1/lib/rp2040/memmap_default.ld<br> with <a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/memmap_default.ld.mp.rp2040">https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/memmap_default.ld.mp.rp2040</a><br> The version of arduino-pico may be different, just need to find the corresponding memmap_default.ld ,replace it and re-compile ulisp</p> cuu tag:github.com,2008:Repository/909561369/multi_booter_v0.4 2025-05-31T12:48:54Z Multi bootloader v0.4 <div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="├── firmware │   ├── lua_180a58e.bin │   ├── micropython_1aa4069.bin │   ├── mp3-player_v0.5.bin │   ├── picocalc_nes_v1.0.bin │   ├── PicoMite_abe6566.bin │   └── ulisp_4.7d.bin └── PicoCalc_Bootloader_v0.4.uf2"><pre class="notranslate"><code>├── firmware │   ├── lua_180a58e.bin │   ├── micropython_1aa4069.bin │   ├── mp3-player_v0.5.bin │   ├── picocalc_nes_v1.0.bin │   ├── PicoMite_abe6566.bin │   └── ulisp_4.7d.bin └── PicoCalc_Bootloader_v0.4.uf2 </code></pre></div> cuu tag:github.com,2008:Repository/909561369/multi_booter_v0.3 2025-05-26T07:05:31Z pico multi booter v0.3 <p>In this release , flash offset changed from 940k to 152k</p> <p>re-complied all *mp.bin files</p> <p>add Default app and Last app</p> <p>In first boot up ,Default app is PicoMite , if no sd card or no firmware bin files, user can still launch PicoMite as Default app</p> <p>If other bin has ran , user can launch it as the last ran app from menu [Last app] to avoid repeated flash read and write.</p> <p>put all bin files into <strong>firmware</strong> folder on SD Card</p> <h1>changelog:</h1> <h2>PicoMite_mp.bin</h2> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="diff --git a/CMakeLists.txt b/CMakeLists.txt index d063c10..3deadc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,14 +7,14 @@ set(PICOCALC true) # PicoMite will need to be shifted by this amount, and all references to # positions in flash updated to accomodate. THIS OPTION IS NOT READY YET. # details: https://github.com/adwuard/Picocalc_SD_Boot -set(SDBOOT true) +#set(SDBOOT true) # Compile for PICO 1 Board -set(COMPILE PICO) +#set(COMPILE PICO) # Compile for PICO 2 Board #set(COMPILE PICORP2350) -#set(COMPILE WEBRP2350) +set(COMPILE WEBRP2350) if (COMPILE STREQUAL &quot;HDMI&quot; OR COMPILE STREQUAL &quot;WEBRP2350&quot; OR COMPILE STREQUAL &quot;HDMIUSB&quot; OR COMPILE STREQUAL &quot;VGARP2350&quot; OR COMPILE STREQUAL &quot;VGAUSBRP2350&quot; OR COMPILE STREQUAL &quot;PICORP2350&quot; OR COMPILE STREQUAL &quot;PICOUSBRP2350&quot; ) set(PICO_PLATFORM rp2350) diff --git a/configuration.h b/configuration.h index 08b7dac..5b4e809 100644 --- a/configuration.h +++ b/configuration.h @@ -162,7 +162,7 @@ extern &quot;C&quot; { #ifdef rp2350 #define HEAP_MEMORY_SIZE (288*1024) #define MAXVARS 768 // 8 + MAXVARLEN + MAXDIM * 4 (ie, 64 bytes) - these do not incl array members - #define FLASH_TARGET_OFFSET (920 * 1024) + #define FLASH_TARGET_OFFSET (832 * 1024) #define MAX_CPU (rp2350a ? 396000 : 378000) #define MAXSUBFUN 512 // each entry takes up 4 bytes #ifdef USBKEYBOARD @@ -175,7 +175,7 @@ extern &quot;C&quot; { #else #define HEAP_MEMORY_SIZE (128*1024) #define MAXVARS 512 // 8 + MAXVARLEN + MAXDIM * 2 (ie, 56 bytes) - these do not incl array members - #define FLASH_TARGET_OFFSET (920 * 1024) + #define FLASH_TARGET_OFFSET (832 * 1024) #define MAX_CPU 420000 #define MAXSUBFUN 256 // each entry takes up 4 bytes #ifdef USBKEYBOARD diff --git a/memmap_default_rp2040.ld b/memmap_default_rp2040.ld index 3c5ab0c..a0e1357 100644 --- a/memmap_default_rp2040.ld +++ b/memmap_default_rp2040.ld @@ -1,6 +1,6 @@ MEMORY { - FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k + FLASH(rx) : ORIGIN = 0x10000000 + 256k, LENGTH = 2048k - 256k RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k"><pre><span class="pl-c1">diff --git a/CMakeLists.txt b/CMakeLists.txt</span> index d063c10..3deadc0 100644 <span class="pl-md">--- a/CMakeLists.txt</span> <span class="pl-mi1">+++ b/CMakeLists.txt</span> <span class="pl-mdr">@@ -7,14 +7,14 @@</span> set(PICOCALC true) # PicoMite will need to be shifted by this amount, and all references to # positions in flash updated to accomodate. THIS OPTION IS NOT READY YET. # details: https://github.com/adwuard/Picocalc_SD_Boot <span class="pl-md"><span class="pl-md">-</span>set(SDBOOT true)</span> <span class="pl-mi1"><span class="pl-mi1">+</span>#set(SDBOOT true)</span> # Compile for PICO 1 Board <span class="pl-md"><span class="pl-md">-</span>set(COMPILE PICO)</span> <span class="pl-mi1"><span class="pl-mi1">+</span>#set(COMPILE PICO)</span> # Compile for PICO 2 Board #set(COMPILE PICORP2350) <span class="pl-md"><span class="pl-md">-</span>#set(COMPILE WEBRP2350)</span> <span class="pl-mi1"><span class="pl-mi1">+</span>set(COMPILE WEBRP2350)</span> if (COMPILE STREQUAL "HDMI" OR COMPILE STREQUAL "WEBRP2350" OR COMPILE STREQUAL "HDMIUSB" OR COMPILE STREQUAL "VGARP2350" OR COMPILE STREQUAL "VGAUSBRP2350" OR COMPILE STREQUAL "PICORP2350" OR COMPILE STREQUAL "PICOUSBRP2350" ) set(PICO_PLATFORM rp2350) <span class="pl-c1">diff --git a/configuration.h b/configuration.h</span> index 08b7dac..5b4e809 100644 <span class="pl-md">--- a/configuration.h</span> <span class="pl-mi1">+++ b/configuration.h</span> <span class="pl-mdr">@@ -162,7 +162,7 @@</span> extern "C" { #ifdef rp2350 #define HEAP_MEMORY_SIZE (288*1024) #define MAXVARS 768 // 8 + MAXVARLEN + MAXDIM * 4 (ie, 64 bytes) - these do not incl array members <span class="pl-md"><span class="pl-md">-</span> #define FLASH_TARGET_OFFSET (920 * 1024) </span> <span class="pl-mi1"><span class="pl-mi1">+</span> #define FLASH_TARGET_OFFSET (832 * 1024) </span> #define MAX_CPU (rp2350a ? 396000 : 378000) #define MAXSUBFUN 512 // each entry takes up 4 bytes #ifdef USBKEYBOARD <span class="pl-mdr">@@ -175,7 +175,7 @@</span> extern "C" { #else #define HEAP_MEMORY_SIZE (128*1024) #define MAXVARS 512 // 8 + MAXVARLEN + MAXDIM * 2 (ie, 56 bytes) - these do not incl array members <span class="pl-md"><span class="pl-md">-</span> #define FLASH_TARGET_OFFSET (920 * 1024) </span> <span class="pl-mi1"><span class="pl-mi1">+</span> #define FLASH_TARGET_OFFSET (832 * 1024) </span> #define MAX_CPU 420000 #define MAXSUBFUN 256 // each entry takes up 4 bytes #ifdef USBKEYBOARD <span class="pl-c1">diff --git a/memmap_default_rp2040.ld b/memmap_default_rp2040.ld</span> index 3c5ab0c..a0e1357 100644 <span class="pl-md">--- a/memmap_default_rp2040.ld</span> <span class="pl-mi1">+++ b/memmap_default_rp2040.ld</span> <span class="pl-mdr">@@ -1,6 +1,6 @@</span> MEMORY { <span class="pl-md"><span class="pl-md">-</span> FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k</span> <span class="pl-mi1"><span class="pl-mi1">+</span> FLASH(rx) : ORIGIN = 0x10000000 + 256k, LENGTH = 2048k - 256k</span> RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k</pre></div> <h2>mp3-player_mp.bin</h2> <p>apply the <a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player/320dcf025478994c10930c5d6ffccd511d456b0a.patch">https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player/320dcf025478994c10930c5d6ffccd511d456b0a.patch</a><br> based on current code</p> <p>in YAHAL_DIR<br> replace ${YAHAL_DIR}/cmake/boards/rpi-pico.ld with <a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/rpi-pico.ld">https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/rpi-pico.ld</a></p> <h2>micropython_mp.bin</h2> <p>in <code>micropython/micropython/ports/rp2</code></p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="diff --git a/ports/rp2/memmap_mp_rp2040.ld b/ports/rp2/memmap_mp_rp2040.ld index a5799cd88..29ca60f69 100644 --- a/ports/rp2/memmap_mp_rp2040.ld +++ b/ports/rp2/memmap_mp_rp2040.ld @@ -23,7 +23,7 @@ MEMORY { - FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k + FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k @@ -42,15 +42,6 @@ SECTIONS __flash_binary_start = .; } &gt; FLASH - .boot2 : { - __boot2_start__ = .; - KEEP (*(.boot2)) - __boot2_end__ = .; - } &gt; FLASH - - ASSERT(__boot2_end__ - __boot2_start__ == 256, - &quot;ERROR: Pico second stage bootloader must be 256 bytes in size&quot;) - /* The second stage will always enter the image at the start of .text. The debugger will use the ELF entry point, which is the _entry_point symbol if present, otherwise defaults to start of .text."><pre><span class="pl-c1">diff --git a/ports/rp2/memmap_mp_rp2040.ld b/ports/rp2/memmap_mp_rp2040.ld</span> index a5799cd88..29ca60f69 100644 <span class="pl-md">--- a/ports/rp2/memmap_mp_rp2040.ld</span> <span class="pl-mi1">+++ b/ports/rp2/memmap_mp_rp2040.ld</span> <span class="pl-mdr">@@ -23,7 +23,7 @@</span> MEMORY { <span class="pl-md"><span class="pl-md">-</span> FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k</span> <span class="pl-mi1"><span class="pl-mi1">+</span> FLASH(rx) : ORIGIN = 0x10000000 + 152k, LENGTH = 2048k - 152k</span> RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k <span class="pl-mdr">@@ -42,15 +42,6 @@</span> SECTIONS __flash_binary_start = .; } &gt; FLASH <span class="pl-md"><span class="pl-md">-</span> .boot2 : {</span> <span class="pl-md"><span class="pl-md">-</span> __boot2_start__ = .;</span> <span class="pl-md"><span class="pl-md">-</span> KEEP (*(.boot2))</span> <span class="pl-md"><span class="pl-md">-</span> __boot2_end__ = .;</span> <span class="pl-md"><span class="pl-md">-</span> } &gt; FLASH</span> <span class="pl-md"><span class="pl-md">-</span></span> <span class="pl-md"><span class="pl-md">-</span> ASSERT(__boot2_end__ - __boot2_start__ == 256,</span> <span class="pl-md"><span class="pl-md">-</span> "ERROR: Pico second stage bootloader must be 256 bytes in size")</span> <span class="pl-md"><span class="pl-md">-</span></span> /* The second stage will always enter the image at the start of .text. The debugger will use the ELF entry point, which is the _entry_point symbol if present, otherwise defaults to start of .text.</pre></div> <h2>ulisp-picocalc.mp.bin</h2> <p>replace <code>~/.arduino15/packages/rp2040/hardware/rp2040/4.4.1/lib/rp2040/memmap_default.ld</code><br> with <a href="https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/memmap_default.ld.mp.rp2040">https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/memmap_default.ld.mp.rp2040</a><br> The version of arduino-pico may be different, just need to find the corresponding memmap_default.ld ,replace it and re-compile ulisp</p> <h2>mp3-player_mp.bin</h2> <p>Just clone <a href="https://github.com/cuu/shapones/tree/for_multi_boot">https://github.com/cuu/shapones/tree/for_multi_boot</a>, all patched</p> cuu tag:github.com,2008:Repository/909561369/pico_multi_booter_v0.2 2025-05-23T07:28:00Z pico multi booter <p>Add more bin files for multi booter</p> <p>Flash combined.uf2 into PicoCalc</p> <p>Put these bin files into sd/ folder on SD card</p> cuu tag:github.com,2008:Repository/909561369/pico_multi_booter_v0.1 2025-05-19T09:56:47Z pico multi booter <p>Here is a bootloader for PicoCalc combined slightly modified <a href="https://github.com/madcock/PicoMiteAllVersions">PicoMite</a> and <a href="https://github.com/adwuard/Picocalc_SD_Boot">SD boot</a></p> <ul> <li>Pico1</li> <li>No sdcard inserted ,PicoMite will show up.</li> <li>Sdcard inserted, SD boot menu will show up, load third pico app bin to run at FLASH TARGET OFFSET 2048k-940k</li> </ul> cuu