Releases: clockworkpi/PicoCalc
Multi bootloader v0.5
├── firmware
│ ├── Lua_180a58e.bin
│ ├── MicroPython_1aa4069.bin
│ ├── MP3player_v0.5.bin
│ ├── PicoCalc_NES_v1.0.bin
│ ├── PicoMite_cbf6d71.bin
│ └── uLisp_4.7d.bin
└── PicoCalc_Bootloader_v0.5.uf2
Lua_180a58e.bin
https://github.com/benob/picocalc_lua
180a58e6eff857f2106b8ce3fdfa2c3715b9e58c
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 "rp2040")
+ pico_set_linker_script(${CMAKE_PROJECT_NAME} ${CMAKE_SOURCE_DIR}/memmap_default_rp2040.ld)
+ elseif(${PICO_PLATFORM} MATCHES "rp2350")
+ 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 = .;
+ } > 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);
+ } > 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);
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ /* Machine inspectable binary information */
+ . = ALIGN(4);
+ __binary_info_start = .;
+ .binary_info :
+ {
+ KEEP(*(.binary_info.keep.*))
+ *(.binary_info.*)
+ } > FLASH
+ __binary_info_end = .;
+ . = ALIGN(4);
+
+ .ram_vector_table (NOLOAD): {
+ *(.ram_vector_table)
+ } > 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__ = .;
+ } > RAM AT> FLASH
+ /* __etext is (for backwards compatibility) the name of the .data init source pointer (...) */
+ __etext = LOADADDR(.data);
+
+ .uninitialized_data (NOLOAD): {
+ . = ALIGN(4);
+ *(.uninitialized_data*)
+ } > RAM
+
+ /* Start and end symbols must be word-aligned */
+ .scratch_x : {
+ __scratch_x_start__ = .;
+ *(.scratch_x.*)
+ . = ALIGN(4);
+ __scratch_x_end__ = .;
+ } > SCRATCH_X AT > FLASH
+ __scratch_x_source__ = LOADADDR(.scratch_x);
+
+ .scratch_y : {
+ __scratch_y_start__ = .;
+ *(.scratch_y.*)
+ . = ALIGN(4);
+ __scratch_y_end__ = .;
+ } > SCRATCH_Y AT > FLASH
+ __scratch_y_source__ = LOADADDR(.scratch_y);
+
+ .bss : {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+
+ .heap (NOLOAD):
+ {
+ __end__ = .;
+ end = __end__;
+ KEEP(*(.heap*))
+ __HeapLimit = .;
+ } > 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*)
+ } > SCRATCH_X
+ .stack_dummy (NOLOAD):
+ {
+ KEEP(*(.stack*))
+ } > SCRATCH_Y
+
+ .flash_end : {
+ PROVIDE(__flash_binary_end = .);
+ } > 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 >= __HeapLimit, "region RAM overflowed")
+
+ ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
+ /* todo assert on extra code */
+}
+
MicroPython_1aa4069.bin
https://github.com/zenodante/PicoCalc-micropython-driver.git
commit 1aa4069d6d01a130437c7e526c3dfe9a90d8e503 (HEAD, tag: 20250426)
in micropython/micropython/ports/rp2
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 = .;
} > FLASH
- .boot2 : {
- __boot2_start__ = .;
- KEEP (*(.boot2))
- __boot2_end__ = .;
- } > FLASH
-
- ASSERT(__boot2_end__ - __boot2_start__ == 256,
- "ERROR: Pico second stage bootloader must be 256 bytes in size")
/* 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
MP3player_v0.5.bin
apply the https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player/320dcf025478994c10930c5d6ffccd511d456b0a.patch
based on current code in
https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player
in YAHAL_DIR
replace ${YAHAL_DIR}/cmake/boards/rpi-pico.ld with https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/rpi-pico.ld
PicoCalc_NES_v1.0.bin
https://github.com/cuu/shapones/tree/for_multi_boot
PicoMite_c...
Multi bootloader v0.4
├── 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
pico multi booter v0.3
In this release , flash offset changed from 940k to 152k
re-complied all *mp.bin files
add Default app and Last app
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
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.
put all bin files into firmware folder on SD Card
changelog:
PicoMite_mp.bin
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 "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)
diff --git a/configuration.h b/configuration.h
index 08b7dac..5b4e809 100644
--- a/configuration.h
+++ b/configuration.h
@@ -162,7 +162,7 @@ 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
- #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 "C" {
#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
mp3-player_mp.bin
apply the https://github.com/clockworkpi/PicoCalc/blob/master/Code/MP3Player/320dcf025478994c10930c5d6ffccd511d456b0a.patch
based on current code
in YAHAL_DIR
replace ${YAHAL_DIR}/cmake/boards/rpi-pico.ld with https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/rpi-pico.ld
micropython_mp.bin
in micropython/micropython/ports/rp2
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 = .;
} > FLASH
- .boot2 : {
- __boot2_start__ = .;
- KEEP (*(.boot2))
- __boot2_end__ = .;
- } > FLASH
-
- ASSERT(__boot2_end__ - __boot2_start__ == 256,
- "ERROR: Pico second stage bootloader must be 256 bytes in size")
-
/* 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.
ulisp-picocalc.mp.bin
replace ~/.arduino15/packages/rp2040/hardware/rp2040/4.4.1/lib/rp2040/memmap_default.ld
with https://github.com/clockworkpi/PicoCalc/blob/master/Code/pico_multi_booter/linker_scripts/memmap_default.ld.mp.rp2040
The version of arduino-pico may be different, just need to find the corresponding memmap_default.ld ,replace it and re-compile ulisp
mp3-player_mp.bin
Just clone https://github.com/cuu/shapones/tree/for_multi_boot, all patched
pico multi booter
Add more bin files for multi booter
Flash combined.uf2 into PicoCalc
Put these bin files into sd/ folder on SD card