Skip to content

Commit

Permalink
driver: timer: npcx: bypass timer counter reading issue
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ChiHuaL committed Dec 11, 2024
1 parent 98f2d51 commit f5e1760
Showing 1 changed file with 12 additions and 9 deletions.
21 changes: 12 additions & 9 deletions drivers/timer/npcx_itim_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,18 @@ static inline uint32_t npcx_itim_get_evt_cyc32(void)
{
uint32_t cnt1, cnt2;

cnt1 = evt_tmr->ITCNT32;
/*
* Wait for two consecutive equal values are read since the source clock
* of event timer is 32KHz.
*/
while ((cnt2 = evt_tmr->ITCNT32) != cnt1) {
cnt1 = cnt2;
}

__asm__ volatile(
"ldr %[c2], [%[tmr], %[itcnt32_off]]\n\t"
".read_itim_cnt_loop_%=:\n\t"
"mov %[c1], %[c2]\n\t"
"ldr %[c2], [%[tmr], %[itcnt32_off]]\n\t"
"nop\n\t"
"nop\n\t"
"cmp %[c1], %[c2]\n\t"
"bne .read_itim_cnt_loop_%=\n\t"
: [c1] "=&r"(cnt1), [c2] "=&r"(cnt2)
: [tmr] "r"(evt_tmr), [itcnt32_off] "i"(offsetof(struct itim32_reg, ITCNT32))
: "memory");
/* Return current value of 32-bit counter of event timer */
return cnt2;
}
Expand Down

0 comments on commit f5e1760

Please sign in to comment.