forked from jappel/VersaMCU
pio run -e versapad --target upload writes the app starting at 0x0000 and silently destroyed the installed UF2 bootloader twice today during testing -- no warning, no error, just a board that stopped responding to the boot-key hold. upload_openocd.py now checks for the bootloader (verify_image against the locally built bootloader/.pio/build/versapad_bootloader/firmware.bin) before an env:versapad upload and refuses if one is present, pointing at env:versapad_usb instead. Fails closed: an inconclusive check (e.g. bootloader not built locally, SWD not responding) blocks rather than proceeding on a guess -- confirmed necessary the hard way, since a "fail open" first attempt let the destructive upload through silently. Scoped to PIOENV == "versapad" only, since bootloader/platformio.ini's own upload reuses this same script and must always be allowed to write 0x0000. A new erase-bootloader-and-flash custom target remains as the explicit, deliberate override. Documented the workflow (bootloader is its own PlatformIO project, flashed once via SWD; versapad_usb is the normal path afterward; versapad's upload is now guarded) in README.md and doc/10_usb_bootloader.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
186 lines
6.5 KiB
Markdown
186 lines
6.5 KiB
Markdown
# 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 |
|
||
| 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.
|
||
|
||
## 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, oder USB über den UF2-Bootloader |
|
||
|
||
## Schnellstart
|
||
|
||
Voraussetzungen sind PlatformIO Core oder die PlatformIO IDE sowie für den
|
||
Upload ein angeschlossener Atmel-ICE beziehungsweise kompatibler
|
||
CMSIS-DAP-Adapter.
|
||
|
||
```bash
|
||
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.
|
||
|
||
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
|
||
```
|
||
|
||
`bootloader/` ist ein eigenständiges PlatformIO-Projekt (eigene
|
||
`platformio.ini`, kein Arduino-Framework). Für die PlatformIO-IDE-Buttons in
|
||
VS Code müsste der Ordner separat als eigener Workspace geöffnet werden; über
|
||
die Kommandozeile reicht `cd bootloader && pio run ...` im selben Fenster.
|
||
|
||
Sobald der Bootloader installiert ist, **verweigert `versapad --target
|
||
upload` den normalen Upload** — dieser Weg schreibt ab `0x0000` und würde den
|
||
Bootloader sonst kommentarlos überschreiben (`upload_openocd.py` prüft das
|
||
vorher automatisch). Bauen und Debuggen über `versapad` bleiben uneingeschränkt
|
||
möglich, nur der Upload ist betroffen. Für App-Updates danach `versapad_usb`
|
||
verwenden; bewusst zurück zu reinem SWD-Betrieb geht über
|
||
`pio run -e versapad -t erase-bootloader-and-flash`.
|
||
|
||
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
|
||
|
||
`main.cpp` besitzt genau einen `CMainController`. Nach einem roten Startsignal
|
||
initialisiert er NVM, USB, Matrix und Encoder. Die Hauptschleife ist:
|
||
|
||
```text
|
||
matrix_scan()
|
||
poll_vendor()
|
||
processEvents()
|
||
check_factory_reset()
|
||
updateLEDs()
|
||
```
|
||
|
||
- Matrix und Encoder legen `SEvent`s 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
|
||
|
||
```text
|
||
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
|
||
|-- 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:
|
||
|
||
1. [Entwicklung und Einstieg](doc/08_development.md)
|
||
2. [Architektur](doc/00_architecture.md)
|
||
3. die zum Task passende Fachdokumentation im [Dokumentationsindex](doc/INDEX.md)
|
||
4. [bekannte Einschränkungen](doc/09_known_limitations.md)
|
||
|
||
Für einen Coding-Agent zusätzlich [`AGENTS.md`](AGENTS.md) als
|
||
Repository-Anweisung mitgeben. Die Datei enthält Quellenhierarchie,
|
||
Binärverträge, Änderungsregeln und die minimale Verifikation.
|
||
|
||
## Dokumentation
|
||
|
||
- [Dokumentationsindex](doc/INDEX.md)
|
||
- [Architektur](doc/00_architecture.md)
|
||
- [Matrix](doc/01_matrix.md)
|
||
- [Encoder](doc/02_encoder.md)
|
||
- [Action-Engine](doc/03_action_engine.md)
|
||
- [Makros](doc/04_macro_system.md)
|
||
- [LED-System](doc/05_led_system.md)
|
||
- [NVM-Config](doc/06_nvm_config.md)
|
||
- [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)
|