Timer Systick : Handle Systick timer rollback in tickless kernel Case
In Tickeless kernel Platform timekeeping is having error because "_sys_clock_tick_count" is not getting updated correctly. Currently "OVERFLOW" Flag (bit 16 in timer control register) is reset before it is taken into account into _sys_clock_tick_count. This patch sets a flag as soon as Timer Overflow occues and clears it when time is accounted into _sys_clock_tick_count. Jira : ZEP-2217 Signed-off-by: Youvedeep Singh <youvedeep.singh@intel.com>
This commit is contained in:
parent
2fab706216
commit
5efaca470c
1 changed files with 24 additions and 9 deletions
|
@ -66,6 +66,9 @@ static u32_t __noinit default_load_value; /* default count */
|
|||
#ifndef CONFIG_TICKLESS_KERNEL
|
||||
static u32_t idle_original_count;
|
||||
#endif
|
||||
#ifdef CONFIG_TICKLESS_KERNEL
|
||||
static u32_t timer_overflow;
|
||||
#endif
|
||||
static u32_t __noinit max_system_ticks;
|
||||
static u32_t idle_original_ticks;
|
||||
static u32_t __noinit max_load_value;
|
||||
|
@ -142,7 +145,8 @@ static ALWAYS_INLINE u32_t sysTickCurrentGet(void)
|
|||
* Counter can rollover if irqs are locked for too long.
|
||||
* Return 0 to indicate programmed cycles have expired.
|
||||
*/
|
||||
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
|
||||
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) || (timer_overflow)) {
|
||||
timer_overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -239,13 +243,13 @@ void _timer_int_handler(void *unused)
|
|||
|
||||
#ifdef CONFIG_TICKLESS_IDLE
|
||||
#if defined(CONFIG_TICKLESS_KERNEL)
|
||||
|
||||
sysTickStop();
|
||||
|
||||
if (!idle_original_ticks) {
|
||||
if (_sys_clock_always_on) {
|
||||
_sys_clock_tick_count = _get_elapsed_clock_time();
|
||||
|
||||
/* clear overflow tracking flag as it is accounted */
|
||||
timer_overflow = 0;
|
||||
sysTickStop();
|
||||
idle_original_ticks = max_system_ticks;
|
||||
sysTickReloadSet(max_load_value);
|
||||
sysTickStart();
|
||||
sys_tick_reload();
|
||||
|
@ -272,6 +276,9 @@ void _timer_int_handler(void *unused)
|
|||
/* _sys_clock_tick_announce() could cause new programming */
|
||||
if (!idle_original_ticks && _sys_clock_always_on) {
|
||||
_sys_clock_tick_count = _get_elapsed_clock_time();
|
||||
/* clear overflow tracking flag as it is accounted */
|
||||
timer_overflow = 0;
|
||||
sysTickStop();
|
||||
sysTickReloadSet(max_load_value);
|
||||
sysTickStart();
|
||||
sys_tick_reload();
|
||||
|
@ -363,7 +370,8 @@ u32_t _get_remaining_program_time(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return sysTickCurrentGet() / default_load_value;
|
||||
return (u32_t)ceiling_fraction((u32_t)sysTickCurrentGet(),
|
||||
default_load_value);
|
||||
}
|
||||
|
||||
u32_t _get_elapsed_program_time(void)
|
||||
|
@ -377,8 +385,6 @@ u32_t _get_elapsed_program_time(void)
|
|||
|
||||
void _set_time(u32_t time)
|
||||
{
|
||||
sysTickStop();
|
||||
|
||||
if (!time) {
|
||||
idle_original_ticks = 0;
|
||||
return;
|
||||
|
@ -388,6 +394,9 @@ void _set_time(u32_t time)
|
|||
|
||||
_sys_clock_tick_count = _get_elapsed_clock_time();
|
||||
|
||||
/* clear overflow tracking flag as it is accounted */
|
||||
timer_overflow = 0;
|
||||
sysTickStop();
|
||||
sysTickReloadSet(idle_original_ticks * default_load_value);
|
||||
|
||||
sysTickStart();
|
||||
|
@ -406,8 +415,12 @@ static inline u64_t get_elapsed_count(void)
|
|||
{
|
||||
u64_t elapsed;
|
||||
|
||||
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
|
||||
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) || (timer_overflow)) {
|
||||
elapsed = SysTick->LOAD;
|
||||
/* Keep track of overflow till it is accounted in
|
||||
* _sys_clock_tick_count as COUNTFLAG bit is clear on read
|
||||
*/
|
||||
timer_overflow = 1;
|
||||
} else {
|
||||
elapsed = (SysTick->LOAD - SysTick->VAL);
|
||||
}
|
||||
|
@ -594,6 +607,8 @@ void _timer_idle_exit(void)
|
|||
if (idle_mode == IDLE_TICKLESS) {
|
||||
idle_mode = IDLE_NOT_TICKLESS;
|
||||
if (!idle_original_ticks && _sys_clock_always_on) {
|
||||
_sys_clock_tick_count = _get_elapsed_clock_time();
|
||||
timer_overflow = 0;
|
||||
sysTickReloadSet(max_load_value);
|
||||
sysTickStart();
|
||||
sys_tick_reload();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue