drivers: timer: nrf_rtc_timer: fix lost ticks from unannounced elapsed
The original code assumed that limiting the tick count to the maximum cycle value representable without wrapping would guarantee that adding the resulting cycle offset to last_count would not lap the counter. This is not true when elapsed time, which is also added to the cycle offset, exceeds one tick. Cap the maximum offset at the number of cycles corresponding to the maximum number of ticks without wrapping. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
parent
bb40f9b0cd
commit
4592ac8ca4
1 changed files with 12 additions and 1 deletions
|
@ -19,6 +19,7 @@
|
|||
#define CYC_PER_TICK (sys_clock_hw_cycles_per_sec() \
|
||||
/ CONFIG_SYS_CLOCK_TICKS_PER_SEC)
|
||||
#define MAX_TICKS ((COUNTER_MAX - CYC_PER_TICK) / CYC_PER_TICK)
|
||||
#define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK)
|
||||
|
||||
static struct k_spinlock lock;
|
||||
|
||||
|
@ -121,10 +122,20 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
|
|||
u32_t cyc, dt, t = counter();
|
||||
bool zli_fixup = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS);
|
||||
|
||||
/* Round up to next tick boundary */
|
||||
/* Get the cycles from last_count to the tick boundary after
|
||||
* the requested ticks have passed starting now.
|
||||
*/
|
||||
cyc = ticks * CYC_PER_TICK + 1 + counter_sub(t, last_count);
|
||||
cyc += (CYC_PER_TICK - 1);
|
||||
cyc = (cyc / CYC_PER_TICK) * CYC_PER_TICK;
|
||||
|
||||
/* Due to elapsed time the calculation above might produce a
|
||||
* duration that laps the counter. Don't let it.
|
||||
*/
|
||||
if (cyc > MAX_CYCLES) {
|
||||
cyc = MAX_CYCLES;
|
||||
}
|
||||
|
||||
cyc += last_count;
|
||||
|
||||
/* Per NRF docs, the RTC is guaranteed to trigger a compare
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue