Skip to content

Commit

Permalink
drivers: systick: avoid starving clock announcements
Browse files Browse the repository at this point in the history
When setting a timeout measure the number of accumulated unannounced
ticks.  If this value exceeds half the 32-bit cycle counter range
force an announcement so the unannounced cycles are incorporated into
the system tick counter.

Signed-off-by: Peter Bigot <[email protected]>
  • Loading branch information
pabigot authored and dleach02 committed Nov 26, 2019
1 parent b3574bd commit 3594f13
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions drivers/timer/cortex_m_systick.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,30 @@ void z_clock_set_timeout(s32_t ticks, bool idle)

k_spinlock_key_t key = k_spin_lock(&lock);

cycle_count += elapsed();

/* Round delay up to next tick boundary */
delay = delay + (cycle_count - announced_cycles);
delay = ((delay + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK;
last_load = delay - (cycle_count - announced_cycles);
u32_t pending = elapsed();

cycle_count += pending;
overflow_cyc = 0U;

u32_t unannounced = cycle_count - announced_cycles;

if ((s32_t)unannounced < 0) {
/* We haven't announced for more than half the 32-bit
* wrap duration, because new timeouts keep being set
* before the existing one fires. Force an announce
* to avoid loss of a wrap event, making sure the
* delay is at least the minimum delay possible.
*/
last_load = MIN_DELAY;
} else {
/* Round delay up to next tick boundary */
delay += unannounced;
delay =
((delay + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK;
delay -= unannounced;
last_load = delay;

}
SysTick->LOAD = last_load - 1;
SysTick->VAL = 0; /* resets timer to last_load */

Expand Down

0 comments on commit 3594f13

Please sign in to comment.