96
96
#endif
97
97
volatile bool hold_interrupt = false;
98
98
#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
+
99
106
void rtc_start_pulsein (void ) {
100
- rtc_set_continuous ();
107
+ rtc_set_continuous (true );
101
108
hold_interrupt = true;
102
109
}
103
110
104
111
void rtc_end_pulsein (void ) {
105
112
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);
112
114
}
113
115
#endif
114
116
@@ -430,19 +432,28 @@ uint32_t port_get_saved_word(void) {
430
432
static volatile uint64_t overflowed_ticks = 0 ;
431
433
static volatile bool _ticks_enabled = false;
432
434
433
- static uint32_t _get_count (void ) {
435
+ static uint32_t _get_count (uint32_t * overflow_count ) {
434
436
#ifdef SAM_D5X_E5X
435
437
while ((RTC -> MODE0 .SYNCBUSY .reg & (RTC_MODE0_SYNCBUSY_COUNTSYNC | RTC_MODE0_SYNCBUSY_COUNT )) != 0 ) {}
436
438
#endif
437
439
#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 ;
438
442
while (RTC -> MODE0 .STATUS .bit .SYNCBUSY != 0 ) {}
439
443
#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 ();
440
451
441
- return RTC -> MODE0 . COUNT . reg ;
452
+ return count ;
442
453
}
443
454
444
455
static void _port_interrupt_after_ticks (uint32_t ticks ) {
445
- uint32_t current_ticks = _get_count ();
456
+ uint32_t current_ticks = _get_count (NULL );
446
457
if (ticks > 1 << 28 ) {
447
458
// We'll interrupt sooner with an overflow.
448
459
return ;
@@ -490,12 +501,13 @@ void RTC_Handler(void) {
490
501
}
491
502
492
503
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 );
494
506
if (subticks != NULL ) {
495
507
* subticks = (current_ticks % 16 ) * 2 ;
496
508
}
497
509
498
- return overflowed_ticks + current_ticks / 16 ;
510
+ return overflow_count + current_ticks / 16 ;
499
511
}
500
512
501
513
// Enable 1/1024 second tick.
@@ -505,6 +517,7 @@ void port_enable_tick(void) {
505
517
RTC -> MODE0 .INTENSET .reg = RTC_MODE0_INTENSET_PER2 ;
506
518
#endif
507
519
#ifdef SAMD21
520
+ // TODO: Switch to using the PER *event* from the RTC to generate an interrupt via EVSYS.
508
521
_ticks_enabled = true;
509
522
_port_interrupt_after_ticks (1 );
510
523
#endif
0 commit comments