No description
Find a file
Julian Appel 6c71f5f057 Document an OpenOCD ELF-flash pitfall found during hardware debugging
While chasing why the boot-key check stopped working, traced it to
openocd's "program <elf> verify" silently writing raw file bytes
starting at flash 0x0 instead of the ELF's own section addresses,
whenever combined with a prior bootloader write in the same OpenOCD
invocation -- repeatedly clobbering the just-flashed bootloader with
the app's ELF header. Recovered via full chip-erase and reflashing
bootloader and app as separate .bin writes with explicit addresses in
isolated OpenOCD sessions; both regions verified correct afterward and
confirmed working on hardware (key-hold entry and normal app boot).

Documented the pitfall and the safe manual-flashing rule so it doesn't
get rediscovered the expensive way again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 22:20:23 +02:00
boards Add end-to-end USB flashing for the app firmware via UF2 2026-08-05 21:35:19 +02:00
bootloader Document an OpenOCD ELF-flash pitfall found during hardware debugging 2026-08-05 22:20:23 +02:00
doc Add end-to-end USB flashing for the app firmware via UF2 2026-08-05 21:35:19 +02:00
src Harden firmware state and transfer handling 2026-07-24 09:49:21 +02:00
variants/versapad Fix bootloader hardware bring-up and add key-based boot entry 2026-08-05 21:28:15 +02:00
.gitignore Add end-to-end USB flashing for the app firmware via UF2 2026-08-05 21:35:19 +02:00
AGENTS.md Harden firmware state and transfer handling 2026-07-24 09:49:21 +02:00
platformio.ini Add end-to-end USB flashing for the app firmware via UF2 2026-08-05 21:35:19 +02:00
README.md Harden firmware state and transfer handling 2026-07-24 09:49:21 +02:00
uf2conv.py Add end-to-end USB flashing for the app firmware via UF2 2026-08-05 21:35:19 +02:00
upload_openocd.py Initial commit 2026-03-29 14:47:13 +02:00
upload_uf2.py Add end-to-end USB flashing for the app firmware via UF2 2026-08-05 21:35:19 +02:00

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:

  1. Entwicklung und Einstieg
  2. Architektur
  3. die zum Task passende Fachdokumentation im Dokumentationsindex
  4. 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.

Dokumentation