2025-03-10 7:36 PM
Hi all,
I'd like to use the RTC as a keeper of real-world clock. It would get synchronized with a (S)NTP server once a day. The RTC would get queried multiple times a day for the current time. The main challenge is that I'd like the timestamps to have a resolution of about 1ms. This should be possible according to the manual, but I'm not sure how to utilize the HAL to do so (if it's even supported by the HAL). When reading some HAL functions, it's mentioned that HAL_RTC_SetTime doesn't set the sub-seconds register.
Is it correct to assume I'll need to use the low-level drivers to implement this functionality?
Thanks
2025-03-10 7:44 PM
The sub-seconds register is not directly writeable.
After writing date/time, you can use the RTC->SHIFTR register to add/subtract fractions of a second from the current time. The function HAL_RTCEx_SetSynchroShift does this.
No low level calls necessary.
2025-03-10 8:06 PM
Thank you, TDK, that is a relief to hear. I'll try it out.
Another confusing thing with regards to RTC and sub-seconds is the relation between the synchronous predivider (PREDIV_S) and the update frequency of the RTC.
By default, when:
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
Then if I set an initial time of 0:
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
And query the time every 5 seconds, I get the expected result of seeing the seconds counter increase by 5.
while(1) {
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
printf("%02d:%02d:%02d\r\n",sTime.Hours, sTime.Minutes, sTime.Seconds);
HAL_Delay(5000);
}
However, according to the manual, the PREDIV_S value must be updated in order to control the precision of the sub-seconds register. So when I increased it to 16383 (to support a resolution of 60us, for example), I noticed that the seconds counter reported in my test above has incremented at a significantly lower rate.
Is it possible to set PREDIV_S/A so that the counter keeps running as normal, but I can still do reads at sub-second resolution?
2025-03-10 8:53 PM
The prescalers must be changed so that the CK_SPRE happens at 1 Hz.
If you are using a 32.768 kHz clock, then you must have (PREDIV_A + 1) * (PREDIV_S + 1) = 32768. So increase one and decrease the other. PREDIV_S is not an independent knob to adjust precision.
2025-03-11 6:20 AM
Thanks again for this information. Yes, I read that in the reference manual, however, it is still unclear to me how everything ties up together: fCK_SPRE, fCK_APRE, and how the RTC advances its internal hour/minute/seconds counters.
Is there a configuration that would allow the RTC to advance the "seconds" register every 1 second, while still keeping the SSR register moving at a resolution that allows, say 0.25ms accuracy (PREDIV_S set to 4095)?
Based on your comment, it looks like the answer is "no".
My intended use case is to get NTP packets with 32 bits of unix time (number of seconds since 1970), and 32 bits of fraction of a second. I'm hoping to somehow store this in the RTC so that it can keep track of this with a desired sub-second resolution. All I need for the RTC is to produce a current timestamp when I ask for it, but it doesn't need to be in human-readable format.
Perhaps the RTC isn't the right peripheral for this?
2025-03-11 6:25 AM
> Is there a configuration that would allow the RTC to advance the "seconds" register every 1 second, while still keeping the SSR register moving at a resolution that allows, say 0.25ms accuracy (PREDIV_S set to 4095)?
Well, from my post, I said you need to have (PREDIV_A + 1) * (PREDIV_S + 1) = 32768 if your clock is 32.768 kHz.
If you want PREDIV_S = 4095, then let's do the math here:
(PREDIV_A + 1) * (4095 + 1) = 32768
PREDIV_A + 1 = 32768 / 4096 = 8
PREDIV_A = 7
So yes, you can have PREDIV_S = 4095 and PREDIV_A = 7.