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+ // 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+
99106void rtc_start_pulsein (void ) {
100- rtc_set_continuous ();
107+ rtc_set_continuous (true );
101108 hold_interrupt = true;
102109}
103110
104111void 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) {
430432static volatile uint64_t overflowed_ticks = 0 ;
431433static 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
444455static 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
492503uint64_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
0 commit comments