From 3e729b2b1c525d548af8caed3dfa75dcf288cfee Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Thu, 23 Apr 2020 10:05:31 -0700 Subject: [PATCH] kernel/timer: Correctly clamp period argument The period argument of a k_timer needs an offset of one tick from the value computed in user code (because periods get reset from within the ISR, see the comment above this code for an explanation). When the computed tick value was 1, it would become 0. This is actually perfectly correct as a k_timeout_t to be passed to z_add_timeout(). BUT: to k_timer's API, K_NO_WAIT means "never" (i.e. the same as K_FOREVER) and not "as soon as possible", so the period timer would not be reset. This is sort of a wart, but it's the way the API has been specified forever. The upshot is that for the case of calling k_timer_start() with a minimal period argument (i.e. one that produces "one tick"), the period would be ignored and the timer would act like a one shot. Fix the clamp so it can't produce K_NO_WAIT. This also adds a filter for absolute timeouts, which (while that's sort of a pathological usage) were getting that one tick offset when it wasn't appropriate. Signed-off-by: Andy Ross --- kernel/timer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/timer.c b/kernel/timer.c index 55760c05325..900e88e2a8c 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -126,7 +126,9 @@ void z_impl_k_timer_start(struct k_timer *timer, k_timeout_t duration, * argument the same way k_sleep() does), but historical. The * timer_api test relies on this behavior. */ - period.ticks = MAX(period.ticks - 1, 0); + if (period.ticks != 0 && Z_TICK_ABS(period.ticks) < 0) { + period.ticks = MAX(period.ticks - 1, 1); + } if (Z_TICK_ABS(duration.ticks) < 0) { duration.ticks = MAX(duration.ticks - 1, 0); }