Skip to content

Commit aa8e343

Browse files
simonguinotgalak
authored andcommitted
drivers: systick: fix cycle count in sys_clock_set_timeout()
With this patch the sys_clock_set_timeout function counts the cycles elapsed while computing the systick timer's new load (tickless mode). This cycles are then added to the total cycle count instead of being lost. This patch mitigates uptime drifting in tickless mode (especially when high frequency timers are registered). Signed-off-by: Simon Guinot <simon.guinot@seagate.com>
1 parent 858dc7f commit aa8e343

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

drivers/timer/cortex_m_systick.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
180180

181181
#if defined(CONFIG_TICKLESS_KERNEL)
182182
uint32_t delay;
183+
uint32_t val1, val2;
184+
uint32_t last_load_ = last_load;
183185

184186
ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks;
185187
ticks = CLAMP(ticks - 1, 0, (int32_t)MAX_TICKS);
@@ -188,6 +190,8 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
188190

189191
uint32_t pending = elapsed();
190192

193+
val1 = SysTick->VAL;
194+
191195
cycle_count += pending;
192196
overflow_cyc = 0U;
193197

@@ -217,9 +221,27 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
217221
last_load = delay;
218222
}
219223
}
224+
225+
val2 = SysTick->VAL;
226+
220227
SysTick->LOAD = last_load - 1;
221228
SysTick->VAL = 0; /* resets timer to last_load */
222229

230+
/*
231+
* Add elapsed cycles while computing the new load to cycle_count.
232+
*
233+
* Note that comparing val1 and val2 is normaly not good enough to
234+
* guess if the counter wrapped during this interval. Indeed if val1 is
235+
* close to LOAD, then there are little chances to catch val2 between
236+
* val1 and LOAD after a wrap. COUNTFLAG should be checked in addition.
237+
* But since the load computation is faster than MIN_DELAY, then we
238+
* don't need to worry about this case.
239+
*/
240+
if (val1 < val2) {
241+
cycle_count += (val1 + (last_load_ - val2));
242+
} else {
243+
cycle_count += (val1 - val2);
244+
}
223245
k_spin_unlock(&lock, key);
224246
#endif
225247
}

0 commit comments

Comments
 (0)