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>
56 lines
2.2 KiB
C
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
|