VersaMCU/bootloader/include/board_config.h
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

56 lines
2.2 KiB
C

/*
* Board config for the VersaPad v2 UF2 bootloader.
* Adapted from Microsoft uf2-samdx1 boards/gemma_m0/board_config.h
* (closest upstream template: crystalless ATSAMD21, same USB_VID).
*/
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define CRYSTALLESS 1
#define VENDOR_NAME "Custom"
#define PRODUCT_NAME "VersaPad v2"
#define VOLUME_LABEL "VERSABOOT"
#define INDEX_URL "https://git.jappel.io/jappel/VersaMCU"
#define BOARD_ID "SAMD21G17D-VersaPad-v2"
/* Same VID as the app firmware (platformio.ini), distinct PID so the
* bootloader enumerates as a different USB device than the app.
*
* NOT 0x0011: that's Adafruit's own Gemma M0 bootloader PID (this file's
* upstream template), and Windows machines with an Adafruit driver already
* installed silently bind it as a "Adafruit Circuit Playground" COM port
* instead of exposing the VERSABOOT mass-storage volume. Confirmed on real
* hardware 2026-08-05. 0x0043 is app PID (0x0042) + 1, not a known
* third-party assignment. */
#define USB_VID 0x239A
#define USB_PID 0x0043
/* No plain GPIO status LED on this board, only a WS2812 chain on PB22.
* The bootloader's LED_PIN code just toggles a digital output, that would
* not drive WS2812 correctly, so leave it undefined for now. */
//#define LED_PIN
//#define LED_TX_PIN
//#define LED_RX_PIN
//#define BOARD_RGBLED_CLOCK_PIN
//#define BOARD_RGBLED_DATA_PIN
/* Hardware bootloader entry, no dedicated reset/boot button on this PCB.
* Reuses the bottom-right Cherry MX key (key_id 24 in the app firmware,
* see src/config/pins.h) as a boot-hold key: held while the board resets
* or powers up -> stay in the bootloader. Checked in check_start_application()
* before the app is even validated, so it works regardless of app firmware
* state.
*
* Pin numbers are PORT-flat (group*32 + pin), matching PINOP()/PINCFG() in
* uf2.h: PA15 = 15, PA08 = 8.
*
* Matrix wiring (src/config/pins.h, src/hal/matrix.cpp): key_id 24 = COL4 x
* ROW4. COL4 has an external 10k pull-up to 3V3 (idle HIGH); ROW4 is driven
* LOW during the check, matching the app's own scan polarity.
*/
#define BOOT_KEY_ROW_PIN 15 // PA15 -- ROW4, driven LOW during the check
#define BOOT_KEY_COL_PIN 8 // PA08 -- COL4, read back; LOW = key pressed
#endif