Add UF2 bootloader for USB firmware flashing
Vendored and trimmed from microsoft/uf2-samdx1, adapted to the actual ATSAMD21G17D (128 KiB flash / 16 KiB RAM), fixing the flash/RAM-size mismatch that the previously commented-out SAM-BA bootloader target had (it assumed a 256 KiB SAMD21G18A). Builds as a standalone PlatformIO environment (bootloader/platformio.ini), no python2/make dependency. Compiles clean, fits in the 8 KiB bootloader region (7292/8192 bytes). Not yet flashed/verified on real hardware.
This commit is contained in:
parent
ce5db617a1
commit
de52b57041
143 changed files with 69119 additions and 0 deletions
92
bootloader/inc/neopixel.h
Normal file
92
bootloader/inc/neopixel.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#ifndef DEVICE_NEOPIXEL_H
|
||||
#define DEVICE_NEOPIXEL_H
|
||||
|
||||
#ifdef BOARD_NEOPIXEL_PIN
|
||||
|
||||
// The timings are taken from Adafruit's NeoPixel library
|
||||
|
||||
static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMask,
|
||||
const uint8_t *ptr, int numBytes) __attribute__((naked));
|
||||
|
||||
static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMask,
|
||||
const uint8_t *ptr, int numBytes) {
|
||||
asm volatile(" push {r4, r5, r6, lr};"
|
||||
" add r3, r2, r3;"
|
||||
"loopLoad:"
|
||||
" ldrb r5, [r2, #0];" // r5 := *ptr
|
||||
" add r2, #1;" // ptr++
|
||||
" movs r4, #128;" // r4-mask, 0x80
|
||||
"loopBit:"
|
||||
" str r1, [r0, #4];" // set
|
||||
#ifdef SAMD21
|
||||
" movs r6, #3; d2: sub r6, #1; bne d2;" // delay 3
|
||||
#endif
|
||||
#ifdef SAMD51
|
||||
" movs r6, #3; d2: subs r6, #1; bne d2;" // delay 3
|
||||
#endif
|
||||
" tst r4, r5;" // mask&r5
|
||||
" bne skipclr;"
|
||||
" str r1, [r0, #0];" // clr
|
||||
"skipclr:"
|
||||
#ifdef SAMD21
|
||||
" movs r6, #6; d0: sub r6, #1; bne d0;" // delay 6
|
||||
#endif
|
||||
#ifdef SAMD51
|
||||
" movs r6, #6; d0: subs r6, #1; bne d0;" // delay 6
|
||||
#endif
|
||||
" str r1, [r0, #0];" // clr (possibly again, doesn't matter)
|
||||
#ifdef SAMD21
|
||||
" asr r4, r4, #1;" // mask >>= 1
|
||||
#endif
|
||||
#ifdef SAMD51
|
||||
" asrs r4, r4, #1;" // mask >>= 1
|
||||
#endif
|
||||
" beq nextbyte;"
|
||||
" uxtb r4, r4;"
|
||||
#ifdef SAMD21
|
||||
" movs r6, #2; d1: sub r6, #1; bne d1;" // delay 2
|
||||
#endif
|
||||
#ifdef SAMD51
|
||||
" movs r6, #2; d1: subs r6, #1; bne d1;" // delay 2
|
||||
#endif
|
||||
" b loopBit;"
|
||||
"nextbyte:"
|
||||
" cmp r2, r3;"
|
||||
" bcs stop;"
|
||||
" b loopLoad;"
|
||||
"stop:"
|
||||
" pop {r4, r5, r6, pc};"
|
||||
"");
|
||||
}
|
||||
|
||||
// this assumes the pin has been configured correctly
|
||||
static inline void neopixel_send_buffer(const uint8_t *ptr, int numBytes) {
|
||||
uint8_t portNum = BOARD_NEOPIXEL_PIN / 32;
|
||||
uint32_t pinMask = 1ul << (BOARD_NEOPIXEL_PIN % 32);
|
||||
|
||||
PINOP(BOARD_NEOPIXEL_PIN, DIRSET);
|
||||
|
||||
#if (USB_VID == 0x239a) && (USB_PID == 0x0013) // Adafruit Metro M0
|
||||
// turn off mux too, needed for metro m0
|
||||
PORT->Group[BOARD_NEOPIXEL_PIN / 32].PINCFG[BOARD_NEOPIXEL_PIN % 32].reg =
|
||||
(uint8_t)(PORT_PINCFG_INEN);
|
||||
#endif
|
||||
|
||||
PINOP(BOARD_NEOPIXEL_PIN, OUTCLR);
|
||||
delay(1);
|
||||
|
||||
volatile uint32_t *clraddr = &PORT->Group[portNum].OUTCLR.reg;
|
||||
|
||||
// equivalent to cpu_irq_is_enabled()
|
||||
if (__get_PRIMASK() == 0) {
|
||||
__disable_irq();
|
||||
neopixel_send_buffer_core(clraddr, pinMask, ptr, numBytes);
|
||||
__enable_irq();
|
||||
} else {
|
||||
neopixel_send_buffer_core(clraddr, pinMask, ptr, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue