Procházet zdrojové kódy

Merge pull request #395 from ZuluSCSI/feature/free-some-sram

Free some SRAM by putting some code in flash
Alex Perez před 1 rokem
rodič
revize
5c67e58c2d

+ 4 - 102
lib/ZuluSCSI_platform_RP2040/ZuluSCSI_platform.cpp

@@ -764,107 +764,7 @@ uint8_t platform_get_buttons()
     return buttons_debounced;
 }
 
-/*****************************************/
-/* Flash reprogramming from bootloader   */
-/*****************************************/
-
-#ifdef PLATFORM_BOOTLOADER_SIZE
-
-extern uint32_t __real_vectors_start;
-extern uint32_t __StackTop;
-static volatile void *g_bootloader_exit_req;
-
-__attribute__((section(".time_critical.platform_rewrite_flash_page")))
-bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_PAGE_SIZE])
-{
-    if (offset == PLATFORM_BOOTLOADER_SIZE)
-    {
-        if (buffer[3] != 0x20 || buffer[7] != 0x10)
-        {
-            logmsg("Invalid firmware file, starts with: ", bytearray(buffer, 16));
-            return false;
-        }
-    }
-
-
-#ifdef __MBED__
-    if (NVIC_GetEnableIRQ(USBCTRL_IRQn))
-    {
-        logmsg("Disabling USB during firmware flashing");
-        NVIC_DisableIRQ(USBCTRL_IRQn);
-        usb_hw->main_ctrl = 0;
-    }
-#endif // __MBED__
-
-    dbgmsg("Writing flash at offset ", offset, " data ", bytearray(buffer, 4));
-    assert(offset % PLATFORM_FLASH_PAGE_SIZE == 0);
-    assert(offset >= PLATFORM_BOOTLOADER_SIZE);
-
-    // Avoid any mbed timer interrupts triggering during the flashing.
-    __disable_irq();
-
-    // For some reason any code executed after flashing crashes
-    // unless we disable the XIP cache.
-    // Not sure why this happens, as flash_range_program() is flushing
-    // the cache correctly.
-    // The cache is now enabled from bootloader start until it starts
-    // flashing, and again after reset to main firmware.
-    xip_ctrl_hw->ctrl = 0;
-
-    flash_range_erase(offset, PLATFORM_FLASH_PAGE_SIZE);
-    flash_range_program(offset, buffer, PLATFORM_FLASH_PAGE_SIZE);
 
-    uint32_t *buf32 = (uint32_t*)buffer;
-    uint32_t num_words = PLATFORM_FLASH_PAGE_SIZE / 4;
-    for (int i = 0; i < num_words; i++)
-    {
-        uint32_t expected = buf32[i];
-        uint32_t actual = *(volatile uint32_t*)(XIP_NOCACHE_BASE + offset + i * 4);
-
-        if (actual != expected)
-        {
-            logmsg("Flash verify failed at offset ", offset + i * 4, " got ", actual, " expected ", expected);
-            __enable_irq();
-            return false;
-        }
-    }
-
-    __enable_irq();
-
-    return true;
-}
-
-void platform_boot_to_main_firmware()
-{
-    // To ensure that the system state is reset properly, we perform
-    // a SYSRESETREQ and jump straight from the reset vector to main application.
-    g_bootloader_exit_req = &g_bootloader_exit_req;
-    SCB->AIRCR = 0x05FA0004;
-    while(1);
-}
-
-void btldr_reset_handler()
-{
-    uint32_t* application_base = &__real_vectors_start;
-    if (g_bootloader_exit_req == &g_bootloader_exit_req)
-    {
-        // Boot to main application
-        application_base = (uint32_t*)(XIP_BASE + PLATFORM_BOOTLOADER_SIZE);
-    }
-
-    SCB->VTOR = (uint32_t)application_base;
-    __asm__(
-        "msr msp, %0\n\t"
-        "bx %1" : : "r" (application_base[0]),
-                    "r" (application_base[1]) : "memory");
-}
-
-// Replace the reset handler when building the bootloader
-// The rp2040_btldr.ld places real vector table at an offset.
-__attribute__((section(".btldr_vectors")))
-const void * btldr_vectors[2] = {&__StackTop, (void*)&btldr_reset_handler};
-
-#endif // PLATFORM_BOOTLOADER_SIZE
 
 /************************************/
 /* ROM drive in extra flash space   */
@@ -872,8 +772,10 @@ const void * btldr_vectors[2] = {&__StackTop, (void*)&btldr_reset_handler};
 
 #ifdef PLATFORM_HAS_ROM_DRIVE
 
-// Reserve up to 352 kB for firmware.
-#define ROMDRIVE_OFFSET (352 * 1024)
+# ifndef ROMDRIVE_OFFSET
+    // Reserve up to 352 kB for firmware by default.
+    #define ROMDRIVE_OFFSET (352 * 1024)
+# endif
 
 uint32_t platform_get_romdrive_maxsize()
 {

+ 41 - 0
lib/ZuluSCSI_platform_RP2040/process-linker-script.py

@@ -0,0 +1,41 @@
+# ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+#
+# ZuluSCSI™ file is licensed under the GPL version 3 or any later version. 
+#
+# https://www.gnu.org/licenses/gpl-3.0.html
+# ----
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version. 
+#
+# 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.  See the
+# GNU General Public License for more details. 
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+from string import Template 
+Import ("env")
+
+template_file = 'lib/ZuluSCSI_platform_RP2040/rp2040-template.ld'
+linker_file = env.subst('$BUILD_DIR') + '/rp2040.ld'
+
+def process_template(source, target, env):
+    values = {
+        'program_size': env.GetProjectOption('program_flash_allocation'),
+        'project_name': env.subst('$PIOENV')
+        }
+    with open(template_file, 'r') as t:
+        src = Template(t.read())
+        result = src.substitute(values)
+
+    with open(linker_file, 'w') as linker_script:
+        linker_script.write(result)
+
+env.AddPreAction("${BUILD_DIR}/${PROGNAME}.elf",
+        env.VerboseAction(process_template, 
+        'Generating linker script: "' + linker_file + '" from : "' + template_file + '"'
+        )
+)

+ 142 - 0
lib/ZuluSCSI_platform_RP2040/program_flash.cpp

@@ -0,0 +1,142 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2022 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * 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.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+
+/**
+ * This has been removed from ZuluSCSI_platform.cpp so this code can be
+ * placed in SRAM while ZuluSCSI_platform.cpp.o can be placed in flash
+*/
+
+#include "ZuluSCSI_platform.h"
+#include "ZuluSCSI_log.h"
+#include <hardware/flash.h>
+#include <hardware/structs/xip_ctrl.h>
+#include <hardware/structs/usb.h>
+#ifndef __MBED__
+#ifndef PIO_FRAMEWORK_ARDUINO_NO_USB
+# include <SerialUSB.h>
+# include <class/cdc/cdc_device.h>
+#endif
+#else
+# include <USB/PluggableUSBSerial.h>
+#endif // __MBED__
+
+/*****************************************/
+/* Flash reprogramming from bootloader   */
+/*****************************************/
+
+#ifdef PLATFORM_BOOTLOADER_SIZE
+
+extern uint32_t __real_vectors_start;
+extern uint32_t __StackTop;
+static volatile void *g_bootloader_exit_req;
+
+__attribute__((section(".time_critical.platform_rewrite_flash_page")))
+bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_PAGE_SIZE])
+{
+    if (offset == PLATFORM_BOOTLOADER_SIZE)
+    {
+        if (buffer[3] != 0x20 || buffer[7] != 0x10)
+        {
+            logmsg("Invalid firmware file, starts with: ", bytearray(buffer, 16));
+            return false;
+        }
+    }
+
+
+#ifdef __MBED__
+    if (NVIC_GetEnableIRQ(USBCTRL_IRQn))
+    {
+        logmsg("Disabling USB during firmware flashing");
+        NVIC_DisableIRQ(USBCTRL_IRQn);
+        usb_hw->main_ctrl = 0;
+    }
+#endif // __MBED__
+
+    dbgmsg("Writing flash at offset ", offset, " data ", bytearray(buffer, 4));
+    assert(offset % PLATFORM_FLASH_PAGE_SIZE == 0);
+    assert(offset >= PLATFORM_BOOTLOADER_SIZE);
+
+    // Avoid any mbed timer interrupts triggering during the flashing.
+    __disable_irq();
+
+    // For some reason any code executed after flashing crashes
+    // unless we disable the XIP cache.
+    // Not sure why this happens, as flash_range_program() is flushing
+    // the cache correctly.
+    // The cache is now enabled from bootloader start until it starts
+    // flashing, and again after reset to main firmware.
+    xip_ctrl_hw->ctrl = 0;
+
+    flash_range_erase(offset, PLATFORM_FLASH_PAGE_SIZE);
+    flash_range_program(offset, buffer, PLATFORM_FLASH_PAGE_SIZE);
+
+    uint32_t *buf32 = (uint32_t*)buffer;
+    uint32_t num_words = PLATFORM_FLASH_PAGE_SIZE / 4;
+    for (int i = 0; i < num_words; i++)
+    {
+        uint32_t expected = buf32[i];
+        uint32_t actual = *(volatile uint32_t*)(XIP_NOCACHE_BASE + offset + i * 4);
+
+        if (actual != expected)
+        {
+            logmsg("Flash verify failed at offset ", offset + i * 4, " got ", actual, " expected ", expected);
+            __enable_irq();
+            return false;
+        }
+    }
+
+    __enable_irq();
+
+    return true;
+}
+
+
+void platform_boot_to_main_firmware()
+{
+    // To ensure that the system state is reset properly, we perform
+    // a SYSRESETREQ and jump straight from the reset vector to main application.
+    g_bootloader_exit_req = &g_bootloader_exit_req;
+    SCB->AIRCR = 0x05FA0004;
+    while(1);
+}
+
+void btldr_reset_handler()
+{
+    uint32_t* application_base = &__real_vectors_start;
+    if (g_bootloader_exit_req == &g_bootloader_exit_req)
+    {
+        // Boot to main application
+        application_base = (uint32_t*)(XIP_BASE + PLATFORM_BOOTLOADER_SIZE);
+    }
+
+    SCB->VTOR = (uint32_t)application_base;
+    __asm__(
+        "msr msp, %0\n\t"
+        "bx %1" : : "r" (application_base[0]),
+                    "r" (application_base[1]) : "memory");
+}
+
+// Replace the reset handler when building the bootloader
+// The rp2040_btldr.ld places real vector table at an offset.
+__attribute__((section(".btldr_vectors")))
+const void * btldr_vectors[2] = {&__StackTop, (void*)&btldr_reset_handler};
+
+#endif // PLATFORM_BOOTLOADER_SIZE

+ 0 - 217
lib/ZuluSCSI_platform_RP2040/rp2040-daynaport.ld

@@ -1,217 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2023 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version. 
- * 
- * 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.  See the
- * GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
-**/
-
-MEMORY
-{
-    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 576k
-    RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k  /* Leave space for pico-debug */
-    SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
-    SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
-}
-ENTRY(_entry_point)
-SECTIONS
-{
-    .flash_begin : {
-        __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")
-    /* If ZuluSCSI SD card bootloader is included, it goes in first 128 kB */
-    
-    .text.bootloader : ALIGN(16) SUBALIGN(16)
-    {
-        KEEP(*(.text.btldr*))
-        . = ALIGN(131072);
-        CHECK_BOOTLOADER_SIZE = 1 / (. <= 131072);
-    } > FLASH
-
-    .text : {
-        __logical_binary_start = .;
-        __real_vectors_start = .;
-        KEEP (*(.vectors))
-        KEEP (*(.binary_info_header))
-        __binary_info_header_end = .;
-        KEEP (*(.reset))
-        KEEP (*(.init))
-        *(.fini)
-        *crtbegin.o(.ctors)
-        *crtbegin?.o(.ctors)
-        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
-        *(SORT(.ctors.*))
-        *(.ctors)
-        *crtbegin.o(.dtors)
-        *crtbegin?.o(.dtors)
-        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
-        *(SORT(.dtors.*))
-        *(.dtors)
-        *(.eh_frame*)
-        . = ALIGN(4);
-
-        /* Put only non-timecritical code in flash
-         * This includes e.g. floating point math routines.
-         */
-        *libm*:(.text .text*)
-        *libc*:(.text .text*)
-        *libgcc*:*df*(.text .text*)
-        *USB*(.text .text*)
-        *SPI*(.text .text*)
-        *Spi*(.text .text*)
-        *spi*(.text .text*)
-        *stdc*:(.text .text*)
-        *supc*:(.text .text*)
-        *nosys*:(.text .text*)
-        *libc*:*printf*(.text .text*)
-        *libc*:*toa*(.text .text*)
-        *libminIni.a:(.text .text*)
-        *libCUEParser.a:(.text .text*)
-        /* RP2040 breakpoints in RAM code don't always work very well
-         * because the boot routine tends to overwrite them.
-         * Uncommenting this line puts all code in flash.
-         */
-        /* *(.text .text*) */
-    } > FLASH
-    .rodata : {
-        . = ALIGN(4);
-        *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*)))
-        *(.rodata)
-        *(.rodata*)
-        . = ALIGN(4);
-    } > FLASH
-    .ARM.extab :
-    {
-        *(.ARM.extab* .gnu.linkonce.armextab.*)
-    } > FLASH
-    __exidx_start = .;
-    .ARM.exidx :
-    {
-        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-    } > FLASH
-    __exidx_end = .;
-    . = ALIGN(4);
-    __binary_info_start = .;
-    .binary_info :
-    {
-        KEEP(*(.binary_info.keep.*))
-        *(.binary_info.*)
-    } > FLASH
-    __binary_info_end = .;
-    . = ALIGN(4);
-    __etext = .;
-   .ram_vector_table (COPY): {
-        *(.ram_vector_table)
-    } > RAM
-    .data : {
-        __data_start__ = .;
-        *(vtable)
-
-        /* Time critical code will go here to avoid external flash latency */
-        *(.time_critical*)
-        . = ALIGN(4);
-        *(.text)
-        *(.text*)
-
-        . = ALIGN(4);
-        *(.data*)
-        . = ALIGN(4);
-        *(.after_data.*)
-        . = ALIGN(4);
-        PROVIDE_HIDDEN (__mutex_array_start = .);
-        KEEP(*(SORT(.mutex_array.*)))
-        KEEP(*(.mutex_array))
-        PROVIDE_HIDDEN (__mutex_array_end = .);
-        . = ALIGN(4);
-        PROVIDE_HIDDEN (__preinit_array_start = .);
-        KEEP(*(SORT(.preinit_array.*)))
-        KEEP(*(.preinit_array))
-        PROVIDE_HIDDEN (__preinit_array_end = .);
-        . = ALIGN(4);
-        PROVIDE_HIDDEN (__init_array_start = .);
-        KEEP(*(SORT(.init_array.*)))
-        KEEP(*(.init_array))
-        PROVIDE_HIDDEN (__init_array_end = .);
-        . = ALIGN(4);
-        PROVIDE_HIDDEN (__fini_array_start = .);
-        *(SORT(.fini_array.*))
-        *(.fini_array)
-        PROVIDE_HIDDEN (__fini_array_end = .);
-        *(.jcr)
-        . = ALIGN(4);
-        __data_end__ = .;
-    } > RAM AT> FLASH
-    .uninitialized_data (COPY): {
-        . = ALIGN(4);
-        *(.uninitialized_data*)
-    } > RAM
-    .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 (COPY):
-    {
-        __end__ = .;
-        PROVIDE(end = .);
-        *(.heap*)
-        . = ORIGIN(RAM) + LENGTH(RAM) - 0x400;
-        __HeapLimit = .;
-    } > RAM
-    .stack1_dummy (COPY):
-    {
-        *(.stack1*)
-    } > SCRATCH_X
-    .stack_dummy (COPY):
-    {
-        *(.stack*)
-    } > RAM
-    .flash_end : {
-        __flash_binary_end = .;
-    } > FLASH
-    __StackTop = ORIGIN(RAM) + LENGTH(RAM);
-    __StackLimit = __StackTop - 0x400;
-    __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
-    __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
-    __StackBottom = __StackTop - SIZEOF(.stack_dummy);
-    PROVIDE(__stack = __StackTop);
-    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")
-}

+ 7 - 2
lib/ZuluSCSI_platform_RP2040/rp2040.ld → lib/ZuluSCSI_platform_RP2040/rp2040-template.ld

@@ -21,7 +21,7 @@
 
 MEMORY
 {
-    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 352k
+    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = $program_size
     RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 256k  /* Leave space for pico-debug */
     SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
     SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k
@@ -73,6 +73,11 @@ SECTIONS
         /* Put only non-timecritical code in flash
          * This includes e.g. floating point math routines.
          */
+        .pio/build/$project_name/src/ZuluSCSI_log.cpp.o(.text .text*)
+        .pio/build/$project_name/src/ZuluSCSI_log_trace.cpp.o(.text .text*)
+        .pio/build/$project_name/src/ZuluSCSI_settings.cpp.o(.text .text*)
+        .pio/build/$project_name/src/QuirksCheck.cpp.o(.text .text*)
+        *libZuluSCSI_platform_RP2040.a:ZuluSCSI_platform.cpp.o(.text .text*)
         *libm*:(.text .text*)
         *libc*:(.text .text*)
         *libgcc*:*df*(.text .text*)
@@ -86,6 +91,7 @@ SECTIONS
         *libc*:*printf*(.text .text*)
         *libc*:*toa*(.text .text*)
         *libminIni.a:(.text .text*)
+        *libCUEParser.a:(.text .text*)
 
         /* RP2040 breakpoints in RAM code don't always work very well
          * because the boot routine tends to overwrite them.
@@ -132,7 +138,6 @@ SECTIONS
         . = ALIGN(4);
         *(.text)
         *(.text*)
-
         . = ALIGN(4);
         *(.data*)
         . = ALIGN(4);

+ 17 - 4
platformio.ini

@@ -88,9 +88,14 @@ build_flags =
 platform = raspberrypi@1.9.0
 framework = arduino
 board = ZuluSCSI_RP2040
-extra_scripts = src/build_bootloader.py
+; How much flash in bytes the bootloader and main app will be allocated
+; It is used as the starting point for a ROM image save in flash
+program_flash_allocation = 360448
+extra_scripts =
+    src/build_bootloader.py
+    lib/ZuluSCSI_platform_RP2040/process-linker-script.py
 platform_packages = platformio/toolchain-gccarmnoneeabi@1.100301.220327
-board_build.ldscript = lib/ZuluSCSI_platform_RP2040/rp2040.ld
+board_build.ldscript = ${BUILD_DIR}/rp2040.ld
 ldscript_bootloader = lib/ZuluSCSI_platform_RP2040/rp2040_btldr.ld
 lib_deps =
     SdFat=https://github.com/rabbitholecomputing/SdFat#2.2.0-gpt
@@ -112,6 +117,8 @@ build_flags =
     -DHAS_SDIO_CLASS
     -DUSE_ARDUINO=1
     -DZULUSCSI_V2_0
+    -DROMDRIVE_OFFSET=${env:ZuluSCSI_RP2040.program_flash_allocation}
+    -Wl,-Map=${BUILD_DIR}/${PROGNAME}.map
 
 ; ZuluSCSI RP2040 hardware platform, as above, but with audio output support enabled
 [env:ZuluSCSI_RP2040_Audio]
@@ -144,9 +151,14 @@ platform_packages =
 framework = arduino
 board = rpipicow
 board_build.core = earlephilhower
-extra_scripts = src/build_bootloader.py
+; How much flash in bytes the bootloader and main app will be allocated
+; It is used as the starting point for a ROM image save in flash
+program_flash_allocation = 589824
+extra_scripts =
+    src/build_bootloader.py
+    lib/ZuluSCSI_platform_RP2040/process-linker-script.py
 ldscript_bootloader = lib/ZuluSCSI_platform_RP2040/rp2040_btldr.ld
-board_build.ldscript = lib/ZuluSCSI_platform_RP2040/rp2040-daynaport.ld
+board_build.ldscript = ${BUILD_DIR}/rp2040.ld
 debug_tool = cmsis-dap
 debug_build_flags =
     -O2 -ggdb -g3
@@ -174,6 +186,7 @@ build_flags =
     -DZULUSCSI_PICO
     -DZULUSCSI_NETWORK
     -DZULUSCSI_DAYNAPORT
+    -DROMDRIVE_OFFSET=${env:ZuluSCSI_Pico_DaynaPORT.program_flash_allocation}
 ; These take a large portion of the SRAM and can be adjusted
     -DLOGBUFSIZE=8192
     -DPREFETCH_BUFFER_SIZE=4608

+ 1 - 1
src/ZuluSCSI_config.h

@@ -28,7 +28,7 @@
 #include <ZuluSCSI_platform.h>
 
 // Use variables for version number
-#define FW_VER_NUM      "24.03.08"
+#define FW_VER_NUM      "24.03.12"
 #define FW_VER_SUFFIX   "dev"
 #define ZULU_FW_VERSION FW_VER_NUM "-" FW_VER_SUFFIX