@@ -79,8 +79,21 @@ static volatile uint16_t ticker_inited = 0;
79
79
#define TMR_CMP_MIN 2
80
80
#define TMR_CMP_MAX 0xFFFFFFu
81
81
82
- /* NOTE: When system clock is higher than timer clock, we need to add 3 engine clock
83
- * (recommended by designer) delay to wait for above timer control to take effect. */
82
+ /* Synchronization issue with LXT/LIRC-clocked Timer
83
+ *
84
+ * PCLK : typical HCLK/2
85
+ * ECLK (engine clock) : LXT/LIRC for Timer used to implement lp_ticker
86
+ *
87
+ * When system clock is higher than Timer clock (LXT/LIRC), we need to add delay for ECLK
88
+ * domain to take effect:
89
+ * 1. Write : typical 1PCLK + 2ECLK
90
+ * Read-check doesn't work because it just checks PCLK domain and doesn't check into
91
+ * ECLK domain.
92
+ * 2. Clear interrupt flag : typical 2PCLK
93
+ * It is very rare that we would meet dummy interrupt and get stuck in ISR until
94
+ * 'clear interrupt flag' takes effect. The issue is ignorable because the pending
95
+ * time is very short (at most 1 dummy interrupt). We won't take special handling for it.
96
+ */
84
97
85
98
void lp_ticker_init (void )
86
99
{
@@ -255,25 +268,7 @@ static void tmr1_vec(void)
255
268
static void tmr3_vec (void )
256
269
#endif
257
270
{
258
- /* NOTE: Avoid blocking in ISR due to wait for "clear interrupt flag"
259
- *
260
- * "clear interrupt flag" needs wait to take effect which isn't added here to avoid
261
- * blocking in ISR.
262
- *
263
- * Continuing above, we will get stuck in ISR due to dummy interrupt until
264
- * "clear interrupt flag" takes effect. To avoid it, we disable interrupt here and enable
265
- * interrupt in lp_ticker_fire_interrupt/lp_ticker_set_interrupt. There is another risk
266
- * that we may get stuck in a loop of ISR and lp_ticker_fire_interrupt/
267
- * lp_ticker_set_interrupt (called by lp_ticker_irq_handler), but actually we don't:
268
- * 1. When lp_ticker_fire_interrupt gets called, it means there is a past event and so this
269
- * interrupt isn't dummy.
270
- * 2. With LPTICKER_DELAY_TICKS enabled, it is lp_ticker_set_interrupt_wrapper rather than
271
- * lp_ticker_set_interrupt that gets straight called. lp_ticker_set_interrupt_wrapper
272
- * guarantees that lp_ticker_set_interrupt won't get re-called in LPTICKER_DELAY_TICKS ticks
273
- * which is just enough for "clear interrupt flag" to take effect.
274
- */
275
271
lp_ticker_clear_interrupt ();
276
- lp_ticker_disable_interrupt ();
277
272
278
273
// NOTE: lp_ticker_set_interrupt() may get called in lp_ticker_irq_handler();
279
274
lp_ticker_irq_handler ();
0 commit comments