VersaMCU/variants/versapad/linker_scripts/gcc/flash_with_bootloader.ld
Julian Appel f60a29137c Fix bootloader hardware bring-up and add key-based boot entry
Hardware-tested the UF2 bootloader end to end on a real VersaPad v2
board. Found and fixed a real bug: the bootloader's jump into the app
(__set_MSP -> SCB->VTOR -> bx) hard-faulted on every standalone boot,
even with the debugger fully disconnected; identical register/VTOR
values injected directly by a halted debugger ran fine, which pointed
at the missing __DSB()/__ISB() barriers ARM's own guidance requires
for this exact pattern. Also fixed a USB PID collision (0x0011 is
Adafruit's own Gemma M0 bootloader PID, misidentified by Windows as a
Circuit Playground COM port instead of exposing VERSABOOT).

This board has no dedicated reset/boot button, so add a hardware boot
entry that doesn't need one: holding the bottom-right Cherry MX key
(key_id 24) during reset/power-on drives its matrix row and reads its
column directly in the bootloader, before the app is even validated.

Also corrected the app-side flash_with_bootloader.ld (was missing the
NVM carve-out flash_without_bootloader.ld already has) and
boards/versapad.json (wrong flash/RAM size, wrong MCU macro, stale
PID), and enabled the previously-commented-out env:versapad_usb.

Documented findings in bootloader/README.md, bootloader/TESTING.md,
and doc/09_known_limitations.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 21:28:15 +02:00

101 lines
2.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Linker script for ATSAMD21G17D with 8KB bootloader (flash starts at 0x2000) */
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
MEMORY
{
rom (rx) : ORIGIN = 0x00002000, LENGTH = 0x0001D900 /* 118.25K Firmware (128K - 8K bootloader - 1.25K NVM) */
nvm (rx) : ORIGIN = 0x0001FB00, LENGTH = 0x00000500 /* 1.25K Makros + Config, same layout as flash_without_bootloader.ld */
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 /* 16K */
}
__StackTop = ORIGIN(ram) + LENGTH(ram);
__StackLimit = __StackTop - 0x1000;
SECTIONS
{
.text :
{
__text_start__ = .;
. = ALIGN(4);
KEEP(*(.isr_vector))
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
KEEP(*(.init))
__preinit_array_start = .;
KEEP(*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
__init_array_end = .;
KEEP(*crtbegin.o(.ctors))
KEEP(*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP(*(SORT(.ctors.*)))
KEEP(*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
__fini_array_start = .;
KEEP(*(.fini_array))
KEEP(*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP(*crtbegin.o(.dtors))
KEEP(*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP(*(SORT(.dtors.*)))
KEEP(*crtend.o(.dtors))
. = ALIGN(4);
} > rom
PROVIDE_HIDDEN(__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN(__exidx_end = .);
. = ALIGN(4);
__etext = .;
_etext = .;
.data : AT(__etext)
{
. = ALIGN(4);
__data_start__ = .;
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
__data_end__ = .;
_erelocate = .;
} > ram
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start__ = .;
_sbss = .;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
_ebss = .;
_ezero = .;
} > ram
. = ALIGN(4);
end = .;
_end = .;
}