summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatryk Duda <pdk@semihalf.com>2021-12-20 12:12:21 +0100
committerCommit Bot <commit-bot@chromium.org>2022-01-19 17:57:52 +0000
commit8e2f1ed611679ae42779748596e5f6482bd9f6b6 (patch)
treeacc4899eba38bcf3c4cdbf6ffabc1aefcccc0ff1
parenta13821d34669aa01a863ad1ea5cc6292234fe006 (diff)
downloadchrome-ec-8e2f1ed611679ae42779748596e5f6482bd9f6b6.tar.gz
stm32/hwtimer: Clear status register after counter is set
Whenever a timer interrupt occurs, the status register is checked for overflow and the overflow status is passed to process_timers(), which increments clksrc_high. When setting the clock to a new time, we don't want the previous overflow state to trigger this process. To avoid this problem, just clear status register when new value is assigned to counter. To avoid race between updating counter and clearing status, operation is performed when counters are disabled. BUG=b:200828093 BRANCH=none TEST=make -j buildall Signed-off-by: Patryk Duda <pdk@semihalf.com> Change-Id: Ifa3f2ff293483e167b5c7b6ff136708a876e8054 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3378344 Reviewed-by: Tom Hughes <tomhughes@chromium.org> Reviewed-by: Bobby Casey <bobbycasey@google.com>
-rw-r--r--chip/stm32/hwtimer.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/chip/stm32/hwtimer.c b/chip/stm32/hwtimer.c
index c215484a22..84a193c14a 100644
--- a/chip/stm32/hwtimer.c
+++ b/chip/stm32/hwtimer.c
@@ -209,8 +209,32 @@ uint32_t __hw_clock_source_read(void)
void __hw_clock_source_set(uint32_t ts)
{
+ ASSERT(!is_interrupt_enabled());
+
+ /* Stop counting (LSB first, then MSB) */
+ STM32_TIM_CR1(TIM_CLOCK_LSB) &= ~1;
+ STM32_TIM_CR1(TIM_CLOCK_MSB) &= ~1;
+
+ /* Set new value to counters */
STM32_TIM_CNT(TIM_CLOCK_MSB) = ts >> 16;
STM32_TIM_CNT(TIM_CLOCK_LSB) = ts & 0xffff;
+
+ /*
+ * Clear status. We may clear information other than timer overflow
+ * (eg. event timestamp was matched) but:
+ * - Bits other than overflow are unused (see __hw_clock_source_irq())
+ * - After setting timestamp software will trigger timer interrupt using
+ * task_trigger_irq() (see force_time() in common/timer.c).
+ * process_timers() is called from timer interrupt, so if "match" bit
+ * was present in status (think: some task timers are expired)
+ * process_timers() will handle that correctly.
+ */
+ STM32_TIM_SR(TIM_CLOCK_MSB) = 0;
+ STM32_TIM_SR(TIM_CLOCK_LSB) = 0;
+
+ /* Start counting (MSB first, then LSB) */
+ STM32_TIM_CR1(TIM_CLOCK_MSB) |= 1;
+ STM32_TIM_CR1(TIM_CLOCK_LSB) |= 1;
}
static void __hw_clock_source_irq(void)
@@ -356,14 +380,14 @@ int __hw_clock_source_init(uint32_t start_t)
STM32_TIM_DIER(TIM_CLOCK_MSB) = 0x0001;
STM32_TIM_DIER(TIM_CLOCK_LSB) = 0x0000;
+ /* Override the count with the start value */
+ STM32_TIM_CNT(TIM_CLOCK_MSB) = start_t >> 16;
+ STM32_TIM_CNT(TIM_CLOCK_LSB) = start_t & 0xffff;
+
/* Start counting */
STM32_TIM_CR1(TIM_CLOCK_MSB) |= 1;
STM32_TIM_CR1(TIM_CLOCK_LSB) |= 1;
- /* Override the count with the start value now that counting has
- * started. */
- __hw_clock_source_set(start_t);
-
/* Enable timer interrupts */
task_enable_irq(IRQ_MSB);
task_enable_irq(IRQ_LSB);