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>
This commit is contained in:
parent
4749adcd1d
commit
f60a29137c
8 changed files with 234 additions and 82 deletions
|
|
@ -3,8 +3,19 @@
|
|||
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: Bootloader-Modus
|
||||
aktivieren (Doppel-Tap Reset), Board erscheint als USB-Laufwerk `VERSABOOT`,
|
||||
`.uf2`-Datei drauf kopieren.
|
||||
aktivieren, Board erscheint als USB-Laufwerk `VERSABOOT`, `.uf2`-Datei drauf
|
||||
kopieren.
|
||||
|
||||
Der Bootloader selbst (Flash, USB-Enumeration, Massenspeicher-Modus,
|
||||
Rücksprung in die App) ist auf echter Hardware verifiziert, siehe
|
||||
[Hardwaretest](#hardwaretest-2026-08-05). Der App-seitige `.uf2`-Schreibweg
|
||||
(Firmware tatsächlich über das Laufwerk aktualisieren) ist noch nicht gebaut,
|
||||
siehe [Bekannte Einschränkungen](#bekannte-einschränkungen).
|
||||
|
||||
Diese Platine hat keinen dedizierten Reset-/Boot-Taster. Bootloader-Modus
|
||||
aktivieren heißt hier: unterste rechte Cherry-MX-Taste (key_id 24) beim
|
||||
Einstecken/Reset gedrückt halten. Siehe
|
||||
[Hardware-Bootloader-Einstieg](#hardware-bootloader-einstieg-ohne-reset-taster).
|
||||
|
||||
## Herkunft
|
||||
|
||||
|
|
@ -37,15 +48,72 @@ da nur `0x0000..0x1FFF` beschrieben wird)
|
|||
pio run -e versapad_bootloader --target upload
|
||||
```
|
||||
|
||||
## Hardware-Bootloader-Einstieg ohne Reset-Taster
|
||||
|
||||
Die Platine hat keinen dedizierten Reset-/Boot-Taster (Custom-PCB-Design).
|
||||
Der klassische UF2-"Doppel-Tap-Reset" braucht aber gar keinen physischen Pin —
|
||||
`check_start_application()` in `src/main.c` prüft ein RAM-Flag
|
||||
(`DBL_TAP_PTR`/`DBL_TAP_MAGIC`), das bei jedem Reset gesetzt wird, unabhängig
|
||||
von der Reset-Quelle.
|
||||
|
||||
Statt eines eigenen Tasters wird die unterste rechte Cherry-MX-Taste
|
||||
(`key_id 24` in der App-Firmware, siehe `../src/config/pins.h`) missbraucht:
|
||||
|
||||
- `key_id 24` liegt auf COL4 (`PA08`) × ROW4 (`PA15`)
|
||||
- `boot_key_pressed()` in `src/main.c` treibt ROW4 kurz auf LOW und liest
|
||||
COL4 zurück — kein voller Matrixscan nötig, nur ein Drei-Pin-Check
|
||||
- der Check läuft ganz am Anfang von `check_start_application()`, noch vor
|
||||
der App-Adress-Validierung und vor der RCAUSE-/DBL-TAP-Logik: funktioniert
|
||||
also auch bei kaputter/gelöschter App-Firmware und bei normalem Power-On
|
||||
(Stecker ziehen/reinstecken), kein Software-Trigger in der App nötig
|
||||
- Pin-Konstanten stehen in `include/board_config.h`
|
||||
(`BOOT_KEY_ROW_PIN`/`BOOT_KEY_COL_PIN`)
|
||||
|
||||
Bedienung: USB-Kabel ziehen, unterste rechte Taste gedrückt halten, Kabel
|
||||
wieder einstecken (Taste dabei weiter halten) → Board bootet direkt in
|
||||
`VERSABOOT`. Ohne gehaltene Taste startet die App normal.
|
||||
|
||||
## Hardwaretest (2026-08-05)
|
||||
|
||||
Erster vollständiger Hardwaretest auf einem echten VersaPad-v2-Board über
|
||||
Atmel-ICE/SWD. Ergebnisse:
|
||||
|
||||
- Bootloader-Build/-Flash/-Verify laufen sauber (89,9 % Flash, 7364/8192 Byte).
|
||||
- USB-Enumeration und `VERSABOOT`-Massenspeicher-Modus funktionieren nach dem
|
||||
PID-Fix (siehe unten) korrekt, inklusive korrektem `INFO_UF2.TXT`.
|
||||
- Der Tastencheck (oben) funktioniert wie vorgesehen: gehaltene Taste beim
|
||||
Boot → `VERSABOOT`, sonst normaler App-Start.
|
||||
- **Kritischer Bug gefunden und behoben:** Der Sprung vom Bootloader in die
|
||||
App (`__set_MSP` → `SCB->VTOR` → `bx`) führte bei jedem echten,
|
||||
eigenständigen Boot (auch bei komplett getrenntem Debugger) zu einem
|
||||
Hard-Fault/Lockup der CPU. Identische Register-/VTOR-Werte, vom Debugger
|
||||
bei angehaltener CPU direkt injiziert, liefen dagegen einwandfrei — das
|
||||
grenzte den Fehler auf die *Ausführung* der Sprungsequenz selbst ein, nicht
|
||||
auf falsche Werte. Fix: `__DSB(); __ISB();` zwischen dem `SCB->VTOR`-Schreib-
|
||||
zugriff und dem `bx` in `check_start_application()` (`src/main.c`) — von ARM
|
||||
für genau dieses Bootloader-Pattern vorgeschrieben, hat im vendorten Code
|
||||
gefehlt. Nach dem Fix bootet die App-Firmware zuverlässig, mit und ohne
|
||||
angeschlossenen Debugger.
|
||||
|
||||
## Bekannte Einschränkungen
|
||||
|
||||
- Flash-Auslastung ~89 % (7292 von 8192 Byte). Wenig Puffer für Änderungen.
|
||||
- Kein physischer Boot-Pin definiert, nur Doppel-Tap-Reset (RAM-Magic-Wert).
|
||||
Ein Hardware-Fallback-Pin wäre für die Wiederherstellung bei kaputter
|
||||
App-Firmware sinnvoll, ist aber noch nicht eingerichtet.
|
||||
- Flash-Auslastung ~90 % (7364 von 8192 Byte). Wenig Puffer für Änderungen.
|
||||
- Kein Status-LED-Feedback im Bootloader-Modus, da die Platine nur eine
|
||||
WS2812-Kette (kein einfaches GPIO-LED oder DotStar) hat und der
|
||||
Original-Code dafür nicht ausgelegt ist.
|
||||
- USB_PID `0x0011` ist unverifiziert übernommen (siehe
|
||||
`../doc/09_known_limitations.md`), noch nicht auf echter Hardware getestet.
|
||||
- Ungetestet auf echter Hardware, siehe Branch `feature/usb-bootloader`.
|
||||
- USB_PID war ursprünglich `0x0011` (Adafruit Gemma M0s eigene
|
||||
Bootloader-PID, unverändert aus der Vorlage übernommen) — kollidierte auf
|
||||
Rechnern mit installiertem Adafruit-Treiber, wurde als `Adafruit Circuit
|
||||
Playground`-COM-Port statt als Massenspeicher gebunden. Verifiziert am
|
||||
2026-08-05, seither `0x0043`. Bleibt ein Wert ohne echte Registrierung
|
||||
(kein offiziell zugeteilter PID unter Adafruits VID); ein sauber eigener
|
||||
VID (z. B. über pid.codes) wäre die langfristig korrekte Lösung, ist aber
|
||||
nicht Teil dieses Branches.
|
||||
- Die App-Firmware erzeugt noch keine `.uf2`-Datei, nur `.bin`/`.elf`
|
||||
(SWD-Weg). Der geplante Weg über das `VERSABOOT`-Laufwerk ist damit noch
|
||||
nicht nutzbar.
|
||||
- `env:versapad_usb` in der Haupt-`platformio.ini` verwendet
|
||||
`upload_protocol = sam-ba` — das klassische Arduino/Atmel-SAM-BA-Protokoll,
|
||||
nicht das UF2/Massenspeicher-Verfahren dieses Bootloaders. Für echtes
|
||||
USB-Flashen wird stattdessen ein `.bin`→`.uf2`-Konvertierungsschritt plus
|
||||
einfaches Kopieren aufs Laufwerk benötigt, kein spezielles Upload-Protokoll.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue