Adds doc/10_usb_bootloader.md as the primary reference for the UF2 bootloader (memory layout, key-based boot entry, build/flash steps, hardware test findings, known limitations), following the existing numbered-doc convention. Updates doc/INDEX.md, doc/09_known_limitations.md (bootloader is no longer "not supported", just scoped), and doc/08_development.md accordingly. Removes bootloader/TESTING.md (its findings now live in doc/10_usb_bootloader.md) and trims bootloader/README.md down to what belongs with that subproject specifically: upstream attribution/license and local build/flash commands, plus the OpenOCD manual-flashing warning since that's implementation-specific detail that would clutter the higher-level doc. Updates the top-level README.md (feature table, hardware table, quickstart, project tree, doc links) to reflect USB flashing as a supported path alongside SWD. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| boards | ||
| inc | ||
| include | ||
| lib | ||
| scripts | ||
| src | ||
| LICENSE-uf2-samdx1 | ||
| platformio.ini | ||
| README.md | ||
VersaMCU UF2-Bootloader
USB-Bootloader für das VersaPad-v2-Makropad. Wird per Atmel-ICE/SWD einmalig
auf den ATSAMD21G17D geflasht und belegt 0x0000..0x1FFF (8 KiB). Danach
lässt sich die App-Firmware ohne SWD über USB aktualisieren.
Speicherlayout, Bootloader-Aktivierung, Bedienung und Hardwaretest-Ergebnisse
stehen in ../doc/10_usb_bootloader.md. Diese
Datei beschreibt nur das Bootloader-Unterprojekt selbst.
Herkunft
Abgeleitet und stark eingekürzt aus
microsoft/uf2-samdx1 (MIT-Lizenz,
siehe LICENSE-uf2-samdx1). Übernommen wurden nur die
SAMD21-Bootloader-Sourcen (src/, inc/), die zugehörigen CMSIS-/ASF-Header
für genau den SAMD21G17A-Chip (lib/) sowie das Linkerskript, angepasst auf
den 128-KiB-Flash/16-KiB-RAM-Chip auf diesem Board (Original-Vorlagen zielen
auf 256-KiB-Chips wie den SAMD21G18A). Board-Vorlage war boards/gemma_m0
aus dem Original-Repo (crystalless, gleiche USB_VID wie unser Board).
Nicht übernommen: SAMD51/SAME54-Support, der Bootloader-Selbstupdate-Pfad
(selfmain.c, sketch.cpp, das python2-Tooling uf2conv.py/gendata.py)
und das Node-/Makefile-basierte Build-System — stattdessen ein eigenständiges
PlatformIO-Environment, damit dasselbe Tooling wie für die App-Firmware
ausreicht.
Für die App-Seite (nicht diesen Bootloader-Build) gibt es unter
../uf2conv.py eine eigene, minimale Python-3-Neuimplemen-
tierung des .bin→.uf2-Konverters (kein Upstream-Code, passendes
Blockformat zu inc/uf2format.h), eingebunden über
../upload_uf2.py als env:versapad_usb-Upload-Hook.
Build
cd bootloader
pio run -e versapad_bootloader
Flash (Atmel-ICE/SWD, einmalig, überschreibt ggf. vorhandene App-Firmware nicht,
da nur 0x0000..0x1FFF beschrieben wird)
pio run -e versapad_bootloader --target upload
Achtung bei manuellem SWD-Flashen von Bootloader UND App
upload_openocd.py (App, env:versapad) und der Bootloader-Upload (oben)
sind sicher, weil sie jeweils nur ihren eigenen Bereich anfassen. Beim
manuellen Debuggen über OpenOCD-Kommandozeile aber Vorsicht:
openocd -c "program datei.elf verify" ohne explizite Zieladresse hat
sich in dieser Kombination aus OpenOCD-Version/CMSIS-DAP-Adapter/Target-Skript
als unzuverlässig erwiesen — statt die im ELF hinterlegten Sektionsadressen
(0x2000 für die App) zu nutzen, landeten die rohen Datei-Bytes teils direkt
ab Flash-Adresse 0x0000 und haben damit den frisch geschriebenen Bootloader
sofort wieder überschrieben (bestätigt am 2026-08-05: Byte 0 an Adresse
0x0000 war 0x7f, der Beginn der ELF-Magic \x7fELF — die rohe Datei, kein
Firmware-Code). Passierte zuverlässig, wenn Bootloader- und App-Flash im
selben OpenOCD-Aufruf kombiniert wurden.
Regel für manuelles SWD-Flashen beider Bereiche: immer die .bin-Datei
verwenden (nie .elf) und die Zieladresse immer explizit angeben
(program firmware.bin 0x0 verify für den Bootloader,
program firmware.bin 0x2000 verify für die App), und Bootloader- und
App-Schreibvorgang in getrennten OpenOCD-Aufrufen, nicht in einer
gemeinsamen -c-Kommandokette. Im Zweifel danach mit dump_image in einer
frischen, unabhängigen Sitzung verifizieren.