drivers/timer: Clamp after tick adjustment, not before
Some early tickless drivers had a common pattern where they would compute a tick maximum for the request (i.e. the maximum the hardware counter can handle) but apply it only on the input tick value and not on the adjusted final value, opening up the overflow condition it was supposed to have prevented. Fixes #20939 (Strictly it fixes the specific pattern that was discovered in that bug. It's not impossible that other drivers with alternative implementations have a similar issue, though they look OK to me via a quick audit). Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
44bbdd0a94
commit
5f63c9d907
4 changed files with 33 additions and 14 deletions
|
@ -136,10 +136,17 @@ void z_clock_set_timeout(s32_t ticks, bool idle)
|
|||
ticks = MAX(MIN(ticks - 1, (s32_t)max_ticks), 0);
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
u32_t now = MAIN_COUNTER_REG, cyc;
|
||||
u32_t now = MAIN_COUNTER_REG, cyc, adj;
|
||||
u32_t max_cyc = max_ticks * cyc_per_tick;
|
||||
|
||||
/* Round up to next tick boundary */
|
||||
cyc = ticks * cyc_per_tick + (now - last_count) + (cyc_per_tick - 1);
|
||||
/* Round up to next tick boundary. */
|
||||
cyc = ticks * cyc_per_tick;
|
||||
adj = (now - last_count) + (cyc_per_tick - 1);
|
||||
if (cyc <= max_cyc - adj) {
|
||||
cyc += adj;
|
||||
} else {
|
||||
cyc = max_cyc;
|
||||
}
|
||||
cyc = (cyc / cyc_per_tick) * cyc_per_tick;
|
||||
cyc += last_count;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue