timer: cortex_m_systick: idle timer: handle no sleep case

SysTick usually has higher measurement resolution than the IDLE timer.
When the time in low power mode is very short or 0, it is possible that
SysTick usually has measures more time since the sys_clock_set_timeout
than the idle timer.

Handle that case to keep uptime correct.

Signed-off-by: Dawid Niedzwiecki <dawidn@google.com>
This commit is contained in:
Dawid Niedzwiecki 2023-11-23 10:37:46 +01:00 committed by Carles Cufí
parent 4104f54987
commit 733bddb32e

View file

@ -368,7 +368,7 @@ void sys_clock_idle_exit(void)
if (timeout_idle) {
cycle_t cycle_post_idle, systick_diff, missed_cycles;
uint32_t idle_timer_diff, idle_timer_post, dcycles, dticks;
uint64_t systick_us, idle_timer_us, measurement_diff_us;
uint64_t systick_us, idle_timer_us;
/* Get current values for both timers */
counter_get_value(idle_timer, &idle_timer_post);
@ -402,9 +402,20 @@ void sys_clock_idle_exit(void)
/* Calculate difference in measurements to get how much time
* the SysTick missed in idle state.
*/
measurement_diff_us = idle_timer_us - systick_us;
missed_cycles =
(sys_clock_hw_cycles_per_sec() * measurement_diff_us) / USEC_PER_SEC;
if (idle_timer_us < systick_us) {
/* This case is possible, when the time in low power mode is
* very short or 0. SysTick usually has higher measurement
* resolution of than the IDLE timer, thus the measurement of
* passed time since the sys_clock_set_timeout call can be higher.
*/
missed_cycles = 0;
} else {
uint64_t measurement_diff_us;
measurement_diff_us = idle_timer_us - systick_us;
missed_cycles = (sys_clock_hw_cycles_per_sec() * measurement_diff_us) /
USEC_PER_SEC;
}
/* Update the cycle counter to include the cycles missed in idle */
cycle_count += missed_cycles;