Skip to content

Commit 3ccf644

Browse files
committed
Fix autoreload on SAMD21
The issue was that a time.sleep() would set the RTC wake up further into the future even if we wanted to tick every ms. Ticking every ms is used to time the autoreload delay and without it, autoreload doesn't work. Fixes adafruit#3528
1 parent e1a80ae commit 3ccf644

File tree

1 file changed

+34
-24
lines changed
  • ports/atmel-samd/supervisor

1 file changed

+34
-24
lines changed

ports/atmel-samd/supervisor/port.c

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,33 @@ uint32_t port_get_saved_word(void) {
430430
static volatile uint64_t overflowed_ticks = 0;
431431
static volatile bool _ticks_enabled = false;
432432

433+
static uint32_t _get_count(void) {
434+
#ifdef SAM_D5X_E5X
435+
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT)) != 0) {}
436+
#endif
437+
#ifdef SAMD21
438+
while (RTC->MODE0.STATUS.bit.SYNCBUSY != 0) {}
439+
#endif
440+
441+
return RTC->MODE0.COUNT.reg;
442+
}
443+
444+
static void _port_interrupt_after_ticks(uint32_t ticks) {
445+
uint32_t current_ticks = _get_count();
446+
if (ticks > 1 << 28) {
447+
// We'll interrupt sooner with an overflow.
448+
return;
449+
}
450+
#ifdef SAMD21
451+
if (hold_interrupt) {
452+
return;
453+
}
454+
#endif
455+
RTC->MODE0.COMP[0].reg = current_ticks + (ticks << 4);
456+
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
457+
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0;
458+
}
459+
433460
void RTC_Handler(void) {
434461
uint32_t intflag = RTC->MODE0.INTFLAG.reg;
435462
if (intflag & RTC_MODE0_INTFLAG_OVF) {
@@ -452,7 +479,7 @@ void RTC_Handler(void) {
452479
supervisor_tick();
453480
// Check _ticks_enabled again because a tick handler may have turned it off.
454481
if (_ticks_enabled) {
455-
port_interrupt_after_ticks(1);
482+
_port_interrupt_after_ticks(1);
456483
}
457484
}
458485
#endif
@@ -462,17 +489,6 @@ void RTC_Handler(void) {
462489
}
463490
}
464491

465-
static uint32_t _get_count(void) {
466-
#ifdef SAM_D5X_E5X
467-
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT)) != 0) {}
468-
#endif
469-
#ifdef SAMD21
470-
while (RTC->MODE0.STATUS.bit.SYNCBUSY != 0) {}
471-
#endif
472-
473-
return RTC->MODE0.COUNT.reg;
474-
}
475-
476492
uint64_t port_get_raw_ticks(uint8_t* subticks) {
477493
uint32_t current_ticks = _get_count();
478494
if (subticks != NULL) {
@@ -490,7 +506,7 @@ void port_enable_tick(void) {
490506
#endif
491507
#ifdef SAMD21
492508
_ticks_enabled = true;
493-
port_interrupt_after_ticks(1);
509+
_port_interrupt_after_ticks(1);
494510
#endif
495511
}
496512

@@ -505,20 +521,14 @@ void port_disable_tick(void) {
505521
#endif
506522
}
507523

524+
// This is called by sleep, we ignore it when our ticks are enabled because
525+
// they'll wake us up earlier. If we don't, we'll mess up ticks by overwriting
526+
// the next RTC wake up time.
508527
void port_interrupt_after_ticks(uint32_t ticks) {
509-
uint32_t current_ticks = _get_count();
510-
if (ticks > 1 << 28) {
511-
// We'll interrupt sooner with an overflow.
512-
return;
513-
}
514-
#ifdef SAMD21
515-
if (hold_interrupt) {
528+
if (_ticks_enabled) {
516529
return;
517530
}
518-
#endif
519-
RTC->MODE0.COMP[0].reg = current_ticks + (ticks << 4);
520-
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
521-
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0;
531+
_port_interrupt_after_ticks(ticks);
522532
}
523533

524534
void port_sleep_until_interrupt(void) {

0 commit comments

Comments
 (0)