address review comments; avoid affecting double-click
This commit is contained in:
parent
a346c82e2d
commit
291610433b
5 changed files with 56 additions and 22 deletions
|
|
@ -290,6 +290,12 @@ void delay(uint32_t ms);
|
||||||
void hidHandoverLoop(int ep);
|
void hidHandoverLoop(int ep);
|
||||||
void handoverPrep(void);
|
void handoverPrep(void);
|
||||||
|
|
||||||
|
// Useful for debugging.
|
||||||
|
#ifdef BLINK_DEBUG
|
||||||
|
void blink_n(uint32_t pin, uint32_t n, uint32_t interval);
|
||||||
|
void blink_n_forever(uint32_t pin, uint32_t n, uint32_t interval);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CONCAT_1(a, b) a##b
|
#define CONCAT_1(a, b) a##b
|
||||||
#define CONCAT_0(a, b) CONCAT_1(a, b)
|
#define CONCAT_0(a, b) CONCAT_1(a, b)
|
||||||
#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }
|
#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
volatile bool g_interrupt_enabled = true;
|
volatile bool g_interrupt_enabled = true;
|
||||||
|
|
||||||
// SAMD51 starts at 1MHz by default.
|
// SAMD21 starts at 1MHz by default.
|
||||||
uint32_t current_cpu_frequency_MHz = 1;
|
uint32_t current_cpu_frequency_MHz = 1;
|
||||||
|
|
||||||
static void gclk_sync(void) {
|
static void gclk_sync(void) {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,8 @@ void system_init(void) {
|
||||||
MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV_DIV1;
|
MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV_DIV1;
|
||||||
|
|
||||||
SysTick_Config(1000);
|
SysTick_Config(1000);
|
||||||
current_cpu_frequency_MHz = 48;
|
// No change from initial frequency.
|
||||||
|
// current_cpu_frequency_MHz = 48;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysTick_Handler(void) { LED_TICK(); }
|
void SysTick_Handler(void) { LED_TICK(); }
|
||||||
|
|
|
||||||
24
src/main.c
24
src/main.c
|
|
@ -29,11 +29,11 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* --------------------
|
* --------------------
|
||||||
* SAM-BA Implementation on SAMD21
|
* SAM-BA Implementation on SAMD21 and SAMD51
|
||||||
* --------------------
|
* --------------------
|
||||||
* Requirements to use SAM-BA :
|
* Requirements to use SAM-BA :
|
||||||
*
|
*
|
||||||
* Supported communication interfaces :
|
* Supported communication interfaces (SAMD21):
|
||||||
* --------------------
|
* --------------------
|
||||||
*
|
*
|
||||||
* SERCOM5 : RX:PB23 TX:PB22
|
* SERCOM5 : RX:PB23 TX:PB22
|
||||||
|
|
@ -68,8 +68,6 @@
|
||||||
*
|
*
|
||||||
* Applications compiled to be executed along with the bootloader will start at
|
* Applications compiled to be executed along with the bootloader will start at
|
||||||
* 0x2000 (samd21) or 0x4000 (samd51)
|
* 0x2000 (samd21) or 0x4000 (samd51)
|
||||||
* The bootloader doesn't changes the VTOR register, application code is
|
|
||||||
* taking care of this.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -110,7 +108,7 @@ static void check_start_application(void) {
|
||||||
if (RESET_CONTROLLER->RCAUSE.bit.POR || *DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
|
if (RESET_CONTROLLER->RCAUSE.bit.POR || *DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
|
||||||
// the second tap on reset will go into app
|
// the second tap on reset will go into app
|
||||||
*DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT;
|
*DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT;
|
||||||
// this will be cleared after succesful USB enumeration
|
// this will be cleared after successful USB enumeration
|
||||||
// this is around 1.5s
|
// this is around 1.5s
|
||||||
resetHorizon = timerHigh + 50;
|
resetHorizon = timerHigh + 50;
|
||||||
return;
|
return;
|
||||||
|
|
@ -150,7 +148,7 @@ extern char _etext;
|
||||||
extern char _end;
|
extern char _end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SAMD21 SAM-BA Main loop.
|
* \brief SAM-BA Main loop.
|
||||||
* \return Unused (ANSI-C compatibility).
|
* \return Unused (ANSI-C compatibility).
|
||||||
*/
|
*/
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|
@ -181,8 +179,17 @@ int main(void) {
|
||||||
while (SUPC->STATUS.bit.BOD33DET) {
|
while (SUPC->STATUS.bit.BOD33DET) {
|
||||||
// Wait for voltage to rise above BOD33 value.
|
// Wait for voltage to rise above BOD33 value.
|
||||||
}
|
}
|
||||||
// Wait 100ms for voltage to stabilize.
|
|
||||||
delay(100);
|
// If we are starting from a power-on or a brownout,
|
||||||
|
// wait for the voltage to stabilize. Don't do this on an
|
||||||
|
// external reset because it interferes with the timing of double-click.
|
||||||
|
// "BODVDD" means BOD33.
|
||||||
|
if (RSTC->RCAUSE.bit.POR || RSTC->RCAUSE.bit.BODVDD) {
|
||||||
|
do {
|
||||||
|
// Check again in 100ms.
|
||||||
|
delay(100);
|
||||||
|
} while (SUPC->STATUS.bit.BOD33DET);
|
||||||
|
}
|
||||||
|
|
||||||
// Now enable reset if voltage falls below minimum.
|
// Now enable reset if voltage falls below minimum.
|
||||||
SUPC->BOD33.bit.ENABLE = 0;
|
SUPC->BOD33.bit.ENABLE = 0;
|
||||||
|
|
@ -190,7 +197,6 @@ int main(void) {
|
||||||
SUPC->BOD33.bit.ENABLE = 1;
|
SUPC->BOD33.bit.ENABLE = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if USB_VID == 0x239a && USB_PID == 0x0013 // Adafruit Metro M0
|
#if USB_VID == 0x239a && USB_PID == 0x0013 // Adafruit Metro M0
|
||||||
// Delay a bit so SWD programmer can have time to attach.
|
// Delay a bit so SWD programmer can have time to attach.
|
||||||
delay(15);
|
delay(15);
|
||||||
|
|
|
||||||
43
src/utils.c
43
src/utils.c
|
|
@ -4,27 +4,48 @@
|
||||||
static uint32_t timerLow;
|
static uint32_t timerLow;
|
||||||
uint32_t timerHigh, resetHorizon;
|
uint32_t timerHigh, resetHorizon;
|
||||||
|
|
||||||
void delay(uint32_t ms) {
|
void __attribute__ ((noinline)) delay(uint32_t ms) {
|
||||||
// These multipliers were determined empirically and are only approximate.
|
// These multipliers were determined empirically and are only approximate.
|
||||||
// SAMD21 starts up at 1MHz by default.
|
// After the pulsing LED is enabled (led_tick_on), the multipliers need to change
|
||||||
|
// due to the interrupt overhead of the pulsing.
|
||||||
|
// SAMD21 starts up at 1MHz by default.
|
||||||
#ifdef SAMD21
|
#ifdef SAMD21
|
||||||
uint32_t count = ms * 167 * (current_cpu_frequency_MHz);
|
uint32_t count = ms * (current_cpu_frequency_MHz) * (led_tick_on ? 149: 167);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SAMD51
|
#ifdef SAMD51
|
||||||
// SAMD51 starts up at 48MHz by default, and we set the clock to
|
// SAMD51 starts up at 48MHz by default, and we set the clock to
|
||||||
// 48MHz, so we don't need to adjust for current_cpu_frequency_MHz.
|
// 48MHz, so we don't need to adjust for current_cpu_frequency_MHz.
|
||||||
uint32_t count = ms * 6000;
|
uint32_t count = ms * (led_tick_on ? 6353 : 6826);
|
||||||
// On SAMD51, before the 1ms SysTick interrupts are set up, the
|
|
||||||
// timing loop will run about twice as fast, so double the count.
|
|
||||||
if (led_tick_on) {
|
|
||||||
count *= 2;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
for (int i = 1; i < count; ++i) {
|
for (uint32_t i = 1; i < count; ++i) {
|
||||||
asm volatile("");
|
asm volatile("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Useful for debugging.
|
||||||
|
// PIN_PA19 is D12 on Metro M0, D11 on Metro M4
|
||||||
|
#ifdef BLINK_DEBUG
|
||||||
|
void blink_n(uint32_t pin, uint32_t n, uint32_t interval) {
|
||||||
|
// Start out off.
|
||||||
|
PINOP(pin, DIRSET);
|
||||||
|
PINOP(pin, OUTCLR);
|
||||||
|
delay(interval);
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
PINOP(pin, OUTSET);
|
||||||
|
delay(interval);
|
||||||
|
PINOP(pin, OUTCLR);
|
||||||
|
delay(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blink_n_forever(uint32_t pin, uint32_t n, uint32_t interval) {
|
||||||
|
while(1) {
|
||||||
|
blink_n(pin, n, interval);
|
||||||
|
delay(interval*5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void timerTick(void) {
|
void timerTick(void) {
|
||||||
if (timerLow-- == 0) {
|
if (timerLow-- == 0) {
|
||||||
timerLow = TIMER_STEP;
|
timerLow = TIMER_STEP;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue