mirror of https://github.com/ARMmbed/mbed-os.git
Nordic: handle unwanted RTC interrupts
This patch clears the EVENT_COMPARE register even when we're not
expecting to get a COMPARE interrupt.
Here is a scenario where we get an unwelcome interrupt, and where it
currently results in a deadlock:
* A Ticker T1 runs at 500ms
* Its handler registers a Timeout T2 at 20µs. Since LF clock runs at
32.768kHz, this will be rounded up to a multiple of 30.5µs (actually
61µs, to ensure we're in the next tick window)
T1 T2 T1' T2'
-------|---|---------------------------------|---|--------->
: : :
<---> n * 30.5µs :
<--------------- 500ms --------------->
* When the ticker API handles T1, it calls us_ticker_set_interrupt a
first time for T1', and then for registering T2.
* Since T2 period is less than one RTC tick (30.5µs), there is a high
chance it will go past *while* we're still in this first handler.
* So ticker_irq_handler also handles T2 as well, and removes it from the
queue.
* us_ticker_set_interrupt is called for T1' before returning from
ticker_irq_handler
The problem resides in the fact that us_ticker_set_interrupt takes more
than 2 RTC ticks to execute: while inside the handler, T2 interrupt will
fire.
* Because of this pending interrupt, RTC1_IRQHandler will be called
right away, but since we removed T2 from the queue, the handler is
waiting for T1' instead, and will not clear EVENT_COMPARE until we
reach the T1' tick, in about 500ms.
* This results in a lock and main isn't executed anymore.
With this patch, we avoid being stuck in RTC1_IRQHandler while waiting
for T1'.
Note: even when T2 isn't handled in the same loop as T1, we may get a
spurious interrupt, because us_ticker_set_interrupt will be called twice
for T2... and will register T2+m the second time, while T2 interrupt is
fired in the background.
That case isn't as harmful, since RTC1_IRQHandler will be waiting for
T2+m, which is only one or two ticks further, and then it won't be
called again before T1'.
Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
pull/1281/head
parent
24cc331f12
commit
1c90449f35
|
|
@ -159,10 +159,11 @@ void RTC1_IRQHandler(void)
|
|||
NRF_RTC1->EVENTS_OVRFLW = 0;
|
||||
NRF_RTC1->EVTENCLR = RTC_EVTEN_OVRFLW_Msk;
|
||||
}
|
||||
if (NRF_RTC1->EVENTS_COMPARE[0] && us_ticker_callbackPending && ((int)(us_ticker_callbackTimestamp - rtc1_getCounter()) <= 0)) {
|
||||
if (NRF_RTC1->EVENTS_COMPARE[0]) {
|
||||
NRF_RTC1->EVENTS_COMPARE[0] = 0;
|
||||
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
|
||||
invokeCallback();
|
||||
if (us_ticker_callbackPending && ((int)(us_ticker_callbackTimestamp - rtc1_getCounter()) <= 0))
|
||||
invokeCallback();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue