Skip to content

Commit 379e73a

Browse files
committed
Finer grained, per port tick locking
Fixes micropython#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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy