2025-05-28 4:58 AM
I’m working with an STM32-based system where the RTC is running on the internal LSI. My goal is to maintain reasonable time accuracy (within a few seconds) while periodically receiving the correct world time over an external communication interface.
To do this, I preset the expected LSI frequency and continuously calibrate it based on time updates I receive. This logic seems to be working well. However, I'm encountering an issue where the RTC alarm interrupt triggers unexpectedly after modifying the `PRER` (prescaler) register — even though the alarm is configured to trigger only once per minute.
Below is the code I'm using to adjust the `PRER` value (executed from within the RTC alarm IRQ):
hrtc.State = HAL_RTC_STATE_BUSY;
__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
status = RTC_EnterInitMode(&hrtc);
if (status == HAL_OK) {
hrtc.Instance->PRER = synchPrediv;
hrtc.Instance->PRER |= (asynchPrediv << RTC_PRER_PREDIV_A_Pos);
print("[RTC] - DR:%08X, TR:%08X\n", (hrtc.Instance->DR), (hrtc.Instance->TR));
status = RTC_ExitInitMode(&hrtc);
}
__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);
if (status == HAL_OK) {
hrtc.State = HAL_RTC_STATE_READY;
}
Here is an example of the logs observed during runtime:
```
13:23:59.063303 [RTC] - Intended 32513(60|532) freq. corrected to 34138(100|337) to drop 3 difference.
13:23:59.063511 [RTC] - DR:00252528, TR:00132400
13:23:59.063854 [Time] - System date/time: 2025-05-28 13:24:00
13:24:00.109324 [RTC] - freq. set to 32513(60|532).
13:24:00.109532 [RTC] - DR:00252528, TR:00132400
13:24:00.109614 [Time] - System date/time: 2025-05-28 13:24:00
13:24:01.106327 [Time] - System date/time: 2025-05-28 13:24:00
```
Context:
Expected behavior:
time catch period enter → ~1 minute later → time catch period exit → 1 minute later → simple IRQ→ 1 minute later → simple IRQ→ ....
Actual behavior:
Sometimes, two or all three trigger within the same second or a few seconds of each other. Apart IRQ's which modifies PRER - no such behavior is observed.
My Question:
What could be causing the RTC alarm to behave unpredictably or trigger early after modifying PRER?
Is it possible that modifying PRER causes an internal resynchronization that affects the alarm trigger logic?
Any insights or similar experiences are greatly appreciated.
Thank you in advance,
Laurynas
2025-05-28 6:01 AM
PRER can only be modified during initialization. It is not meant to be modified on the fly. The RM requires you to set PRER and DR/TR during initialization.
When reading RTC, you must read DR last.
2025-05-28 6:58 AM
According to RM0454 `23.6.5 RTC prescaler register (RTC_PRER)` - `PRER` and `DR`/`TR` have no relation, or I fail to find one where that relation is stated. Also it is not being done in their HAL driver.
...
/* Check whether the calendar needs to be initialized */
if (__HAL_RTC_IS_CALENDAR_INITIALIZED(hrtc) == 0U)
{
/* Disable the write protection for RTC registers */
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
/* Enter Initialization mode */
status = RTC_EnterInitMode(hrtc);
if(status == HAL_OK)
{
/* Clear RTC_CR FMT, OSEL and POL Bits */
hrtc->Instance->CR &= ~(RTC_CR_FMT | RTC_CR_POL | RTC_CR_OSEL | RTC_CR_TAMPOE);
/* Set RTC_CR register */
hrtc->Instance->CR |= (hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity);
/* Configure the RTC PRER */
hrtc->Instance->PRER = (hrtc->Init.SynchPrediv);
hrtc->Instance->PRER |= (hrtc->Init.AsynchPrediv << RTC_PRER_PREDIV_A_Pos);
/* Exit Initialization mode */
status = RTC_ExitInitMode(hrtc);
}
if (status == HAL_OK)
{
hrtc->Instance->CR &= ~(RTC_CR_TAMPALRM_PU |RTC_CR_TAMPALRM_TYPE | RTC_CR_OUT2EN);
hrtc->Instance->CR |= (hrtc->Init.OutPutPullUp | hrtc->Init.OutPutType | hrtc->Init.OutPutRemap);
}
/* Enable the write protection for RTC registers */
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
}
...
And in my approach I'm reusing same logic - just dropping `CR` modification as I do not need it and I assume it should not cause issues.
And yes I understand it is not meant to be done this way - tho I assume it should work. And it mostly does, just somewhere it acts not as I would expect time to time.