cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H755 - RTC->SSR & RTC->SHIFTR

ravo
Senior

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
}

 

 

 

14 REPLIES 14
ravo
Senior

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...

ravo_0-1733855830347.png

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.

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

 

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:

ravo_1-1733988728241.png

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. 

ravo_0-1733991635352.png

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

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

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