Skip to main content
Visitor II
October 24, 2019
Question

Why an STM32L476's RTC counts more than 24h and don't icnreases the day

  • October 24, 2019
  • 21 replies
  • 9639 views

I've designed a board that has a STM32L476.

This part is supplied using a triple system of dual battery + power ( when it is available)

We've manufactured more than 20k units of them and they are working ok

A few days ago 2 boards came back to our design lab that exhibit the following symptoms :

-> The RTC keeps counting past 23:59:59 until 39:59:59

-> Neither on 23h nor 39h rollover the day gets increased

-> When trying to set the time we get the following data:

If the time is less than 20h, 20h get added to it

Else the hour is correctly set

-> Rollover behavior don't changes

If we force a reset of the CPU, the problem dissapears.

More data:

-> The RTC access is done using HAL libs.

-> The RTC isn't reset when setting the date/time

We still have one untouched board for testing, but any try to use a debugger would trigger a CPU reset, making the probblem dissapear. (This is why we lost ont of the boards )

Does anybody have a hint about what the problem could be ?

    This topic has been closed for replies.

    21 replies

    Visitor II
    December 14, 2022

    Faced the same issue and managed to find the solution.

    The problem is especially pronounced if you are using the init codes from HAL to initialise the RTC, because it basically skips updating the RTC_CR register in every init call after rebooting once the year value in the calendar is not 00 ...

    And to update the RTC_CR register, you have to stop the RTC momentarily, and follow the sequence below:

    1. __HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
    2. RTC_EnterInitMode(&hrtc);
    3. update RTC_CR by setting FMT to 0
    4. RTC_ExitInitMode(&hrtc);
    5. __HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);

    Hope it helps.

    albert2Author
    Visitor II
    December 14, 2022

    Hi again

    Just in case anybody has the same problem :

    The HAL lib doesen't mask the bit fields before writing the data to the RTC registers, so any stray 1s in the variables outside the defined fields will corrupt your RTC register's data.

    The solution is to make sure all your struct fields are zero before filling in the needed data for the update.

    Sorry not answering before, I though I had done it, really.

    Albert

    Visitor II
    January 29, 2023

    Hello @albert2​,

    Thanks for your tip! I am suffering with this issue as well.

    In my original code this was already done during struct declaration, but it runs only once:

    RTC_TimeTypeDef sTime = {0};

    RTC_DateTypeDef sDate = {0};

    Now I have to initialize all struct members before every update:

    sTime.Hours = 0;

    sTime.Minutes = 0;

    sTime.Seconds = 0;

    sTime.SubSeconds = 0;

    sTime.SecondFraction = 0;

    sTime.TimeFormat = 0;

    sTime.DayLightSaving = 0;

    sTime.StoreOperation = 0;

    HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD);

    sDate.WeekDay = 0;

    sDate.Month = 0;

    sDate.Date = 0;

    sDate.Year = 0;

    HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD);

    Do you think it is enough to solve the issue?

    Best regards,

    Iaran

    Super User
    January 29, 2023

    > In my original code this was already done during struct declaration, but it runs only once:

    >

    > RTC_TimeTypeDef sTime = {0};

    > RTC_DateTypeDef sDate = {0};

    If these variables are defined as *local*, they are automatically allocated on the stack, and also the initialization is performed, every time the given function is called. And this initialization is equivalent of assigning 0 to all members of the given struct.

    > Do you think it is enough to solve the issue?

    If those structs were local, as I wrote above, they were already cleared when the function was called. Without seeing your particular function it's hard to tell, but it's quite likely that you did not change anything and that the root of your problem is elsewhere.

    Start a new thread (perhaps giving a link to this one), stating what's your hardware, what is the problem, its symptoms and how do you observe them.

    JW

    Visitor II
    January 31, 2023

    How can we address this topic to the ST HAL development team? A correction could be implemented directly in the HAL code.

    I see there are other HAL structs, for ADC, UART, I2C... Is this initialization issue also present in those structs?

    Thank you,

    Iaran

    Super User
    February 1, 2023

    Root of the problem is, that users call the Cube/HAL functions with incorrectly set parameters (struct fields - having them as uninitialized local variables is only one way how they can be set incorrectly).

    I don't understand how could Cube/HAL fix something which is user error.

    JW

    Visitor II
    February 2, 2023

    It seems I misunderstood the answer from @albert2​, saying the "The HAL lib doesn't mask the bit fields before writing the data to the RTC registers".

    For me it was some HAL Lib problem.

    If the solution is just to initialize ALL struct members than it should be fine for my application now.

    Orinally, I was not using/not updating these two parameters: SubSeconds and SecondFraction.

    Do you think this could be the reason for the RTC hours counting going more than 24h?

    Thanks.

    EDITED: Just happened again. Today morning I see the hours showing 26! I still don´t get real root cause for this problem...

    Super User
    February 2, 2023

    > It seems I misunderstood the answer from @albert2 (Community Member)​, saying the "The HAL lib

    > doesn't mask the bit fields before writing the data to the RTC registers".

    > For me it was some HAL Lib problem.

    I am not really willing to discuss Cube/HAL issues, I don't use it and I think it's simply a waste of time.

    Nonetheless, masking bitfileds won't help with uninitialized struct fields as they may have unwanted ones (note, uninitialized means random content) at the places which are unmasked.

    > Just happened again. Today morning I see the hours showing 26!

    > I still don´t get real root cause for this problem...

    The very first thing to do when you encounter this sort of problems is to read out and check the RTC registers content.

    Then check all places where you write into RTC, whether all registers are written as intended. Note, that at this moment you should consider Cube/HAL code as your own and debug it as such.

    JW

    Graduate
    February 2, 2023

    For me, one of the more serious sources of the problem is the way in which CubeMX creates the code and how HAL examples are written in all the ST demos.

    This is an example of the error-prone ST style:

     GPIO_InitTypeDef GPIO_InitStruct = {0};
     
     /*Configure GPIO pin : CEC_CK_MCO1_Pin */
     GPIO_InitStruct.Pin = CEC_CK_MCO1_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
     HAL_GPIO_Init(CEC_CK_MCO1_GPIO_Port, &GPIO_InitStruct);

    And that's how it should be written to educate the users:

     static const GPIO_InitTypeDef GPIO_InitStruct = {
     /*Configure GPIO pin : CEC_CK_MCO1_Pin */
     .Pin = CEC_CK_MCO1_Pin,
     .Mode = GPIO_MODE_AF_PP,
     .Pull = GPIO_NOPULL,
     .Speed = GPIO_SPEED_FREQ_LOW,
     .Alternate = GPIO_AF0_MCO
    }
     HAL_GPIO_Init(CEC_CK_MCO1_GPIO_Port, &GPIO_InitStruct);

    This way:

    • init structure uses Flash, not RAM
    • all the non-initialized explicitly fields are guarateed to be 0

    There is one problem with this approach. Most of HAL creators don't understand the importance of const specifier in pointer-to-structure arguments, so most of HAL functions don't like constant arguments which they incorrectly believe to be variables. This is a well-known serious issue of HAL code.

    Visitor II
    March 29, 2023

    I have the same problem with a B-U585I-IOT board.

    Days never increase and hours keep increasing...

    Try all the above suggestions... none worked

    Something new ?

    thanks

    Visitor II
    March 29, 2023

    Sorry, this works:

    sDate.WeekDay = RTC_WEEKDAY_WEDNESDAY;
    sDate.Date = 31;
    sDate.Month = RTC_MONTH_DECEMBER;
    sDate.Year = 23;
     
    sTime.SubSeconds = 0;
    sTime.SecondFraction = 0;
    sTime.TimeFormat = RTC_FORMAT_BIN;
    sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    sTime.Hours = 23;
    sTime.Minutes = 59;
    sTime.Seconds = 55;
     
    __HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
    RTC_EnterInitMode(&hrtc);
    if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) {
    	printf("Error Setting Time !\n");
    }
    if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) {
     printf("Error Setting Date !\n");
    }
    RTC_ExitInitMode(&hrtc);
     __HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);
     
    HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, 0x1234); // Date & Time are set

    The day, month & year are incremented 5 seconds later

    Visitor II
    January 29, 2024
    void Set_RTC_Date_And_Time(Date_And_Time_Typedef *dt)
    {
    dt->Timeout_Counter = 0;
    Set_RTC_Time(&dt->The_Time);
    Set_RTC_Date(&dt->The_Date);
     
    __HAL_RTC_WRITEPROTECTION_DISABLE(rtc_ptr);
    RTC_EnterInitMode(rtc_ptr);
    rtc_ptr->Instance->CR = 0;//CR_Old & 0xFFFFFFDF;
    RTC_ExitInitMode(rtc_ptr);
    __HAL_RTC_WRITEPROTECTION_ENABLE(rtc_ptr);
     
     
    HAL_RTCEx_SetWakeUpTimer_IT(rtc_ptr, Calculate_WakeUp_Counter_Value(5000), RTC_WAKEUPCLOCK_RTCCLK_DIV16,0);//todo
    Set_RTC_Alarm_For_Next_Second(dt);
     
    }
    void Get_RTC_Date_And_Time(Date_And_Time_Typedef *dt)
    {
    Get_RTC_Time(&dt->The_Time);
    Get_RTC_Date(&dt->The_Date);
     
    dt->Raw_UnixTime = Date_Time_To_UnixTime(dt);
     
    // --------------------------------------------------------------------------------------------------------
    Update_Log_Time(dt->Raw_UnixTime);
    // --------------------------------------------------------------------------------------------------------
    static uint8_t second_1 = 0;
    static uint8_t hour_1 = 0;
     
    if(second_1 != dt->The_Time.Seconds)
    {
    second_1 = dt->The_Time.Seconds;
    sprintf(dt->Time_Str," %02u:%02u", dt->The_Time.Hours,dt->The_Time.Minutes);
    sprintf(dt->Time_Sec_Str," %02u", dt->The_Time.Seconds);
    }
    if(hour_1 != dt->The_Time.Hours)
    {
    hour_1 = dt->The_Time.Hours;
    sprintf(dt->Date_Day_Month_Str,"%02u-%02u", dt->The_Date.Date,dt->The_Date.Month);
    sprintf(dt->Date_Year_Str," 20%02u", dt->The_Date.Year);
    }
    }
    void Set_RTC_Date(RTC_DateTypeDef *sDate)
    {
    sDate->WeekDay = Get_Weekday_of_Date(sDate);
    if (HAL_RTC_SetDate(rtc_ptr, sDate, RTC_FORMAT_BIN) != HAL_OK)
    {
    //_Error_Handler(__FILE__, __LINE__);
    }
    }
    void Set_RTC_Time(RTC_TimeTypeDef *sTime)
    {
    sTime->DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sTime->SecondFraction = 0;
    sTime->SubSeconds = 0;
    sTime->TimeFormat = RTC_HOURFORMAT_24;
    sTime->StoreOperation = RTC_STOREOPERATION_RESET;
    if (HAL_RTC_SetTime(rtc_ptr, sTime, RTC_FORMAT_BIN) != HAL_OK)
    {
    //_Error_Handler(__FILE__, __LINE__);
    }
     
    }

    This code solved my problem. Basically, Set CR register 0, after setting the time and date, then restart your alarm or wakeup timer if you need to.
    Visitor II
    June 2, 2024

    Hi, I have solved this, replacing the following files by old version of the hal API from other project:

    Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h
    Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c
    Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c

    I only replacing, but we can see in git diff the differences

    BugFix-RTC-MoreThan24hs.PNG

     

    Super User
    June 3, 2024

    If you look at the definitions of the symbols you've replacing, you'd see the same values. Thus, this is not the reason of the "fix" which is quite likely concidental.

    I believe most of the problems in this thread are caused by uninitialized local structs used to set up the RTC or the time there.

    JW

    Visitor II
    June 5, 2024

    It wasn't just what's in the diff that changed, but all .c code, and for me it resolved.