Переглянути джерело

Dynamic linker script and fix ROMs for DaynaPORT

Converted the linker script to a Python string template.
It fills in the path value for the object files that are put into flash.
It also fills in the maximum flash allocated to the program.

The motivation for the different flash sizes is because the DaynaPORT
takes up more flash than allocated to the other RP2040 base builds.
To make the RP2040 build bigger to the same size of the DaynaPORT build
will break users the have a ROM drive installed on their ZuluSCSI. So
the code bases are built with different flash sizes.

Also fixed now is the DaynaPORT code now writes the ROM at the
program boundary instead of partially overwriting the code in flash.

The program boundary is set in the `platformio.ini` file with the
`program_flash_allocation` setting.
Morio 1 рік тому
батько
коміт
80eab4696c

+ 4 - 2
lib/ZuluSCSI_platform_RP2040/ZuluSCSI_platform.cpp

@@ -772,8 +772,10 @@ uint8_t platform_get_buttons()
 
 #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 + '"'
+        )
+)

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

@@ -1,222 +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.
-         */
-        .pio/build/ZuluSCSI_Pico_DaynaPORT/src/ZuluSCSI_log.cpp.o(.text .text*)
-        .pio/build/ZuluSCSI_Pico_DaynaPORT/src/ZuluSCSI_log_trace.cpp.o(.text .text*)
-        .pio/build/ZuluSCSI_Pico_DaynaPORT/src/ZuluSCSI_settings.cpp.o(.text .text*)
-        .pio/build/ZuluSCSI_Pico_DaynaPORT/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*)
-        *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")
-}

+ 5 - 5
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,10 +73,10 @@ SECTIONS
         /* Put only non-timecritical code in flash
          * This includes e.g. floating point math routines.
          */
-        .pio/build/ZuluSCSI_RP2040/src/ZuluSCSI_log.cpp.o(.text .text*)
-        .pio/build/ZuluSCSI_RP2040/src/ZuluSCSI_log_trace.cpp.o(.text .text*)
-        .pio/build/ZuluSCSI_RP2040/src/ZuluSCSI_settings.cpp.o(.text .text*)
-        .pio/build/ZuluSCSI_RP2040/src/QuirksCheck.cpp.o(.text .text*)
+        .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*)

+ 16 - 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,7 @@ 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
@@ -145,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
@@ -175,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