Skip to content

Commit 0b53be9

Browse files
committed
drivers: timer: WCH system timer fixes
Use a spinlock to be sure we're consistently returning monotonically increasing time, and not accessing the periperal or local count and then have them changed out from under us in the ISR. Also tweak the init ordering a bit to ensure IRQs are enabled before enabling the peripheral. Signed-off-by: Peter Johanson <peter@peterjohanson.com>
1 parent 087888e commit 0b53be9

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

drivers/timer/wch_systick_ch32v00x.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010
#include <zephyr/drivers/timer/system_timer.h>
1111
#include <zephyr/irq.h>
1212
#include <zephyr/kernel.h>
13+
#include <zephyr/spinlock.h>
1314
#include <zephyr/sys/util.h>
1415

1516
#include <hal_ch32fun.h>
1617

17-
#define STK_SWIE BIT(31)
18-
#define STK_STRE BIT(3)
1918
#define STK_STCLK BIT(2)
2019
#define STK_STIE BIT(1)
2120
#define STK_STE BIT(0)
@@ -27,20 +26,35 @@
2726

2827
#define SYSTICK ((SysTick_Type *)(DT_INST_REG_ADDR(0)))
2928

29+
static struct k_spinlock lock;
3030
static volatile uint32_t ch32v00x_systick_count;
3131

3232
static void ch32v00x_systick_irq(const void *unused)
3333
{
3434
ARG_UNUSED(unused);
3535

36+
k_spinlock_key_t key = k_spin_lock(&lock);
37+
38+
SYSTICK->CTLR &= ~(STK_STE);
3639
SYSTICK->SR = 0;
40+
SYSTICK->CNT = 0;
41+
SYSTICK->CTLR |= STK_STE;
42+
3743
ch32v00x_systick_count += CYCLES_PER_TICK; /* Track cycles. */
44+
45+
k_spin_unlock(&lock, key);
3846
sys_clock_announce(1); /* Poke the scheduler. */
3947
}
4048

4149
uint32_t sys_clock_cycle_get_32(void)
4250
{
43-
return ch32v00x_systick_count + SYSTICK->CNT;
51+
uint32_t ret;
52+
53+
k_spinlock_key_t key = k_spin_lock(&lock);
54+
ret = ch32v00x_systick_count + SYSTICK->CNT;
55+
k_spin_unlock(&lock, key);
56+
57+
return ret;
4458
}
4559

4660
uint32_t sys_clock_elapsed(void)
@@ -52,13 +66,15 @@ static int ch32v00x_systick_init(void)
5266
{
5367
IRQ_CONNECT(DT_INST_IRQN(0), 0, ch32v00x_systick_irq, NULL, 0);
5468

69+
SYSTICK->CTLR = 0;
5570
SYSTICK->SR = 0;
5671
SYSTICK->CMP = CYCLES_PER_TICK;
5772
SYSTICK->CNT = 0;
58-
SYSTICK->CTLR = STK_STRE | STK_STCLK | STK_STIE | STK_STE;
5973

6074
irq_enable(DT_INST_IRQN(0));
6175

76+
SYSTICK->CTLR = STK_STE | STK_STCLK | STK_STIE;
77+
6278
return 0;
6379
}
6480

0 commit comments

Comments
 (0)