2024-12-03 4:00 PM
Dears, I have issues with setting RTC shift register.
I have setup RTC with AsynchPrediv = 127 & SynchPrediv = 255 and is working normally.
I tried to periodically setting RTC->SHIFTR with value 100 each 5 secs. Then wait for the shift operation to complete and immediately I read SS back using register RTC->SSR register. But RTC->SSR provide "random values" in PREDIV_S range (0 - 255). I expect that it should be lower than 100 but close (not higher)
Where could be problem ?
Thanks in advance
Radim
Example code:
int main(void)
{
unsigned this_ssr, tick, tr, dr;
reset_backup_domain();
...
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_RTC_Init();
...
// Turn on shadow registers to speed up RTC operations
HAL_RTCEx_EnableBypassShadow(&hrtc);
...
while(1)
{
__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
HAL_PWR_EnableBkUpAccess();
RTC->SHIFTR = 100; // test value
// Wait for the shift operation to complete
while ((hrtc.Instance->ISR & RTC_ISR_SHPF) != 0) {}
HAL_PWR_DisableBkUpAccess();
__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);
/* Read all 3 registers. */
this_ssr = READ_REG(RTC->SSR);
tr = READ_REG(RTC->TR);
dr = READ_REG(RTC->DR);
HAL_Delay(5000); // wait cca 5 sec
}
Solved! Go to Solution.
2024-12-10 10:58 AM - edited 2024-12-10 10:59 AM
Please apologise me, maybe I'm mixing two things together which are not related. I just remember one my older issue with calibration output, when I start playing with RTC clock on STM32. When in MX Cube select calibration output 1Hz and then observe that there is no 1Hz. But It depends on correct value of async and sync prescallers. as noted in TRM manual. But now I don't play with calibration...
So now I am doing only RTC time setting and syncing with SNTP protocol. I am using middleware LWIP + SNTP addon without FreeRTOS as standalone.
Simply periodically I send and receive sntp packet. Here is "simplified pseudo code" I get 4 timestamps:
T1,T2,T3, T4
do some calculation and converting them to UNIX time in usec
request_offset = T2 - T1; // client->server
response_offset = T4 - T3; // server->client
delta = (T4 - T1) - (T3- T2);
theta = ((T2 - T1) + (T3 - T4)) / 2;
T4_new = T4 += theta; // new T4 timestamps which I would like write to RTC with msec precision.
I setup RTC time & date from T4_new timestamp
{
SNTP_TimestampToDate(timestamp, &date);
SNTP_TimestampToTime(timestamp, &time);
HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN);
HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN);
}
And with remaining msec
RTC_msec = (remaining miliseconds in last second in T4_new )
subsecond_shift = hrtc.Init.SynchPrediv - RTC_msec * ( hrtc.Init.SynchPrediv + 1) / 1000;
HAL_RTCEx_SetSynchroShift(&hrtc, RTC_SHIFTADD1S_RESET, subsecond_shift );
and if I have RTC clocked from LSE it is working good with about 3-5 msec noise
But with HSE I have these issues.
2024-12-11 1:15 AM
OK I see. And, just to be sure, the HSE_25MHz.txt file you've posted above are results taken *without* the feedback/correction, i.e. the time read out from RTC is only compared to NTP time, RTC is not set from NTP time (except for the first time), correct?
How do you read out the current time from RTC and convert it to milliseconds, exactly? What are the bus clocks frequencies in relationship to RTC clock frequency?
Could you try to use a higher divider (e.g. 50) to make sure the RTC clock is below 1MHz?
JW
2024-12-11 11:38 PM - edited 2024-12-12 12:24 AM
Thanks for theese suggestions,
>>> RTC is not set from NTP time (except for the first time), correct?
Yeas exactly I do this way... but logs look quite different that for LSE (there was cumulative msec_diff)
So I tried to change 25 -> 50 divider PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV50;
So now RTC clock input should be lowered to 500 kHz and with ASYNC = 49 and SYNC = 9999 prescallers I still get msec_diff 156; 598; 22; 472; 919; 371; 816; 730; 643; ... so it did not still helped:
Update: For comparsion when RTC is working from LSE with same prerequisites (only one time set RTC without SHIFTR correction) so first diff is 817msec. And in this option it works as expected.
But I must have working HSE :( So I will focus now why the msec_diff does not contain only increasing values. There must be something wrong there.
Regards
Radim
2024-12-14 4:36 AM
How do you read out the current time from RTC and convert it to milliseconds, exactly?
What are the bus clocks frequencies in relationship to RTC clock frequency?
JW
2025-03-11 12:36 AM - edited 2025-03-11 12:56 AM
Dear Jan,
I am sorry for long time. I was busy with other projects.
It was hard to find and localise problem, due the time is still running, and especially in usec/msec resolution
I already solved the issues by myself. I found problem in convert LocalDateTimeToSNTP:
void LocalDateTimeToSNTP(SNTP_Timestamp *sntp_time, RTC_DateTypeDef *rtc_date, RTC_TimeTypeDef *rtc_time){
struct tm datetime = {0};
//not Y2.1K compliant:
datetime.tm_year = rtc_date->Year + 2000;
datetime.tm_mon = rtc_date->Month - 1;
datetime.tm_mday = rtc_date->Date;
datetime.tm_hour = rtc_time->Hours;
datetime.tm_min = rtc_time->Minutes;
datetime.tm_sec = rtc_time->Seconds;
time_t unixDate = mktime(&datetime) - TIME_H_DIFF;
sntp_time->seconds = unixDate + SNTP_UNIX_TIMESTAMP_DIFF;
sntp_time->seconds_fraction = (255 - rtc_time->SubSeconds) << 24;
}
I found that I don't properly adopt/edit code which was originally based on https://github.com/ignacygrudzinski/STM32_SNTP
And this is not so "clean" calculation for time from fraction. There was hidden 8 bit division (shifted only 24 instead of originally 32 bits)
It was due sync_prescaler was originally 255 for LSE and I have 25 MHz external clock and setup sync_prescaler to 9999 for HSE clock. But calculation was using "fixed numbers".
sntp_time->seconds_fraction = (255 - rtc_time->SubSeconds) << 24; // only works for SecondFraction is 255
I correct using bellow formula and now it is working as expected (e.g rtc_time->SecondFraction instead 255)
sntp_time->seconds_fraction = (uint32_t)(((uint64_t)rtc_time->SecondFraction- rtc_time->SubSeconds) << 32) / rtc_time->SecondFraction+ 1));
Now all works good.
Thanks once more for your time, and all suggestions which was helped me.
Radim