From 54e915e40d7e701f36778a2ef75da6b5b41fa1dc Mon Sep 17 00:00:00 2001 From: Jue Date: Thu, 27 Oct 2022 23:48:08 +0200 Subject: [PATCH] cpu/efm32/timer_series2: sync STATUS register Make sure the STATUS register has been synced between the different clock domains. Especially the LETIMER needs some time to update the STATUS register after it has been enabled. If the LETIMER is started and stopped with just a short delay, pm_layered gets confused because the timer seems to be inactive ... --- cpu/efm32/periph/timer_series2.c | 34 ++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/cpu/efm32/periph/timer_series2.c b/cpu/efm32/periph/timer_series2.c index ee5772af13..87aa91c57c 100644 --- a/cpu/efm32/periph/timer_series2.c +++ b/cpu/efm32/periph/timer_series2.c @@ -224,26 +224,44 @@ unsigned int timer_read(tim_t dev) return _is_letimer(dev) ? _letimer_read(dev) : _timer_read(dev); } +static inline bool _letimer_is_running(LETIMER_TypeDef *tim) +{ + /* make sure registers are up-to-date and + * we can rely on the STATS register */ + LETIMER_SyncWait(tim); + + return tim->STATUS & LETIMER_STATUS_RUNNING; +} + +static inline bool _timer_is_running(TIMER_TypeDef *tim) +{ + /* make sure registers are up-to-date and + * we can rely on the STATS register */ + TIMER_SyncWait(tim); + + return tim->STATUS & TIMER_STATUS_RUNNING; +} + static inline void _letimer_stop(tim_t dev) { LETIMER_TypeDef *tim = timer_config[dev].dev; - if (tim->STATUS & LETIMER_STATUS_RUNNING) { + if (_letimer_is_running(tim)) { pm_unblock(LETIMER_PM_BLOCKER); } - LETIMER_Enable(timer_config[dev].dev, false); + LETIMER_Enable(tim, false); } static inline void _timer_stop(tim_t dev) { TIMER_TypeDef *tim = timer_config[dev].dev; - if (tim->STATUS & TIMER_STATUS_RUNNING) { + if (_timer_is_running(tim)) { pm_unblock(TIMER_PM_BLOCKER); } - TIMER_Enable(timer_config[dev].dev, false); + TIMER_Enable(tim, false); } void timer_stop(tim_t dev) @@ -255,22 +273,22 @@ static inline void _letimer_start(tim_t dev) { LETIMER_TypeDef *tim = timer_config[dev].dev; - if (!(tim->STATUS & LETIMER_STATUS_RUNNING)) { + if (!_letimer_is_running(tim)) { pm_block(LETIMER_PM_BLOCKER); } - LETIMER_Enable(timer_config[dev].dev, true); + LETIMER_Enable(tim, true); } static inline void _timer_start(tim_t dev) { TIMER_TypeDef *tim = timer_config[dev].dev; - if (!(tim->STATUS & TIMER_STATUS_RUNNING)) { + if (!_timer_is_running(tim)) { pm_block(TIMER_PM_BLOCKER); } - TIMER_Enable(timer_config[dev].dev, true); + TIMER_Enable(tim, true); } void timer_start(tim_t dev)