SDK的RTC驱动对闹钟的处理不完善导致频繁进中断并看门狗复位问题
-
在SDK的RTC驱动存在一个BUG,公司生产项目有遇到,最近发现新版本SDK还没修复。
主要问题是RTC_DRV_IRQHandler中没有对alarm触发且alarmConfig为NULL的情况做处理,然后会一直触发RTC中断,最终导致MCU看门狗复位(复位也不会恢复,会一直持续复位)。复现流程:
- 正常上电
- 设置RTC闹钟
- 在RTC闹钟触发前软复位MCU(会导致alarmConfig变为NULL)
- 到RTC闹钟时间时会一直进RTC中断
- 看门狗复位
代码位置:
void RTC_DRV_IRQHandler(uint32_t instance) { DEV_ASSERT(instance < RTC_INSTANCE_COUNT); uint32_t tempSeconds; /* Get the alarm configuration */ rtc_alarm_config_t *alarmConfig = g_rtcRuntimeConfig[instance].alarmConfig; /* Get the fault interrupt configuration */ const rtc_overflow_config_t *const overflowConfig = g_rtcRuntimeConfig[instance].overflowConfig; /* Check if an alarm has occurred */ if (RTC_GetTimeAlarmFlag(g_rtcBase[instance]) == true) { /* If the alarm interrupt configuration has been defined process the * alarm IRQ */ if ((alarmConfig != NULL)) { /* If recurrence is enabled modify the alarm register to the next * alarm. */ if ((alarmConfig->numberOfRepeats > 0UL) || (alarmConfig->repeatForever == true)) { /* Get current time */ tempSeconds = RTC_GetTimeSecondsRegister(g_rtcBase[instance]); /* Current time is incremented with the repetition value */ tempSeconds += alarmConfig->repetitionInterval - 1UL; /* Set new value to trigger the alarm */ RTC_SetTimeAlarmRegister(g_rtcBase[instance], tempSeconds); g_rtcRuntimeConfig[instance].isAlarmTimeNew = true; /* If the alarm repeats forever, set number of repeats to 0 * to avoid an accidental trigger of the core overflow flag */ alarmConfig->numberOfRepeats = (alarmConfig->repeatForever == false) ? (alarmConfig->numberOfRepeats - 1UL) : 0UL; } else { /* If the alarm does not repeat, write 0 to ALM to clear the * alarm flag. */ RTC_SetTimeAlarmRegister(g_rtcBase[instance], 0UL); /* Set the internal variable which indicates that a new alarm is enabled to false */ g_rtcRuntimeConfig[instance].isAlarmTimeNew = false; } /* If the user has defined a callback, call it */ if (alarmConfig->rtcAlarmCallback != NULL) { alarmConfig->rtcAlarmCallback(alarmConfig->callbackParams); } } // 这里else 分支没有处理 } /* If the IRQ is not caused by the alarm then call the user callback if * defined. */ else if (overflowConfig != NULL) { if (overflowConfig->rtcOverflowCallback != NULL) { /* Call the RTC interrupt callback function with callback parameter */ overflowConfig->rtcOverflowCallback(overflowConfig->callbackParams); } } else { /* Do nothing*/ } }修复方案:
补充else分支,清除RTC闹钟diff --git a/platform/drivers/src/rtc/rtc_driver.c b/platform/drivers/src/rtc/rtc_driver.c index 439a400..512f49a 100644 --- a/platform/drivers/src/rtc/rtc_driver.c +++ b/platform/drivers/src/rtc/rtc_driver.c @@ -736,6 +736,14 @@ void RTC_DRV_IRQHandler(uint32_t instance) { alarmConfig->rtcAlarmCallback(alarmConfig->callbackParams); } + } else + { + /* If the alarm interrupt configuration is NULL (it may happen if the + * alarm is not arrived but the chip has been reset by any reason), + * So we should write 0 to ALM to clear the alarm flag */ + RTC_SetTimeAlarmRegister(g_rtcBase[instance], 0UL); + /* Set the internal variable which indicates that a new alarm is enabled to false */ + g_rtcRuntimeConfig[instance].isAlarmTimeNew = false; } } /* If the IRQ is not caused by the alarm then call the user callback if
快速上手云途开发生态
发帖前请查看
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...
