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