From 704ca8f1b4ddb43fdecf5c1cbea62e8d84c1d62d Mon Sep 17 00:00:00 2001 From: Julien D'Ascenzio Date: Fri, 13 Jan 2023 12:07:43 +0100 Subject: [PATCH] drivers: timer: stm32_lptim: fix sys_clock_* return value This commit finish to fix the bug describe by 85e2a0679a68f02f7ef. With the previous correction, the uptime read could be in the past: if the counter rewinds just after testing ARRM flag, we had lost some counts. Signed-off-by: Julien D'Ascenzio --- drivers/timer/stm32_lptim_timer.c | 57 +++++++++++++++++-------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/timer/stm32_lptim_timer.c b/drivers/timer/stm32_lptim_timer.c index 6df7e693d5e..c32a49ec34e 100644 --- a/drivers/timer/stm32_lptim_timer.c +++ b/drivers/timer/stm32_lptim_timer.c @@ -86,6 +86,11 @@ static struct k_spinlock lock; #endif #endif /* !CONFIG_STM32_LPTIM_TICK_FREQ_RATIO_OVERRIDE */ +static inline bool arrm_state_get(void) +{ + return (LL_LPTIM_IsActiveFlag_ARRM(LPTIM) && LL_LPTIM_IsEnabledIT_ARRM(LPTIM)); +} + static void lptim_irq_handler(const struct device *unused) { @@ -105,9 +110,7 @@ static void lptim_irq_handler(const struct device *unused) } } - if ((LL_LPTIM_IsActiveFlag_ARRM(LPTIM) != 0) - && LL_LPTIM_IsEnabledIT_ARRM(LPTIM) != 0) { - + if (arrm_state_get()) { k_spinlock_key_t key = k_spin_lock(&lock); /* do not change ARR yet, sys_clock_announce will do */ @@ -238,6 +241,29 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) k_spin_unlock(&lock, key); } +static uint32_t sys_clock_lp_time_get(void) +{ + uint32_t lp_time; + + do { + /* In case of counter roll-over, add the autoreload value, + * because the irq has not yet been handled + */ + if (arrm_state_get()) { + lp_time = LL_LPTIM_GetAutoReload(LPTIM) + 1; + lp_time += z_clock_lptim_getcounter(); + break; + } + + lp_time = z_clock_lptim_getcounter(); + + /* Check if the flag ARRM wasn't be set during the process */ + } while (arrm_state_get()); + + return lp_time; +} + + uint32_t sys_clock_elapsed(void) { if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { @@ -246,20 +272,7 @@ uint32_t sys_clock_elapsed(void) k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t lp_time = 0; - - /* In case of counter roll-over, add the autoreload value, - * even if the irq has not yet been handled. - * Check ARRM flag before loading counter to make - * sure we don't use a counter close to ARR that - * hasn't triggered ARRM yet, which would mistakenly - * account for double the number of ticks. - */ - if ((LL_LPTIM_IsActiveFlag_ARRM(LPTIM) != 0) - && LL_LPTIM_IsEnabledIT_ARRM(LPTIM) != 0) { - lp_time += LL_LPTIM_GetAutoReload(LPTIM) + 1; - } - lp_time += z_clock_lptim_getcounter(); + uint32_t lp_time = sys_clock_lp_time_get(); k_spin_unlock(&lock, key); @@ -277,15 +290,7 @@ uint32_t sys_clock_cycle_get_32(void) k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t lp_time = z_clock_lptim_getcounter(); - - /* In case of counter roll-over, add this value, - * even if the irq has not yet been handled - */ - if ((LL_LPTIM_IsActiveFlag_ARRM(LPTIM) != 0) - && LL_LPTIM_IsEnabledIT_ARRM(LPTIM) != 0) { - lp_time += LL_LPTIM_GetAutoReload(LPTIM) + 1; - } + uint32_t lp_time = sys_clock_lp_time_get(); lp_time += accumulated_lptim_cnt;