Thanks to visit codestin.com
Credit goes to github.com

Skip to content

STM32F1: RTC does not advance date when running from VBAT for long periods of time #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ArrestedLightning opened this issue Jan 22, 2023 · 3 comments · Fixed by #89
Closed
Labels
bug 🐛 Something isn't working
Milestone

Comments

@ArrestedLightning
Copy link

I am working on a project based on the STM32F1 and have found an issue with this library. I am using a custom board which should be equivalent to a blue pill board for the purposes of this issue. (32.768KHz RTC oscillator, 8MHz main oscillator, 3V CR2032 attached to the VBAT pin, USB-TTL serial adapter on pins PA9 and PA10.)
If the board is powered down (i.e. only VBAT is present) when the clock rolls over from 23:59 to 00:00, the time will be correct when main power is reapplied to the board, but the date will not advance if the power is off for more than hour.

I have created a short Arduino sketch which demonstrates the issue:

#include <STM32RTC.h>
STM32RTC& rtc = STM32RTC::getInstance();

HardwareSerial Serial1(PA10, PA9);

const byte seconds = 0;
const byte minutes = 58;
const byte hours = 23;
const byte weekDay = 1;
const byte day = 1;
const byte month = 1;
const byte year = 23;

void setup()
{
  pinMode(PB0, INPUT_PULLUP);
  Serial1.begin(115200);
  rtc.setClockSource(STM32RTC::LSE_CLOCK);
  rtc.begin(STM32RTC::HOUR_24); // initialize RTC 24H format
  
  Serial1.println("---------------------------------------------------------------"); 
  
  if (digitalRead(PB0) == 0) {
    rtc.setTime(hours, minutes, seconds);
    rtc.setDate(weekDay, day, month, year);
    Serial1.printf("RTC reset to %d:%d:%d %d-%d-%d\n", hours, minutes, seconds, year, month, day);
  }
}

void loop()
{
  Serial1.printf("%02d-%02d-%02d ", rtc.getYear(), rtc.getMonth(), rtc.getDay());
  Serial1.printf("%02d:%02d:%02d.%03d\n", rtc.getHours(), rtc.getMinutes(), rtc.getSeconds(), rtc.getSubSeconds());
  delay(1000);
}

To demonstrate the issue, power on the board with pin B0 shorted to ground, then power it off and wait 10 minutes. When it is powered on again, it will print out the following:

---------------------------------------------------------------
23-01-02 00:10:01.000
23-01-02 00:10:02.000

Note that both the date and time have advanced, as expected.

Then repeat the process: power on the board with pin B0 shorted to ground, then power it off and wait 70 minutes. When it is powered on again, it will print out the following:

---------------------------------------------------------------
23-01-01 01:10:48.000
23-01-01 01:10:49.000

In this case, the time has advanced as expected, but the date has not. Leaving the device powered off for longer periods of time will produce similar results.

As I understand it, the STM32F1 does not have a hardware calendar, so the RTC is just used as a flat seconds counter that (when the CPU is running) is reset every 86400 seconds. Since it is a 32-bit register, there is no technical reason that it couldn't handle more than one day's worth of time, assuming the logic was implemented to support this.

Looking into how the library is implemented, I see that RTC_SetDate is used to set the date from backup RAM when the RTC is initialized:

STM32RTC/src/rtc.c

Lines 487 to 490 in 58da1ed

memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4);
/* and fill the new RTC Date value */
RTC_SetDate(RtcHandle.DateToUpdate.Year, RtcHandle.DateToUpdate.Month,
RtcHandle.DateToUpdate.Date, RtcHandle.DateToUpdate.WeekDay);

RTC_SetDate does not contain any logic to handle advancing the date, though, and in fact intentionally subtracts out any accumulated days:
https://github.com/STMicroelectronics/STM32CubeF1/blob/2976d3b5b5cd1178ece18546e697c497c29d9c14/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c#L962-L969

However, the logic to advance the date based on accumulated counter time does in fact already exist, in the HAL_RTC_GetTime and RTC_DateUpdate functions:
https://github.com/STMicroelectronics/STM32CubeF1/blob/2976d3b5b5cd1178ece18546e697c497c29d9c14/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c#L825-L832
https://github.com/STMicroelectronics/STM32CubeF1/blob/2976d3b5b5cd1178ece18546e697c497c29d9c14/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c#L882

This function even pulls in the backup date from the RtcHandle structure. It seems a little strange to use the GetTime function to actually set the date, but it does not seem to have any other side effects.

I have experimented with replacing the RTC_SetDate call with HAL_RTC_GetTime in the RTC_Init function, and in my testing have found that it appears to resolve the issue, at least for my application. The date is advanced correctly even after being powered off for several days.

https://github.com/ArrestedLightning/STM32RTC/blob/7243392c9bd14c40b534ab96ac5cb333a4cf2909/src/rtc.c#L487-L490

However, I am not sure if there may be other side effects due to this change, or additional changes required for other code paths that I'm not using; someone who is more familiar with the code base would have to comment on that.

@fpistm
Copy link
Member

fpistm commented Jan 23, 2023

Hi,
I will deep into this and get you informed.
My first guess is that it misses one step after date restoration.
https://github.com/STMicroelectronics/STM32CubeF1/blob/2976d3b5b5cd1178ece18546e697c497c29d9c14/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c#L61C7-L63

fpistm added a commit to fpistm/STM32RTC that referenced this issue Jan 24, 2023
Fixes stm32duino#87

Signed-off-by: Frederic Pillon <[email protected]>
@fpistm
Copy link
Member

fpistm commented Jan 24, 2023

Hi @ArrestedLightning,

Thanks for the detailed description, I've reviewed the code and agreed with you. I've made a PR to fix this.
Let me know if it is ok for you.

@fpistm fpistm added the bug label Jan 25, 2023
@fpistm fpistm added this to the 1.3.6 milestone Jan 25, 2023
@fpistm
Copy link
Member

fpistm commented Jan 25, 2023

I've made a test with a Nucleo F103RB and it works as expected, wait 110min :

---------------------------------------------------------------
RTC reset to 23:58:0 23-1-1
23-01-01 23:58:00.000
23-01-01 23:58:00.000
23-01-01 23:58:01.000
23-01-01 23:58:02.000
23-01-01 23:58:03.000
23-01-01 23:58:04.000
23-01-01 23:58:05.000
23-01-01 23:58:06.000
23-01-01 23:58:07.000
23-01-02 01:48:27.000
23-01-02 01:48:28.000
23-01-02 01:48:29.000
23-01-02 01:48:30.000
23-01-02 01:48:31.000

@fpistm fpistm closed this as completed in fdebabc Jan 25, 2023
@fpistm fpistm added bug 🐛 Something isn't working and removed bug labels Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants