Skip to content

Releases: clockworkpi/PicoCalc

Multi bootloader v0.5

03 Jun 15:34
@cuu cuu
Compare
Choose a tag to compare
Multi bootloader v0.5 Pre-release
Pre-release
├── 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...

Read more

Multi bootloader v0.4

31 May 12:48
@cuu cuu
Compare
Choose a tag to compare
Multi bootloader v0.4 Pre-release
Pre-release
├── 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

26 May 07:03
@cuu cuu
Compare
Choose a tag to compare
Pre-release

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

23 May 07:09
@cuu cuu
Compare
Choose a tag to compare
pico multi booter Pre-release
Pre-release

Add more bin files for multi booter

Flash combined.uf2 into PicoCalc

Put these bin files into sd/ folder on SD card

pico multi booter

19 May 09:56
@cuu cuu
Compare
Choose a tag to compare
pico multi booter Pre-release
Pre-release

Here is a bootloader for PicoCalc combined slightly modified PicoMite and SD boot

  • Pico1
  • No sdcard inserted ,PicoMite will show up.
  • Sdcard inserted, SD boot menu will show up, load third pico app bin to run at FLASH TARGET OFFSET 2048k-940k