VersaMCU/doc/09_known_limitations.md
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

4.4 KiB

Bekannte Einschränkungen und Risiken

Diese Liste beschreibt den aktuellen Implementierungsstand nach den Robustheitskorrekturen. Sie ist keine Liste bereits umgesetzter Features.

Bootloader-Ziel bleibt nicht unterstützt

Das aktive Ziel versapad_nobl reserviert den kompletten Bereich 0x1FB00..0x1FFFF für Makros und Config.

Ein USB-Bootloader-Pfad wird im Branch feature/usb-bootloader aufgebaut (bootloader/, App-Environment env:versapad_usb). Der Bootloader selbst (UF2, bootloader/) ist dort auf echter Hardware verifiziert — inklusive eines gefundenen und behobenen Bugs beim Sprung in die App (fehlende __DSB()/__ISB() vor dem bx, siehe bootloader/README.md, "Hardwaretest"). env:versapad_usbs Linkerskript (variants/versapad/linker_scripts/gcc/flash_with_bootloader.ld) reserviert inzwischen denselben NVM-Bereich wie flash_without_bootloader.ld.

Trotzdem noch kein Produktionsziel: env:versapad_usb verwendet upload_protocol = sam-ba, das klassische Arduino/Atmel-SAM-BA-Protokoll — das spricht der UF2-Bootloader nicht. Die App-Firmware erzeugt außerdem noch keine .uf2-Datei. Vor einem Merge nach master fehlen also noch die .uf2-Erzeugung und ein Ende-zu-Ende-Test des tatsächlichen USB-Flashwegs (Datei aufs VERSABOOT-Laufwerk kopieren).

Die aktive Boarddatei benennt die MCU als samd21g17d, setzt 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.

Event-Queue hat eine feste Kapazität

Matrix- und Encoder-Producer verändern den Tail-Index nicht mehr gleichzeitig: Der Matrixcallback maskiert Interrupts während seines Queue-Pushs.

Die Queue besitzt aber weiterhin nur 16 nutzbare Slots. Bei Überlauf wird ein neues Event ohne Hostmeldung verworfen. Das kann vor allem während blockierender Makro-, NVM- oder Feedbackpfade auftreten.

Host-Command-Ausführung liegt in der Desktop-App

Die Firmware überträgt Command-ID, Key-/Encoder-ID und Eventrichtung vollständig. VersaGUI validiert und empfängt diese Pakete, führt eine Command-ID aber noch nicht als Prozess-, URL- oder frei konfigurierbare Hostaktion aus. Eine spätere Implementierung benötigt ein explizites, sicheres Mapping; beliebige Command-Strings sollten nicht direkt an eine Shell weitergegeben werden.

Grenzen des HID-Reports

Keyboard-Holds und Modifier werden referenzgezählt. Der USB-Descriptor kann maximal sechs unterschiedliche Keyboard-Usages gleichzeitig darstellen. Weitere Holds bleiben intern aktiv und rücken nach, sobald ein Report-Slot frei wird.

Der Consumer-Descriptor enthält genau ein Usage. Mehrere Consumer-Holds werden intern verwaltet, sichtbar ist jeweils das zuletzt gedrückte aktive Usage.

CDC bleibt ein festes, ungeframtes Paketprotokoll

Config- und Makrotransfers prüfen jetzt Chunkzahl, eindeutige Indizes und Vollständigkeit. Config besitzt zusätzlich CRC und Feldvalidierung.

Weiterhin gilt:

  • Das Protokoll hat kein Byte-Framing. Ein verlorenes oder zusätzliches Byte verschiebt die 8-Byte-Paketgrenzen bis zum Reconnect.
  • Einzelpakete besitzen keine Sequenznummer oder Prüfsumme.
  • Die Makrotabelle besitzt im NVM keine persistente CRC; beim Transfer werden nur Vollständigkeit und HID-Keycode-Bereiche geprüft.

Farbanimationen und Helligkeit

Globale und LED-spezifische Helligkeit werden beim Laden in die Base-Farbe eingerechnet. COLOR_CYCLE berechnet RGB dagegen direkt mit festen 40 % Helligkeit und ignoriert Base-Farbe sowie Override.

COLOR_FADE aus der Config wird als einmaliger Fade von Schwarz zur gespeicherten Base-Farbe interpretiert.

Reservierte beziehungsweise noch ungenutzte Hardware und Felder

  • Die drei Fader-Pins sind im Variant und in config/pins.h definiert, werden absichtlich noch nicht von der Firmware eingelesen.
  • enc_sensitivity[4] wird gespeichert und mit Default 1 befüllt, beeinflusst die Encoderdekodierung derzeit aber nicht.
  • SET_LED_BASE verändert nur den RAM-Zustand und wird nicht in NVM persistiert.

Zeitverhalten

Makros und Encoder-Taps verwenden blockierende delay()-Aufrufe. Startsignal, Werksreset-Feedback und NVM-Operationen blockieren ebenfalls den Loop. Während dessen werden Matrix und CDC nicht bearbeitet; Encoder-ISRs können weiter Events erzeugen, bis die Queue voll ist.