Skip to content

Commit 1b6e269

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 80da735 commit 1b6e269

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

drivers/timer/wch_systick_ch32v00x.c

Lines changed: 21 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,36 @@
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+
55+
ret = ch32v00x_systick_count + SYSTICK->CNT;
56+
k_spin_unlock(&lock, key);
57+
58+
return ret;
4459
}
4560

4661
uint32_t sys_clock_elapsed(void)
@@ -52,13 +67,15 @@ static int ch32v00x_systick_init(void)
5267
{
5368
IRQ_CONNECT(DT_INST_IRQN(0), 0, ch32v00x_systick_irq, NULL, 0);
5469

70+
SYSTICK->CTLR = 0;
5571
SYSTICK->SR = 0;
5672
SYSTICK->CMP = CYCLES_PER_TICK;
5773
SYSTICK->CNT = 0;
58-
SYSTICK->CTLR = STK_STRE | STK_STCLK | STK_STIE | STK_STE;
5974

6075
irq_enable(DT_INST_IRQN(0));
6176

77+
SYSTICK->CTLR = STK_STE | STK_STCLK | STK_STIE;
78+
6279
return 0;
6380
}
6481

0 commit comments

Comments
 (0)