Skip to content

Commit 379e73a

Browse files
committed
Finer grained, per port tick locking
Fixes #3504 hopefully.
1 parent 9de9678 commit 379e73a

File tree

5 files changed

+35
-17
lines changed

5 files changed

+35
-17
lines changed

ports/atmel-samd/common-hal/pulseio/PulseIn.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ void pulsein_reset(void);
5151
void pulsein_interrupt_handler(uint8_t channel);
5252
void pulsein_timer_interrupt_handler(uint8_t index);
5353
#ifdef SAMD21
54-
void rtc_set_continuous(void);
5554
void rtc_start_pulsein(void);
5655
void rtc_end_pulsein(void);
5756
#endif

ports/atmel-samd/supervisor/port.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,21 @@
9696
#endif
9797
volatile bool hold_interrupt = false;
9898
#ifdef SAMD21
99+
static void rtc_set_continuous(bool continuous) {
100+
while (RTC->MODE0.STATUS.bit.SYNCBUSY);
101+
// TODO: DaveP: Do we need the RREQ here?
102+
RTC->MODE0.READREQ.reg = RTC_READREQ_RREQ | (continuous ? RTC_READREQ_RCONT : 0) | 0x0010;
103+
while (RTC->MODE0.STATUS.bit.SYNCBUSY);
104+
}
105+
99106
void rtc_start_pulsein(void) {
100-
rtc_set_continuous();
107+
rtc_set_continuous(true);
101108
hold_interrupt = true;
102109
}
103110

104111
void rtc_end_pulsein(void) {
105112
hold_interrupt = false;
106-
}
107-
108-
void rtc_set_continuous(void) {
109-
while (RTC->MODE0.STATUS.bit.SYNCBUSY);
110-
RTC->MODE0.READREQ.reg = RTC_READREQ_RREQ | RTC_READREQ_RCONT | 0x0010;
111-
while (RTC->MODE0.STATUS.bit.SYNCBUSY);
113+
rtc_set_continuous(false);
112114
}
113115
#endif
114116

@@ -430,19 +432,28 @@ uint32_t port_get_saved_word(void) {
430432
static volatile uint64_t overflowed_ticks = 0;
431433
static volatile bool _ticks_enabled = false;
432434

433-
static uint32_t _get_count(void) {
435+
static uint32_t _get_count(uint32_t* overflow_count) {
434436
#ifdef SAM_D5X_E5X
435437
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT)) != 0) {}
436438
#endif
437439
#ifdef SAMD21
440+
// Request a read so we don't stall the bus later. See section 14.3.1.5 Read Request
441+
RTC->MODE0.READREQ.reg = RTC_READREQ_RREQ | 0x0010;
438442
while (RTC->MODE0.STATUS.bit.SYNCBUSY != 0) {}
439443
#endif
444+
// Disable interrupts so we can grab the count and the overflow.
445+
common_hal_mcu_disable_interrupts();
446+
uint32_t count = RTC->MODE0.COUNT.reg;
447+
if (overflow_count != NULL) {
448+
*overflow_count = overflowed_ticks;
449+
}
450+
common_hal_mcu_enable_interrupts();
440451

441-
return RTC->MODE0.COUNT.reg;
452+
return count;
442453
}
443454

444455
static void _port_interrupt_after_ticks(uint32_t ticks) {
445-
uint32_t current_ticks = _get_count();
456+
uint32_t current_ticks = _get_count(NULL);
446457
if (ticks > 1 << 28) {
447458
// We'll interrupt sooner with an overflow.
448459
return;
@@ -490,12 +501,13 @@ void RTC_Handler(void) {
490501
}
491502

492503
uint64_t port_get_raw_ticks(uint8_t* subticks) {
493-
uint32_t current_ticks = _get_count();
504+
uint32_t overflow_count;
505+
uint32_t current_ticks = _get_count(&overflow_count);
494506
if (subticks != NULL) {
495507
*subticks = (current_ticks % 16) * 2;
496508
}
497509

498-
return overflowed_ticks + current_ticks / 16;
510+
return overflow_count + current_ticks / 16;
499511
}
500512

501513
// Enable 1/1024 second tick.
@@ -505,6 +517,7 @@ void port_enable_tick(void) {
505517
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_PER2;
506518
#endif
507519
#ifdef SAMD21
520+
// TODO: Switch to using the PER *event* from the RTC to generate an interrupt via EVSYS.
508521
_ticks_enabled = true;
509522
_port_interrupt_after_ticks(1);
510523
#endif

ports/litex/supervisor/port.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ uint32_t port_get_saved_word(void) {
128128
}
129129

130130
uint64_t port_get_raw_ticks(uint8_t* subticks) {
131-
return raw_ticks;
131+
// Reading 64 bits may take two loads, so turn of interrupts while we do it.
132+
irq_setie(false);
133+
uint64_t raw_tick_snapshot = raw_ticks;
134+
irq_setie(true);
135+
return raw_tick_snapshot;
132136
}
133137

134138
// Enable 1/1024 second tick.

ports/nrf/supervisor/port.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,15 @@ uint32_t port_get_saved_word(void) {
274274
}
275275

276276
uint64_t port_get_raw_ticks(uint8_t* subticks) {
277+
common_hal_mcu_disable_interrupts();
277278
uint32_t rtc = nrfx_rtc_counter_get(&rtc_instance);
279+
uint32_t overflow_count = overflow_tracker.overflowed_ticks;
280+
common_hal_mcu_enable_interrupts();
281+
278282
if (subticks != NULL) {
279283
*subticks = (rtc % 32);
280284
}
281-
return overflow_tracker.overflowed_ticks + rtc / 32;
285+
return overflow_count + rtc / 32;
282286
}
283287

284288
// Enable 1/1024 second tick.

supervisor/shared/tick.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,7 @@ void supervisor_tick(void) {
125125

126126
uint64_t supervisor_ticks_ms64() {
127127
uint64_t result;
128-
common_hal_mcu_disable_interrupts();
129128
result = port_get_raw_ticks(NULL);
130-
common_hal_mcu_enable_interrupts();
131129
result = result * 1000 / 1024;
132130
return result;
133131
}

0 commit comments

Comments
 (0)