Skip to content

Commit a4b4792

Browse files
c1728p9adbridge
authored andcommitted
Safely initialize RTC on kinetis devices
When initializing the RTC on Kinetis devices, handle the case where the time overflow interrupt is pending and the case where the time alarm flag is pending. These flags persist across reset and if not handled will cause a crash when powering up the low power ticker. This problem manifested as a lp_ticker test failure on the K22F and K64F on CI only when running a nightly. This problem has been present but was made obvious by PR #4094 which configures all tickers to interrupt at least every MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA (~31 minutes). This caused the RTC alarm to fire 31 minutes after the lp_ticker or lp_timeout test and caused the next run of the lp_ticker test to crash on boot.
1 parent 206e1b7 commit a4b4792

File tree

1 file changed

+21
-10
lines changed
  • targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api

1 file changed

+21
-10
lines changed

targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/api/lp_ticker.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,26 @@ static int lptmr_schedule = 0;
3333

3434
static void rtc_isr(void)
3535
{
36-
RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable);
37-
RTC->TAR = 0; /* Write clears the IRQ flag */
38-
39-
/* Wait subsecond remainder if any */
40-
if (lptmr_schedule) {
41-
LPTMR_SetTimerPeriod(LPTMR0, lptmr_schedule);
42-
LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
43-
LPTMR_StartTimer(LPTMR0);
44-
} else {
45-
lp_ticker_irq_handler();
36+
uint32_t sr = RTC->SR;
37+
if (sr & RTC_SR_TOF_MASK) {
38+
// Reset RTC to 0 so it keeps counting
39+
RTC_StopTimer(RTC);
40+
RTC->TSR = 0;
41+
RTC_StartTimer(RTC);
42+
} else if (sr & RTC_SR_TAF_MASK) {
43+
RTC_DisableInterrupts(RTC, kRTC_AlarmInterruptEnable);
44+
RTC->TAR = 0; /* Write clears the IRQ flag */
45+
46+
/* Wait subsecond remainder if any */
47+
if (lptmr_schedule) {
48+
LPTMR_SetTimerPeriod(LPTMR0, lptmr_schedule);
49+
LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
50+
LPTMR_StartTimer(LPTMR0);
51+
} else {
52+
lp_ticker_irq_handler();
53+
}
54+
} else if (sr & RTC_SR_TIF_MASK) {
55+
RTC_DisableInterrupts(RTC, kRTC_TimeOverflowInterruptEnable);
4656
}
4757
}
4858

@@ -73,6 +83,7 @@ void lp_ticker_init(void)
7383
RTC_StartTimer(RTC);
7484
}
7585

86+
RTC->TAR = 0; /* Write clears the IRQ flag */
7687
NVIC_ClearPendingIRQ(RTC_IRQn);
7788
NVIC_SetVector(RTC_IRQn, (uint32_t)rtc_isr);
7889
NVIC_EnableIRQ(RTC_IRQn);

0 commit comments

Comments
 (0)