drivers: nrf_rtc_timer: Fix handling of COMPARE events in set_alarm()
This is a follow-up to commitscf871aec64
and205e684958
. It turns out that the current implementation of the nrf_rtc_timer may still fail to properly handle a timeout if that timeout is set in very specific conditions - when a previously set timeout is about to expire. When that happens, the new timeout is handled 512 seconds later (when the system timer overflows) than it should be. A recently added nrf_rtc_timer test case (test_tight_rescheduling) exposes this problem and this commit fixes it by adding examination of COMPARE events that appear during setting of the CC register value for a given timeout. Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
parent
d6ba49e298
commit
31c11a5dc0
1 changed files with 21 additions and 6 deletions
|
@ -280,13 +280,28 @@ static void set_alarm(int32_t chan, uint32_t req_cc)
|
|||
* Increase the CC value by a larger number of cycles in each
|
||||
* trial to avoid spending too much time in this loop if it
|
||||
* continuously gets interrupted and delayed by something.
|
||||
* But if the COMPARE event turns out to be already generated,
|
||||
* there is obviously no need to continue the loop.
|
||||
*/
|
||||
if ((counter_sub(cc_val, now + MIN_CYCLES_FROM_NOW) >
|
||||
(COUNTER_HALF_SPAN - MIN_CYCLES_FROM_NOW))
|
||||
&&
|
||||
!event_check(chan)) {
|
||||
if (counter_sub(cc_val, now + MIN_CYCLES_FROM_NOW) >
|
||||
(COUNTER_HALF_SPAN - MIN_CYCLES_FROM_NOW)) {
|
||||
/* If the COMPARE event turns out to be already
|
||||
* generated, check if the loop can be finished.
|
||||
*/
|
||||
if (event_check(chan)) {
|
||||
/* If the current counter value has not yet
|
||||
* reached the requested CC value, the event
|
||||
* must come from the previously set CC value
|
||||
* (the alarm is apparently rescheduled).
|
||||
* The event needs to be cleared then and the
|
||||
* loop needs to be continued.
|
||||
*/
|
||||
now = counter();
|
||||
if (counter_sub(now, req_cc) > COUNTER_HALF_SPAN) {
|
||||
event_clear(chan);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cc_val = now + cc_inc;
|
||||
cc_inc++;
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue