Skip to content

Commit 3594f13

Browse files
pabigotdleach02
authored andcommitted
drivers: systick: avoid starving clock announcements
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]>
1 parent b3574bd commit 3594f13

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

drivers/timer/cortex_m_systick.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,30 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
188188

189189
k_spinlock_key_t key = k_spin_lock(&lock);
190190

191-
cycle_count += elapsed();
192-
193-
/* Round delay up to next tick boundary */
194-
delay = delay + (cycle_count - announced_cycles);
195-
delay = ((delay + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK;
196-
last_load = delay - (cycle_count - announced_cycles);
191+
u32_t pending = elapsed();
197192

193+
cycle_count += pending;
198194
overflow_cyc = 0U;
195+
196+
u32_t unannounced = cycle_count - announced_cycles;
197+
198+
if ((s32_t)unannounced < 0) {
199+
/* We haven't announced for more than half the 32-bit
200+
* wrap duration, because new timeouts keep being set
201+
* before the existing one fires. Force an announce
202+
* to avoid loss of a wrap event, making sure the
203+
* delay is at least the minimum delay possible.
204+
*/
205+
last_load = MIN_DELAY;
206+
} else {
207+
/* Round delay up to next tick boundary */
208+
delay += unannounced;
209+
delay =
210+
((delay + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK;
211+
delay -= unannounced;
212+
last_load = delay;
213+
214+
}
199215
SysTick->LOAD = last_load - 1;
200216
SysTick->VAL = 0; /* resets timer to last_load */
201217

0 commit comments

Comments
 (0)