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> |
||
|---|---|---|
| boards | ||
| bootloader | ||
| doc | ||
| src | ||
| variants/versapad | ||
| .gitignore | ||
| AGENTS.md | ||
| platformio.ini | ||
| README.md | ||
| upload_openocd.py | ||
VersaMCU
Firmware für das VersaPad-v2-Makropad. Das Projekt läuft auf einem ATSAMD21G17D mit PlatformIO und dem Arduino-SAMD-Framework.
Aktueller Funktionsumfang
| Bereich | Stand |
|---|---|
| Eingaben | 20 MX-Tasten, 4 Encoder-Taster und 4 Quadratur-Encoder |
| USB | Keyboard-HID, Consumer-HID und CDC Serial |
| Aktionen | HID-Key, Consumer-Key, Host-Event, Makro, Profilwechsel |
| Makros | 32 Slots mit je bis zu 8 HID-Schritten |
| Profile | 3 Profile in Config v3 |
| LEDs | 20 WS2812B mit Base-/Override-Farbe und 7 Animationsmodi |
| Persistenz | Config und Makros im internen Flash |
| Recovery | Werksreset über zwei Tasten |
Die drei Fader-Pins sind im Board-Variant definiert, werden von der aktuellen Firmware aber noch nicht eingelesen.
Hardware
| Eigenschaft | Detail |
|---|---|
| MCU | ATSAMD21G17D, Cortex-M0+, 48 MHz |
| Flash / RAM | 128 KiB / 16 KiB |
| Matrix | logisch 5×5: 20 MX, 4 Encoder-SW, 1 unbelegt |
| 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 |
Schnellstart
Voraussetzungen sind PlatformIO Core oder die PlatformIO IDE sowie für den Upload ein angeschlossener Atmel-ICE beziehungsweise kompatibler CMSIS-DAP-Adapter.
pio run -e versapad
pio run -e versapad --target upload
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.
Laufzeitmodell
main.cpp besitzt genau einen CMainController. Nach einem roten Startsignal
initialisiert er NVM, USB, Matrix und Encoder. Die Hauptschleife ist:
matrix_scan()
poll_vendor()
processEvents()
check_factory_reset()
updateLEDs()
- Matrix und Encoder legen
SEvents in eine feste Queue. - Der Controller setzt Events in HID-Aktionen, Makros, Host-Events oder Profilwechsel um.
poll_vendor()verarbeitet feste 8-Byte-Pakete über CDC.- LEDs werden nur neu übertragen, wenn ein Zustand dirty ist oder eine Animation läuft.
- Makros, Encoder-Taps, NVM-Zugriffe und visuelles Reset-Feedback blockieren den Loop kurzzeitig; es gibt keinen Scheduler.
Wichtige Datenverträge
Config v3
- Magic
0x56503203 SDeviceConfig: 740 Byte- CRC16-CCITT über Bytes
7..739 - 3 Profile
- globale und LED-spezifische Helligkeit
- 124 Chunks mit je 6 Nutzbytes beim CDC-Transfer
Makros
SMacroTable: 512 Byte- 32 Slots × 8 Schritte × 2 Byte
- 86 Chunks mit je 6 Nutzbytes beim CDC-Transfer
Flashzugriffe
| Bereich | Adresse | Größe |
|---|---|---|
| Makros | 0x1FB00..0x1FCFF |
512 B |
| Config | 0x1FD00..0x1FFFF |
768 B, davon 740 B genutzt |
Das aktive Linker-Skript und boards/versapad_nobl.json begrenzen das
Firmware-Image auf 0x00000..0x1FAFF. Damit sind alle fünf NVM-Rows gegen
Firmwarewachstum geschützt.
Werksreset
Unteren linken und unteren rechten MX-Button gleichzeitig fünf Sekunden halten:
- die Tasten werden während des Haltens rot markiert,
- ihre normalen Aktionen werden unterdrückt,
- bei Erfolg blinken alle LEDs kurz rot,
- Config und Makrotabelle werden auf Defaults zurückgesetzt.
Ein normaler SWD-Reflash löscht diese NVM-Daten nicht automatisch.
Projektstruktur
VersaMCU/
|-- AGENTS.md # Kontext und Richtlinien für Coding-LLMs
|-- README.md
|-- platformio.ini
|-- boards/ # PlatformIO-Boarddefinitionen
|-- variants/versapad/ # Pinmapping und Linker-Skripte
|-- doc/ # Architektur- und Protokolldokumentation
`-- src/
|-- main.cpp
|-- CMainController.* # Orchestrierung
|-- CButton.* # Actions und LED-Zustand
|-- CEventQueue.* # feste Event-Queue
|-- config/ # Binärformate, NVM und Pins
`-- hal/ # Matrix, Encoder, HID, CDC, WS2812
Einstieg für Entwickler und LLMs
Für einen neuen Kollegen:
- Entwicklung und Einstieg
- Architektur
- die zum Task passende Fachdokumentation im Dokumentationsindex
- bekannte Einschränkungen
Für einen Coding-Agent zusätzlich AGENTS.md als
Repository-Anweisung mitgeben. Die Datei enthält Quellenhierarchie,
Binärverträge, Änderungsregeln und die minimale Verifikation.