9696#endif
9797volatile bool hold_interrupt = false;
9898#ifdef SAMD21
99+ static void rtc_set_continuous (bool continuous ) {
100+ while (RTC -> MODE0 .STATUS .bit .SYNCBUSY );
101+ RTC -> MODE0 .READREQ .reg = (continuous ? RTC_READREQ_RCONT : 0 ) | 0x0010 ;
102+ while (RTC -> MODE0 .STATUS .bit .SYNCBUSY );
103+ }
104+
99105void rtc_start_pulsein (void ) {
100- rtc_set_continuous ();
106+ rtc_set_continuous (true );
101107 hold_interrupt = true;
102108}
103109
104110void rtc_end_pulsein (void ) {
105111 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 );
112+ rtc_set_continuous (false);
112113}
113114#endif
114115
@@ -430,19 +431,28 @@ uint32_t port_get_saved_word(void) {
430431static volatile uint64_t overflowed_ticks = 0 ;
431432static volatile bool _ticks_enabled = false;
432433
433- static uint32_t _get_count (void ) {
434+ static uint32_t _get_count (uint32_t * overflow_count ) {
434435 #ifdef SAM_D5X_E5X
435436 while ((RTC -> MODE0 .SYNCBUSY .reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT )) != 0 ) {}
436437 #endif
437438 #ifdef SAMD21
439+ // Request a read so we don't stall the bus later. See section 14.3.1.5 Read Request
440+ RTC -> MODE0 .READREQ .reg = RTC_READREQ_RREQ | 0x0010 ;
438441 while (RTC -> MODE0 .STATUS .bit .SYNCBUSY != 0 ) {}
439442 #endif
443+ // Disable interrupts so we can grab the count and the overflow.
444+ common_hal_mcu_disable_interrupts ();
445+ uint32_t count = RTC -> MODE0 .COUNT .reg ;
446+ if (overflow_count != NULL ) {
447+ * overflow_count = overflowed_ticks ;
448+ }
449+ common_hal_mcu_enable_interrupts ();
440450
441- return RTC -> MODE0 . COUNT . reg ;
451+ return count ;
442452}
443453
444454static void _port_interrupt_after_ticks (uint32_t ticks ) {
445- uint32_t current_ticks = _get_count ();
455+ uint32_t current_ticks = _get_count (NULL );
446456 if (ticks > 1 << 28 ) {
447457 // We'll interrupt sooner with an overflow.
448458 return ;
@@ -490,12 +500,13 @@ void RTC_Handler(void) {
490500}
491501
492502uint64_t port_get_raw_ticks (uint8_t * subticks ) {
493- uint32_t current_ticks = _get_count ();
503+ uint32_t overflow_count ;
504+ uint32_t current_ticks = _get_count (& overflow_count );
494505 if (subticks != NULL ) {
495506 * subticks = (current_ticks % 16 ) * 2 ;
496507 }
497508
498- return overflowed_ticks + current_ticks / 16 ;
509+ return overflow_count + current_ticks / 16 ;
499510}
500511
501512// Enable 1/1024 second tick.
@@ -505,6 +516,7 @@ void port_enable_tick(void) {
505516 RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_PER2 ;
506517 #endif
507518 #ifdef SAMD21
519+ // TODO: Switch to using the PER *event* from the RTC to generate an interrupt via EVSYS.
508520 _ticks_enabled = true;
509521 _port_interrupt_after_ticks (1 );
510522 #endif
0 commit comments