Fold bootloader documentation into the main doc/ index

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>
This commit is contained in:
Julian Appel 2026-08-05 22:49:56 +02:00
parent 3986d2effe
commit 33d9e85992
7 changed files with 153 additions and 201 deletions

View file

@ -15,6 +15,7 @@ ATSAMD21G17D mit PlatformIO und dem Arduino-SAMD-Framework.
| LEDs | 20 WS2812B mit Base-/Override-Farbe und 7 Animationsmodi |
| Persistenz | Config und Makros im internen Flash |
| Recovery | Werksreset über zwei Tasten |
| Firmware-Update | SWD (Atmel-ICE) oder USB (UF2-Bootloader, `bootloader/`) |
Die drei Fader-Pins sind im Board-Variant definiert, werden von der aktuellen
Firmware aber noch nicht eingelesen.
@ -29,7 +30,7 @@ Firmware aber noch nicht eingelesen.
| Encoder | 4× Quadratur über EIC-Interrupts |
| LEDs | 20× WS2812B an `PB22` |
| USB | Native USB als HID + CDC Composite Device |
| Programmer | Atmel-ICE/CMSIS-DAP über SWD, standardmäßig ohne Bootloader |
| Programmer | Atmel-ICE/CMSIS-DAP über SWD, oder USB über den UF2-Bootloader |
## Schnellstart
@ -46,9 +47,17 @@ Das Standard-Environment `versapad` baut für `boards/versapad_nobl.json`. Der
Upload wird durch `upload_openocd.py` über das von PlatformIO installierte
OpenOCD ausgeführt.
Das in `platformio.ini` auskommentierte Bootloader-Environment ist derzeit
nicht als Produktionsziel unterstützt. Details stehen unter
[bekannte Einschränkungen](doc/09_known_limitations.md).
Alternativ lässt sich die App-Firmware nach einem einmaligen
SWD-Bootloader-Flash auch über USB aktualisieren, ganz ohne Atmel-ICE:
```bash
cd bootloader && pio run -e versapad_bootloader --target upload # einmalig
pio run -e versapad_usb --target upload # danach jedes App-Update
```
Details, Speicherlayout und die Bootloader-Aktivierung (kein physischer
Reset-Taster auf dieser Platine) stehen in
[10_usb_bootloader.md](doc/10_usb_bootloader.md).
## Laufzeitmodell
@ -119,9 +128,13 @@ VersaMCU/
|-- AGENTS.md # Kontext und Richtlinien für Coding-LLMs
|-- README.md
|-- platformio.ini
|-- upload_openocd.py # SWD-Upload-Hook (env:versapad)
|-- uf2conv.py # .bin -> .uf2 Konverter (App-Firmware)
|-- upload_uf2.py # USB-Upload-Hook (env:versapad_usb)
|-- boards/ # PlatformIO-Boarddefinitionen
|-- variants/versapad/ # Pinmapping und Linker-Skripte
|-- doc/ # Architektur- und Protokolldokumentation
|-- bootloader/ # UF2-Bootloader (eigenes PlatformIO-Projekt)
`-- src/
|-- main.cpp
|-- CMainController.* # Orchestrierung
@ -157,3 +170,4 @@ Binärverträge, Änderungsregeln und die minimale Verifikation.
- [CDC-Protokoll](doc/07_serial_protocol.md)
- [Entwicklung und Einstieg](doc/08_development.md)
- [Bekannte Einschränkungen](doc/09_known_limitations.md)
- [USB-Bootloader](doc/10_usb_bootloader.md)

View file

@ -2,18 +2,11 @@
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, Board erscheint als USB-Laufwerk `VERSABOOT`, `.uf2`-Datei drauf
kopieren.
lässt sich die App-Firmware ohne SWD über USB aktualisieren.
Der komplette Weg — Bootloader-Einstieg, `.uf2`-Erzeugung, Kopieren aufs
Laufwerk, automatischer Rücksprung in die neu geschriebene App — ist auf
echter Hardware verifiziert, siehe [Hardwaretest](#hardwaretest-2026-08-05).
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).
Speicherlayout, Bootloader-Aktivierung, Bedienung und Hardwaretest-Ergebnisse
stehen in [`../doc/10_usb_bootloader.md`](../doc/10_usb_bootloader.md). Diese
Datei beschreibt nur das Bootloader-Unterprojekt selbst.
## Herkunft
@ -52,42 +45,6 @@ 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.
## App-Firmware per USB flashen (nach dem einmaligen Bootloader-Flash)
```bash
# Board zuerst in den Bootloader-Modus versetzen: USB ziehen, unterste
# rechte Taste halten, wieder einstecken (siehe oben)
pio run -e versapad_usb --target upload
```
Baut die App-Firmware (Repo-Root, nicht `bootloader/`), erzeugt `firmware.uf2`
und kopiert es aufs `VERSABOOT`-Laufwerk. Kein Atmel-ICE mehr nötig.
## Achtung bei manuellem SWD-Flashen von Bootloader UND App
`upload_openocd.py` (App, `env:versapad`) und der Bootloader-Upload (oben)
@ -111,61 +68,3 @@ verwenden (nie `.elf`) und die Zieladresse **immer explizit angeben**
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.
## 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.
- **Zweiter Bug beim manuellen Debuggen gefunden:** Beim anschließenden
manuellen SWD-Debugging (Suche nach der Ursache des Tastencheck-Problems,
siehe oben) hat `openocd -c "program app.elf verify"` ohne explizite
Zieladresse wiederholt den Bootloader mit rohen ELF-Datei-Bytes
überschrieben, sobald Bootloader- und App-Flash im selben OpenOCD-Aufruf
kombiniert wurden — siehe "Achtung bei manuellem SWD-Flashen" oben. Nach
einem vollständigen Chip-Erase und getrennten `.bin`-Flashes mit expliziten
Adressen liefen beide Bereiche wieder zuverlässig, Tastencheck und
App-Start bestätigt funktionsfähig.
- **Kompletter USB-Flashweg getestet:** `pio run -e versapad_usb --target
upload` (App-Firmware, Repo-Root) baut `firmware.bin`, wandelt es über
[`../uf2conv.py`](../uf2conv.py) in `firmware.uf2` und kopiert es über
[`../upload_uf2.py`](../upload_uf2.py) automatisch aufs erkannte
`VERSABOOT`-Laufwerk. Der Bootloader erkennt den Schreibzugriff und
springt danach selbständig in die neue App — kein manuelles Auswerfen
oder Reset nötig. Voraussetzung: Board zuvor per gehaltener Taste (siehe
oben) in den Bootloader-Modus versetzt.
## Bekannte Einschränkungen
- 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 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.
- [`../upload_uf2.py`](../upload_uf2.py) sucht das `VERSABOOT`-Laufwerk aktuell
nur über die Windows-API (`GetVolumeInformationW`) — passend zur bisherigen
Dev-Umgebung dieses Projekts, aber nicht plattformübergreifend. Für
macOS/Linux müsste die Laufwerkssuche noch ergänzt werden.

View file

@ -1,65 +0,0 @@
# Bootloader-Testflash -- Ergebnis
Der UF2-Bootloader (siehe [README.md](README.md)) wurde am 2026-08-05 auf
einem echten VersaPad-v2-Board über Atmel-ICE/SWD getestet. Zusammenfassung
der Ergebnisse steht im [Hardwaretest-Abschnitt der README](README.md#hardwaretest-2026-08-05).
Dieses Dokument hält den Testablauf und die Antworten auf die ursprünglichen
Prüffragen fest.
**Sicherheitsrahmen, der eingehalten wurde:** Der Bootloader-Flash schreibt
nur `0x0000..0x1FFF` (8 KiB). Die App-Firmware ab `0x2000` blieb dabei
unangetastet. Über SWD war der Chip jederzeit neu beschreibbar; ein Brick war
zu keinem Zeitpunkt möglich, solange der Atmel-ICE-Zugriff funktionierte.
## Voraussetzungen
- Board per Atmel-ICE/SWD angeschlossen, wie beim normalen
App-Firmware-Flashen (`pio run -e versapad --target upload`,
siehe `../doc/08_development.md`)
- PlatformIO Core (hier: PlatformIO-IDE-penv unter
`%USERPROFILE%\.platformio\penv\Scripts\pio.exe`)
## Ablauf
1. `git checkout feature/usb-bootloader`
2. `cd bootloader && pio run -e versapad_bootloader` — Build sauber
(89,9 % Flash, 7364/8192 Byte)
3. `pio run -e versapad_bootloader --target upload` — Flash + Verify über
Atmel-ICE/SWD
## Ursprüngliche Prüffragen und Antworten
- **Ist der Flash-Befehl ohne Fehler durchgelaufen?** Ja, `** Verified OK **`
bei jedem Flash.
- **Erscheint nach dem Bootloader-Einstieg ein Laufwerk `VERSABOOT`?** Ja.
Getestete Board-Revision hat **keinen physischen Reset-/Boot-Taster**
(Custom-PCB) — der ursprünglich geplante Doppel-Tap-Reset-Test war damit
nicht durchführbar. Stattdessen wurde ein Hardware-Bootloader-Einstieg über
eine gehaltene Cherry-MX-Taste ergänzt, siehe
[README.md](README.md#hardware-bootloader-einstieg-ohne-reset-taster).
Mit dieser Ergänzung: gehaltene Taste beim Power-On → `VERSABOOT`.
- **Was steht in `INFO_UF2.TXT`?**
```
UF2 Bootloader versapad-1 SFHWRO
Model: VersaPad v2
Board-ID: SAMD21G17D-VersaPad-v2
```
- **Reagiert das Board normal als App-Firmware, wenn man es ohne gehaltene
Taste ansteckt?** Ja, nach dem in der README beschriebenen DSB/ISB-Fix.
Vor dem Fix: nein, siehe unten.
- **Ungewöhnliches?** Ja, ein echter Bug: siehe
[Hardwaretest-Abschnitt der README](README.md#hardwaretest-2026-08-05) für
die Fehlersuche (Bootloader-eigener Sprung faultete zuverlässig, obwohl vom
Debugger injizierte identische Register-/VTOR-Werte einwandfrei liefen) und
den Fix (fehlende `__DSB()`/`__ISB()` vor dem `bx` in
`check_start_application()`).
- **USB-Identität korrekt, kein Fremdtreiber-Konflikt?** Nach PID-Wechsel von
`0x0011` auf `0x0043` ja (siehe README, "Bekannte Einschränkungen" zum
ursprünglichen Adafruit-PID-Konflikt).
## Noch NICHT getestet
Firmware tatsächlich über das `VERSABOOT`-Laufwerk flashen. Der
Firmware-Build der App erzeugt noch keine `.uf2`-Datei (nur `.bin`/`.elf` für
den SWD-Weg) — das ist der nächste Schritt, siehe README, "Bekannte
Einschränkungen".

View file

@ -26,9 +26,9 @@ pio run -e versapad --target upload
Der Upload nutzt `upload_openocd.py`, das das von PlatformIO installierte
OpenOCD mit `interface/cmsis-dap.cfg` und `target/at91samdXX.cfg` startet.
Das in `platformio.ini` nur als Beispiel enthaltene Environment
`versapad_usb` ist auskommentiert und mit dem aktuellen NVM-/Linker-Layout
nicht als unterstützt anzusehen.
Für App-Updates über USB (nach einem einmaligen Bootloader-Flash) gibt es
zusätzlich `env:versapad_usb`, siehe
[10_usb_bootloader.md](10_usb_bootloader.md).
## Was beim Start passiert
@ -63,6 +63,7 @@ und NVM-Schreibvorgängen. Es gibt keinen Scheduler und keine Threads.
| LEDs | `05_led_system.md` | `CButton.*`, `hal/ws2812.*` |
| Persistente Config | `06_nvm_config.md` | `config/nvm_config.*`, Linker-Skripte |
| Host-Protokoll | `07_serial_protocol.md` | `hal/usb_serial.*`, Controller |
| USB-Bootloader | `10_usb_bootloader.md` | `bootloader/`, `variants/versapad/linker_scripts/gcc/flash_with_bootloader.ld`, `boards/versapad.json`, `uf2conv.py`, `upload_uf2.py` |
## Verifikation

View file

@ -3,36 +3,33 @@
Diese Liste beschreibt den aktuellen Implementierungsstand nach den
Robustheitskorrekturen. Sie ist keine Liste bereits umgesetzter Features.
## Bootloader-Ziel bleibt nicht unterstützt
## USB-Bootloader hat einen eingeschränkten Gültigkeitsbereich
Das aktive Ziel `versapad_nobl` reserviert den kompletten Bereich
`0x1FB00..0x1FFFF` für Makros und Config.
Der UF2-Bootloader (`bootloader/`, App-Environment `env:versapad_usb`,
Details in [10_usb_bootloader.md](10_usb_bootloader.md)) ist auf echter
Hardware verifiziert und ergänzt den SWD-Weg, ersetzt ihn aber nicht: der
Bootloader selbst muss weiterhin einmalig per Atmel-ICE/SWD geflasht werden.
Ein USB-Bootloader-Pfad wird im Branch `feature/usb-bootloader` aufgebaut
(`bootloader/`, App-Environment `env:versapad_usb`). Der komplette Weg ist
dort auf echter Hardware verifiziert: Bootloader-Flash, USB-Enumeration,
Tastencheck-Einstieg (kein physischer Reset-Taster auf diesem Board, siehe
`bootloader/README.md`, "Hardware-Bootloader-Einstieg"), App-Firmware per
`.uf2` über `env:versapad_usb --target upload` schreiben, automatischer
Rücksprung in die neue App. Details und ein gefundener/behobener
Hard-Fault-Bug beim Sprung Bootloader→App (fehlende `__DSB()`/`__ISB()` vor
dem `bx`) stehen in `bootloader/README.md`, "Hardwaretest".
`env:versapad_usb`s Linkerskript
(`variants/versapad/linker_scripts/gcc/flash_with_bootloader.ld`) reserviert
inzwischen denselben NVM-Bereich wie `flash_without_bootloader.ld`.
Verbleibende Einschränkungen:
Trotzdem noch kein Merge-fertiges Produktionsziel: Der `.bin``.uf2`-Weg
(`uf2conv.py`, `upload_uf2.py`, Repo-Root) sucht das `VERSABOOT`-Laufwerk
bisher nur über die Windows-API, keine macOS/Linux-Unterstützung. Die
Bootloader-USB-PID (`0x0043`) ist zwar kollisionsfrei verifiziert, aber kein
offiziell registrierter Wert unter Adafruits VID `0x239A`.
- `uf2conv.py`/`upload_uf2.py` (Repo-Root) suchen das `VERSABOOT`-Laufwerk
nur über die Windows-API, keine macOS/Linux-Unterstützung.
- Die Bootloader-USB-PID (`0x0043`) ist kollisionsfrei verifiziert, aber kein
offiziell registrierter Wert unter Adafruits VID `0x239A`.
- Kein Software-Trigger, um aus der laufenden App heraus in den
Bootloader-Modus zu wechseln — nur der physische Weg (Kabel ziehen, Taste
halten, wieder einstecken).
- Bootloader-Flash-Auslastung ~90 % (7364 von 8192 Byte), wenig Puffer für
Änderungen am Bootloader selbst.
Die aktive Boarddatei benennt die MCU als `samd21g17d`, setzt für den
Sowohl `boards/versapad_nobl.json` (SWD-Ziel) als auch `boards/versapad.json`
(USB-Bootloader-Ziel) benennen die MCU als `samd21g17d`, setzen für den
Arduino-Core aber weiterhin das Kompatibilitätsmakro `__SAMD21G18A__`. Der
PlatformIO-Build meldet korrekt 128 KiB physischen Flash, 16 KiB RAM und
129.792 Byte nutzbaren Firmwarebereich. Vor device-spezifischen
Core-Änderungen sollte die historische Makro-Abweichung trotzdem geprüft
werden.
129.792 Byte (`versapad_nobl`) beziehungsweise 121.600 Byte
(`versapad`, abzüglich 8 KiB Bootloader) nutzbaren Firmwarebereich. Vor
device-spezifischen Core-Änderungen sollte die historische Makro-Abweichung
trotzdem geprüft werden.
## Event-Queue hat eine feste Kapazität

104
doc/10_usb_bootloader.md Normal file
View file

@ -0,0 +1,104 @@
# USB-Bootloader (UF2)
Zweiter Firmware-Update-Weg neben SWD: ein UF2-Bootloader unter
`bootloader/` erlaubt, die App-Firmware über USB zu aktualisieren, ohne
Atmel-ICE. Der Bootloader selbst wird einmalig per SWD geflasht; danach
reicht für App-Updates ein PlatformIO-Befehl.
## Speicherlayout
| Bereich | Adresse | Größe | Environment |
|---|---|---|---|
| Bootloader | `0x00000..0x01FFF` | 8 KiB | `versapad_bootloader` (in `bootloader/`) |
| App-Firmware | `0x02000..0x1FAFF` | 118,75 KiB | `versapad_usb` |
| NVM (Makros + Config) | `0x1FB00..0x1FFFF` | 1,25 KiB | — |
Gleiches NVM-Layout wie beim SWD-Ziel `versapad_nobl`
(siehe [06_nvm_config.md](06_nvm_config.md)); nur die Firmware-Obergrenze
sinkt um die 8 KiB Bootloader. Linkerskript:
`variants/versapad/linker_scripts/gcc/flash_with_bootloader.ld`, Boarddatei:
`boards/versapad.json`.
## Bootloader-Einstieg ohne Reset-Taster
Die Platine hat keinen dedizierten Reset-/Boot-Taster. Statt eines
physischen Pins wird die unterste rechte Cherry-MX-Taste (`key_id 24`,
COL4 × ROW4, siehe [01_matrix.md](01_matrix.md)) beim Boot geprüft:
`check_start_application()` in `bootloader/src/main.c` treibt ROW4 kurz auf
LOW und liest COL4 zurück — noch vor der App-Adress-Validierung, funktioniert
also auch bei kaputter oder fehlender App-Firmware.
Bedienung: USB-Kabel ziehen, Taste gedrückt halten, wieder einstecken (Taste
weiter halten) → Board bootet in den Massenspeicher-Modus (`VERSABOOT`).
Ohne gehaltene Taste startet die App normal.
## Bauen und Flashen
Bootloader einmalig per SWD (überschreibt nur `0x0000..0x1FFF`):
```bash
cd bootloader
pio run -e versapad_bootloader --target upload
```
Danach App-Firmware per USB (Board vorher wie oben in den Bootloader-Modus
versetzen):
```bash
pio run -e versapad_usb --target upload
```
Baut die App, wandelt `firmware.bin` über `uf2conv.py` (Repo-Root, eigene
minimale Implementierung, kein Upstream-Code) in `firmware.uf2` und kopiert
es über `upload_uf2.py` aufs erkannte `VERSABOOT`-Laufwerk. Der Bootloader
erkennt den Schreibzugriff und springt selbständig in die neue App.
`upload_uf2.py` sucht das Laufwerk aktuell nur über die Windows-API
(`GetVolumeInformationW`) — keine macOS/Linux-Unterstützung.
## Herkunft und Details
Der Bootloader ist abgeleitet und stark eingekürzt aus
[microsoft/uf2-samdx1](https://github.com/microsoft/uf2-samdx1) (MIT), auf
den `SAMD21G17D`-Chip dieses Boards zugeschnitten. Herkunft, Lizenz und
vollständige Implementierungsdetails stehen in `bootloader/README.md`.
## Hardwaretest (2026-08-05) und gefundene Bugs
Kompletter Weg auf echter Hardware verifiziert: Bootloader-Flash,
USB-Enumeration, Tastencheck-Einstieg, App-Firmware per `.uf2` schreiben,
automatischer Rücksprung in die neue App. Details, Fehlerbilder und Fixes
stehen in `bootloader/README.md` unter "Hardwaretest"; kurz zusammengefasst:
- **Fehlende Synchronisationsbarriere beim Sprung Bootloader→App.** Der
Sprung (`__set_MSP``SCB->VTOR``bx`) faultete bei jedem
eigenständigen Boot. Fix: `__DSB(); __ISB();` vor dem `bx` in
`check_start_application()` — von ARM für dieses Pattern vorgeschrieben,
fehlte im vendorten Code.
- **USB-PID-Kollision.** Die ursprünglich übernommene PID `0x0011` ist
Adafruits eigene Gemma-M0-Bootloader-PID; Windows-Rechner mit
installiertem Adafruit-Treiber banden das Board fälschlich als
`Adafruit Circuit Playground`-COM-Port statt als Massenspeicher. Fix:
eigene PID `0x0043`.
- **OpenOCD-Falle beim manuellen SWD-Debuggen:** `program datei.elf verify`
ohne explizite Zieladresse hat wiederholt den Bootloader mit rohen
ELF-Datei-Bytes überschrieben, sobald Bootloader- und App-Flash im selben
OpenOCD-Aufruf kombiniert wurden. Bei manuellem Flashen beider Bereiche
immer `.bin` mit expliziter Adresse und getrennte OpenOCD-Aufrufe
verwenden — Details in `bootloader/README.md`, "Achtung bei manuellem
SWD-Flashen".
## Bekannte Einschränkungen
- Bootloader-Flash-Auslastung ~90 % (7364 von 8192 Byte) — wenig Puffer für
Änderungen am Bootloader selbst.
- Kein Status-LED-Feedback im Bootloader-Modus (nur WS2812-Kette, dafür ist
der Original-Code nicht ausgelegt).
- USB-PID `0x0043` ist kollisionsfrei verifiziert, aber kein offiziell
registrierter Wert unter Adafruits VID `0x239A`.
- `upload_uf2.py` ist Windows-only (siehe oben).
- Kein Software-Trigger, um aus der laufenden App heraus in den Bootloader
zurückzuspringen — nur der physische Kabel-raus/Taste-halten/Kabel-rein-Weg.
Wäre über einen neuen CDC-Befehl (siehe
[07_serial_protocol.md](07_serial_protocol.md)) nachrüstbar, der dieselbe
`DBL_TAP_MAGIC`-RAM-Adresse setzt und `NVIC_SystemReset()` aufruft.

View file

@ -17,6 +17,7 @@ Bereiche stehen ausdrücklich in
| [07_serial_protocol.md](07_serial_protocol.md) | 8-Byte-Protokoll, Config-/Makro-Transfer, ACK/NACK |
| [08_development.md](08_development.md) | Setup, Build, Einstieg nach Änderungstyp, Verifikation |
| [09_known_limitations.md](09_known_limitations.md) | Aktuelle technische Einschränkungen und Risiken |
| [10_usb_bootloader.md](10_usb_bootloader.md) | UF2-Bootloader, Speicherlayout, Tastencheck-Einstieg, USB-Flashweg |
Die Repository-weiten Richtlinien und der kompakte LLM-Kontext stehen in
[`../AGENTS.md`](../AGENTS.md).
@ -29,3 +30,4 @@ Die Repository-weiten Richtlinien und der kompakte LLM-Kontext stehen in
- Action-Semantik und HID-Hold: [03_action_engine.md](03_action_engine.md)
- CDC-Protokoll und Chunk-Zahlen: [07_serial_protocol.md](07_serial_protocol.md)
- bekannte Risiken vor strukturellen Änderungen: [09_known_limitations.md](09_known_limitations.md)
- Firmware per USB statt SWD flashen: [10_usb_bootloader.md](10_usb_bootloader.md)