summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorScott Shawcroft <scott@adafruit.com>2020-10-13 13:39:32 -0700
committerGitHub <noreply@github.com>2020-10-13 13:39:32 -0700
commit3d21eec3cdb48710e6826af2643f350294d4d68a (patch)
treeb2053a03e71ab84d24f72359bc28f633195b4280 /ports
parenta010dc35fa90effdb28fa61adfb652c80ceadcfc (diff)
parent2bc40bcadf36d27d2807ac155f185e6cc55e9ecb (diff)
Merge pull request #3546 from tannewt/rtc_irq
Finer grained, per port tick locking
Diffstat (limited to 'ports')
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseIn.h1
-rw-r--r--ports/atmel-samd/supervisor/port.c36
-rw-r--r--ports/litex/supervisor/port.c6
-rw-r--r--ports/nrf/supervisor/port.c6
4 files changed, 34 insertions, 15 deletions
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.h b/ports/atmel-samd/common-hal/pulseio/PulseIn.h
index 99358178f..b91bbd703 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseIn.h
+++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.h
@@ -51,7 +51,6 @@ void pulsein_reset(void);
void pulsein_interrupt_handler(uint8_t channel);
void pulsein_timer_interrupt_handler(uint8_t index);
#ifdef SAMD21
-void rtc_set_continuous(void);
void rtc_start_pulsein(void);
void rtc_end_pulsein(void);
#endif
diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c
index e69062296..d65d09825 100644
--- a/ports/atmel-samd/supervisor/port.c
+++ b/ports/atmel-samd/supervisor/port.c
@@ -96,19 +96,20 @@
#endif
volatile bool hold_interrupt = false;
#ifdef SAMD21
+static void rtc_set_continuous(bool continuous) {
+ while (RTC->MODE0.STATUS.bit.SYNCBUSY);
+ RTC->MODE0.READREQ.reg = (continuous ? RTC_READREQ_RCONT : 0) | 0x0010;
+ while (RTC->MODE0.STATUS.bit.SYNCBUSY);
+}
+
void rtc_start_pulsein(void) {
- rtc_set_continuous();
+ rtc_set_continuous(true);
hold_interrupt = true;
}
void rtc_end_pulsein(void) {
hold_interrupt = false;
-}
-
-void rtc_set_continuous(void) {
- while (RTC->MODE0.STATUS.bit.SYNCBUSY);
- RTC->MODE0.READREQ.reg = RTC_READREQ_RREQ | RTC_READREQ_RCONT | 0x0010;
- while (RTC->MODE0.STATUS.bit.SYNCBUSY);
+ rtc_set_continuous(false);
}
#endif
@@ -430,19 +431,28 @@ uint32_t port_get_saved_word(void) {
static volatile uint64_t overflowed_ticks = 0;
static volatile bool _ticks_enabled = false;
-static uint32_t _get_count(void) {
+static uint32_t _get_count(uint32_t* overflow_count) {
#ifdef SAM_D5X_E5X
while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT)) != 0) {}
#endif
#ifdef SAMD21
+ // Request a read so we don't stall the bus later. See section 14.3.1.5 Read Request
+ RTC->MODE0.READREQ.reg = RTC_READREQ_RREQ | 0x0010;
while (RTC->MODE0.STATUS.bit.SYNCBUSY != 0) {}
#endif
+ // Disable interrupts so we can grab the count and the overflow.
+ common_hal_mcu_disable_interrupts();
+ uint32_t count = RTC->MODE0.COUNT.reg;
+ if (overflow_count != NULL) {
+ *overflow_count = overflowed_ticks;
+ }
+ common_hal_mcu_enable_interrupts();
- return RTC->MODE0.COUNT.reg;
+ return count;
}
static void _port_interrupt_after_ticks(uint32_t ticks) {
- uint32_t current_ticks = _get_count();
+ uint32_t current_ticks = _get_count(NULL);
if (ticks > 1 << 28) {
// We'll interrupt sooner with an overflow.
return;
@@ -490,12 +500,13 @@ void RTC_Handler(void) {
}
uint64_t port_get_raw_ticks(uint8_t* subticks) {
- uint32_t current_ticks = _get_count();
+ uint32_t overflow_count;
+ uint32_t current_ticks = _get_count(&overflow_count);
if (subticks != NULL) {
*subticks = (current_ticks % 16) * 2;
}
- return overflowed_ticks + current_ticks / 16;
+ return overflow_count + current_ticks / 16;
}
// Enable 1/1024 second tick.
@@ -505,6 +516,7 @@ void port_enable_tick(void) {
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_PER2;
#endif
#ifdef SAMD21
+ // TODO: Switch to using the PER *event* from the RTC to generate an interrupt via EVSYS.
_ticks_enabled = true;
_port_interrupt_after_ticks(1);
#endif
diff --git a/ports/litex/supervisor/port.c b/ports/litex/supervisor/port.c
index e55eb49f0..02617b9af 100644
--- a/ports/litex/supervisor/port.c
+++ b/ports/litex/supervisor/port.c
@@ -128,7 +128,11 @@ uint32_t port_get_saved_word(void) {
}
uint64_t port_get_raw_ticks(uint8_t* subticks) {
- return raw_ticks;
+ // Reading 64 bits may take two loads, so turn of interrupts while we do it.
+ irq_setie(false);
+ uint64_t raw_tick_snapshot = raw_ticks;
+ irq_setie(true);
+ return raw_tick_snapshot;
}
// Enable 1/1024 second tick.
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index bc8b47be7..493de43e0 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -274,11 +274,15 @@ uint32_t port_get_saved_word(void) {
}
uint64_t port_get_raw_ticks(uint8_t* subticks) {
+ common_hal_mcu_disable_interrupts();
uint32_t rtc = nrfx_rtc_counter_get(&rtc_instance);
+ uint32_t overflow_count = overflow_tracker.overflowed_ticks;
+ common_hal_mcu_enable_interrupts();
+
if (subticks != NULL) {
*subticks = (rtc % 32);
}
- return overflow_tracker.overflowed_ticks + rtc / 32;
+ return overflow_count + rtc / 32;
}
// Enable 1/1024 second tick.