drivers: timer: fix tickless contineous interrupts
K_FOREVER/INT_MAX number of ticks needs delay cycles value of maximum order and exceeds 'int32' range. The typecast to 'int32' results in wrongly evaluating the value as less than 'MIN_DELAY' and chooses 'MIN_DELAY' over the actual delay cycles. Cap the 'MAX_TICKS' to INT32_MAX. fixes: #26632 Signed-off-by: Sandeep Tripathy <sandeep.tripathy@broadcom.com>
This commit is contained in:
parent
c5132aac18
commit
b37ce93979
1 changed files with 12 additions and 12 deletions
|
@ -10,10 +10,9 @@
|
|||
#include <spinlock.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#define CYC_PER_TICK ((uint32_t)((uint64_t)sys_clock_hw_cycles_per_sec() \
|
||||
/ (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC))
|
||||
|
||||
#define MAX_TICKS ((0xffffffffu - CYC_PER_TICK) / CYC_PER_TICK)
|
||||
#define CYC_PER_TICK ((uint64_t)sys_clock_hw_cycles_per_sec() \
|
||||
/ (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)
|
||||
#define MAX_TICKS INT32_MAX
|
||||
#define MIN_DELAY (1000)
|
||||
|
||||
static struct k_spinlock lock;
|
||||
|
@ -33,7 +32,7 @@ static void arm_arch_timer_compare_isr(void *arg)
|
|||
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
|
||||
uint64_t next_cycle = last_cycle + CYC_PER_TICK;
|
||||
|
||||
if ((int64_t)(next_cycle - curr_cycle) < MIN_DELAY) {
|
||||
if ((uint64_t)(next_cycle - curr_cycle) < MIN_DELAY) {
|
||||
next_cycle += CYC_PER_TICK;
|
||||
}
|
||||
arm_arch_timer_set_compare(next_cycle);
|
||||
|
@ -67,18 +66,19 @@ void z_clock_set_timeout(int32_t ticks, bool idle)
|
|||
return;
|
||||
}
|
||||
|
||||
ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks;
|
||||
ticks = MAX(MIN(ticks - 1, (int32_t)MAX_TICKS), 0);
|
||||
ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : \
|
||||
MIN(MAX_TICKS, MAX(ticks - 1, 0));
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
uint64_t curr_cycle = arm_arch_timer_count();
|
||||
uint32_t req_cycle = ticks * CYC_PER_TICK;
|
||||
uint64_t req_cycle = ticks * CYC_PER_TICK;
|
||||
|
||||
/* Round up to next tick boundary */
|
||||
req_cycle += (uint32_t)(curr_cycle - last_cycle) + (CYC_PER_TICK - 1);
|
||||
req_cycle += (curr_cycle - last_cycle) + (CYC_PER_TICK - 1);
|
||||
|
||||
req_cycle = (req_cycle / CYC_PER_TICK) * CYC_PER_TICK;
|
||||
|
||||
if ((int32_t)(req_cycle + last_cycle - curr_cycle) < MIN_DELAY) {
|
||||
if ((req_cycle + last_cycle - curr_cycle) < MIN_DELAY) {
|
||||
req_cycle += CYC_PER_TICK;
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,8 @@ uint32_t z_clock_elapsed(void)
|
|||
}
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
uint32_t ret = ((uint32_t)arm_arch_timer_count() - (uint32_t)last_cycle)
|
||||
/ CYC_PER_TICK;
|
||||
uint32_t ret = (uint32_t)((arm_arch_timer_count() - last_cycle)
|
||||
/ CYC_PER_TICK);
|
||||
|
||||
k_spin_unlock(&lock, key);
|
||||
return ret;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue