Skip to content

Commit 2bda7b8

Browse files
ChiHuaLkartben
authored andcommitted
driver: timer: npcx: bypass timer counter reading issue
Originally, when the timer's source clock is 32.768 kHz, the timer driver uses two consecutive reads to ensure the timer reading is correct. However, it is not robust enough due to an asynchronous timing issue in the chip. The workaround is to add at least two NOPs between the LDR and CMP instructions. This commit implements the workaround in the assembly code to ensure it is not affected by the compiler toolchain or optimization flags. Signed-off-by: Jun Lin <[email protected]>
1 parent bdf0500 commit 2bda7b8

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

drivers/timer/npcx_itim_timer.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,18 @@ static inline uint32_t npcx_itim_get_evt_cyc32(void)
217217
{
218218
uint32_t cnt1, cnt2;
219219

220-
cnt1 = evt_tmr->ITCNT32;
221-
/*
222-
* Wait for two consecutive equal values are read since the source clock
223-
* of event timer is 32KHz.
224-
*/
225-
while ((cnt2 = evt_tmr->ITCNT32) != cnt1) {
226-
cnt1 = cnt2;
227-
}
228-
220+
__asm__ volatile(
221+
"ldr %[c2], [%[tmr], %[itcnt32_off]]\n\t"
222+
".read_itim_cnt_loop_%=:\n\t"
223+
"mov %[c1], %[c2]\n\t"
224+
"ldr %[c2], [%[tmr], %[itcnt32_off]]\n\t"
225+
"nop\n\t"
226+
"nop\n\t"
227+
"cmp %[c1], %[c2]\n\t"
228+
"bne .read_itim_cnt_loop_%=\n\t"
229+
: [c1] "=&r"(cnt1), [c2] "=&r"(cnt2)
230+
: [tmr] "r"(evt_tmr), [itcnt32_off] "i"(offsetof(struct itim32_reg, ITCNT32))
231+
: "memory");
229232
/* Return current value of 32-bit counter of event timer */
230233
return cnt2;
231234
}

0 commit comments

Comments
 (0)