Add crt0 support for running through the bootrom when using no_flash binaries with a debugger This allows using load_maps to load code under the debugger (eg xip_sram pinning, or copying around stuff) Enable this by default - minimal code size impact on Arm (0x4) as it would need to setup RCP and SP otherwise, but more on Risc-V (0x2a)
diff --git a/src/rp2_common/pico_crt0/crt0.S b/src/rp2_common/pico_crt0/crt0.S index 287d2ce..aa1546e 100644 --- a/src/rp2_common/pico_crt0/crt0.S +++ b/src/rp2_common/pico_crt0/crt0.S
@@ -12,6 +12,7 @@ #include "hardware/regs/addressmap.h" #include "hardware/regs/sio.h" #include "hardware/regs/xip.h" +#include "hardware/regs/watchdog.h" #include "pico/binary_info/defs.h" #include "boot/picobin.h" #include "pico/bootrom.h" @@ -31,6 +32,15 @@ #define PICO_CRT0_NO_DATA_COPY PICO_NO_FLASH #endif +// PICO_CONFIG: PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM, Whether crt0 should always reset through the bootrom when loaded using a debugger - not supported on RP2040, default=1, type=bool, advanced=true, group=pico_crt0 +#if PICO_RP2040 +#define PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM 0 +#else +#ifndef PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM +#define PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM 1 +#endif +#endif + #ifdef NDEBUG #ifndef COLLAPSE_IRQS #define COLLAPSE_IRQS @@ -393,7 +403,7 @@ .global _entry_point _entry_point: -#if PICO_NO_FLASH +#if PICO_NO_FLASH && !PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM // on the NO_FLASH case, we do not do a rest thru bootrom below, so the RCP may or may not have been initialized: // // in the normal (e.g. UF2 download etc. case) we will have passed thru bootrom initialization, but if @@ -425,9 +435,28 @@ ldr r0, =__vectors // Vector through our own table (SP, VTOR will not have been set up at // this point). Same path for debugger entry and bootloader entry. -#else - // Debugger tried to run code after loading, so SSI is in 03h-only mode. - // Go back through bootrom + boot2 to properly initialise flash. +#else // PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM or !PICO_NOFLASH + #if PICO_NO_FLASH // PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM is always 0 on RP2040, so this code doesn't support RP2040 + // Launch this no_flash binary using a RAM image boot + ldr r1, =(WATCHDOG_BASE + WATCHDOG_SCRATCH2_OFFSET) // offsets start from here, to fit in str immediate + // scratch 2 = __logical_binary_start + ldr r0, =__logical_binary_start + str r0, [r1, #0] + // scratch 3 = size + ldr r0, =(SRAM_END - SRAM_BASE) // assume maximum size for block loop + str r0, [r1, #4] + // scratch 4&7 = magic number + ldr r0, =0xb007c0d3 + str r0, [r1, #8] + str r0, [r1, #20] + // scratch 5 = magic number xored with -(magic number) == -2 + ldr r0, =(-2) + str r0, [r1, #12] + // scratch 6 = ram image boot == 3 + ldr r0, =3 + str r0, [r1, #16] + #endif + // Go back through bootrom to finish the boot. ldr r0, =BOOTROM_VTABLE_OFFSET #endif
diff --git a/src/rp2_common/pico_crt0/crt0_riscv.S b/src/rp2_common/pico_crt0/crt0_riscv.S index fbdeb0d..be084ee 100644 --- a/src/rp2_common/pico_crt0/crt0_riscv.S +++ b/src/rp2_common/pico_crt0/crt0_riscv.S
@@ -8,6 +8,7 @@ #include "hardware/regs/addressmap.h" #include "hardware/regs/rvcsr.h" +#include "hardware/regs/watchdog.h" #include "pico/binary_info/defs.h" #include "boot/picobin.h" #include "pico/bootrom_constants.h" @@ -38,6 +39,10 @@ #define PICO_USE_XIP_CACHE_AS_RAM PICO_XIP_RAM #endif +#ifndef PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM +#define PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM 1 +#endif + // If vectors are in RAM, we put them in the .data section, so that they are // preloaded by _reset_handler (assuming this is not a loaded-in-place // binary). @@ -297,11 +302,31 @@ .global _entry_point _entry_point: -#if PICO_NO_FLASH +#if PICO_NO_FLASH && !PICO_CRT0_ALWAYS_RESET_THROUGH_BOOTROM // Go through our own reset handler. Same path for debugger entry and // bootloader entry. j _reset_handler #else + #if PICO_NO_FLASH + // Launch this no_flash binary using a RAM image boot + la a1, WATCHDOG_BASE + WATCHDOG_SCRATCH2_OFFSET // offsets start from here, to fit in sw immediate + // scratch 2 = __logical_binary_start + la a0, __logical_binary_start + sw a0, 0(a1) + // scratch 3 = size + li a0, SRAM_END - SRAM_BASE // assume maximum size for block loop + sw a0, 4(a1) + // scratch 4&7 = magic number + li a0, 0xb007c0d3 + sw a0, 8(a1) + sw a0, 20(a1) + // scratch 5 = magic number xored with -(magic number) == -2 + li a0, -2 + sw a0, 12(a1) + // scratch 6 = ram image boot == 3 + li a0, 3 + sw a0, 16(a1) + #endif // Debugger tried to run code after loading, so SSI is in 03h-only mode. // Go back through bootrom + boot2 to properly initialise flash. j reenter_bootrom