How to (safely) set RTC COMP?

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Context: For power savings, I'm putting the SAMD21 into STANDBY mode until an RTC COMP interrupt wakes it back up.  (The RTC is driven from the OSCULP32K.)  The challenge is to make sure that the RTC COMP register is set to be greater than the COUNT register before going so sleep. 

 

Consider this code:

// Assume RTC COMP interrupts have been enabled.
// Set RTC to wake processor in two tics from now.
uint32_t now = hri_rtcmode0_read_COUNT_COUNT_bf(RTC);
hri_rtcmode0_write_COMP_COMP_bf(RTC, 0, now + 2);
sleep(SLEEP_STANDBY_MODE);

The problem is that there's a race condition: if an interrupt occurs between reading `now` and entering sleep mode, the RTC COUNT register might have advanced past the COMP value, so the system will sleep "forever" (or at least for 2^32 RTC tics).  This is only slightly better:

CRITICAL_SECTION_ENTER()
uint32_t now = hri_rtcmode0_read_COUNT_COUNT_bf(RTC);
hri_rtcmode0_write_COMP_COMP_bf(RTC, 0, now + 2);
CRITICAL_SECTION_LEAVE()
sleep(SLEEP_STANDBY_MODE);

...but it still has the same race condition after leaving the critical section and before entering sleep.

 

Of course, RTC interrupts must be enabled before calling sleep, which suggests something like this:

CRITICAL_SECTION_ENTER()
uint32_t now = hri_rtcmode0_read_COUNT_COUNT_bf(RTC);
hri_rtcmode0_write_COMP_COMP_bf(RTC, 0, now + 2);
<enable only RTC COMP interrupts>
sleep(SLEEP_STANDBY_MODE);
CRITICAL_SECTION_LEAVE()

So the questions:

1. Is this the way you'd do it?

2. What's the approved way to <enable only RTC COMP interrupts>?

- rdp

 

Last Edited: Sun. Dec 1, 2019 - 05:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

By the way, the code snippet above has a more serious issue than just race conditions: the now + 2 expression assumes that the processor will enter sleep mode within one or two RTC ticks.  It turns out that's a bad assumption (and I have the scope traces to prove it).

 

With a 1 MHz master clock and a 32KHz RTC clock, that would be about 30 processor cycles.  Without analyzing the disassembled code and doing a timing analysis, it's impossible to know exactly how many cycles elapse between setting RTC COMP and going to sleep.

 

So the original questions stands: how can one safely set RTC COMP so it's guaranteed to be greater than RTC COUNT by the time the processor sleeps?  The comments about race conditions, though still valid, are a bit misleading.

 

- rdp