Skip to content

Commit 2954603

Browse files
authored
Merge pull request #58 from FRASTM/f1_bkup_date
Adds date retention in the backup memory for the stm32f1xx
2 parents 66f42fa + 0f402ca commit 2954603

File tree

4 files changed

+172
-2
lines changed

4 files changed

+172
-2
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ _One-Second interrupt_
113113
* **`void detachSecondsInterrupt(void)`**
114114

115115

116+
_Date retention for stm32F1xx_
117+
118+
STM32 RTC includes date save/retrieve mechanism for the stm32F1xx mcu, that do not have a date counter.
119+
120+
The content is stored in BackUp memory which is kept during Reset and powered by Vbat when the Vdd is off.
121+
116122

117123
### Since STM32 Core version > 1.5.0
118124
_Reset time management_
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
F1RTCDateRetention
3+
4+
This sketch shows how to keep the RTC date with backup registers on a stm32F1 MCU.
5+
It is reserved for stm32F1 as other devices actually embed the feature.
6+
If a VBat is present on the target board, then the content is kept when
7+
the VDD power supply is off, else the content is reset
8+
9+
Creation 03 dec 2021
10+
by FRASTM for STMicroelectronics
11+
12+
This example code is in the public domain.
13+
14+
https://github.com/stm32duino/STM32RTC
15+
*/
16+
17+
#include <STM32RTC.h>
18+
19+
/* Get the rtc object */
20+
STM32RTC& rtc = STM32RTC::getInstance();
21+
22+
#if !defined(STM32F1xx)
23+
#error "Not applicable (only stm32F1xx save date in backup memory)"
24+
#endif /* !STM32F1xx */
25+
26+
#define INITIAL_SEC 53
27+
#define INITIAL_MIN 59
28+
#define INITIAL_HOUR 23
29+
#define INITIAL_WDAY 2
30+
#define INITIAL_DAY 7
31+
#define INITIAL_MONTH 12
32+
#define INITIAL_YEAR 21
33+
34+
uint32_t subSec;
35+
byte seconds;
36+
byte minutes;
37+
byte hours;
38+
byte am_pm;
39+
40+
/* these values are read in the backUp register */
41+
byte weekDay;
42+
byte day;
43+
byte month;
44+
byte year;
45+
46+
void setup()
47+
{
48+
Serial.begin(115200);
49+
50+
// Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
51+
// By default the LSI is selected as source.
52+
//rtc.setClockSource(STM32RTC::LSE_CLOCK);
53+
54+
// true: reset the backUp register (restart from the initial date/time above on each reset)
55+
// false: keep the latest date from the BackUp register on each reset
56+
bool reset_bkup = false;
57+
rtc.begin(reset_bkup); // initialize RTC 24H format
58+
// get the date if stored in BackUp reg
59+
rtc.getDate(&weekDay, &day, &month, &year);
60+
if (reset_bkup) {
61+
Serial.printf("reset the date to %02d/%02d/%02d\n", day, month, year);
62+
} else {
63+
Serial.printf("date from the BackUp %02d/%02d/%02d\n", day, month, year);
64+
}
65+
66+
// Check if date is valid = read in the backUp reg.
67+
// Note that backup reg only keep the date /time
68+
// and a power off reset the content if not saved by Vbat
69+
// HAL_RTC init date is set to 1st of January 2000
70+
if ((day == 1) && (month == RTC_MONTH_JANUARY) && (year == 0)) {
71+
// Set the time
72+
rtc.setHours(INITIAL_HOUR);
73+
rtc.setMinutes(INITIAL_MIN);
74+
rtc.setSeconds(INITIAL_SEC);
75+
76+
// Set the date
77+
rtc.setWeekDay(INITIAL_WDAY);
78+
rtc.setDay(INITIAL_DAY);
79+
rtc.setMonth(INITIAL_MONTH);
80+
rtc.setYear(INITIAL_YEAR);
81+
82+
// Here you can also use
83+
//rtc.setTime(hours, minutes, seconds);
84+
//rtc.setDate(weekDay, day, month, year);
85+
}
86+
}
87+
88+
void loop()
89+
{
90+
// Print date...
91+
Serial.printf("%02d/%02d/%02d \t", rtc.getDay(), rtc.getMonth(), rtc.getYear());
92+
93+
uint8_t sec = 0;
94+
uint8_t mn = 0;
95+
uint8_t hrs = 0;
96+
uint32_t subs = 0;
97+
rtc.getTime(&hrs, &mn, &sec, &subs);
98+
99+
// ...and time
100+
Serial.printf("%02d:%02d:%02d\n", hrs, mn, sec);
101+
102+
delay(1000);
103+
}

src/rtc.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
*/
3636

3737
#include "rtc.h"
38+
#include <string.h>
3839

3940
#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01090000) &&\
4041
defined(HAL_RTC_MODULE_ENABLED) && !defined(HAL_RTC_MODULE_ONLY)
@@ -367,17 +368,36 @@ void RTC_init(hourFormat_t format, sourceClock_t source, bool reset)
367368
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
368369
#endif /* STM32F1xx */
369370

371+
/* Ensure backup domain is enabled before we init the RTC so we can use the backup registers for date retention on stm32f1xx baords */
372+
enableBackupDomain();
373+
370374
HAL_RTC_Init(&RtcHandle);
371375

376+
#if defined(STM32F1xx)
377+
// Copy RTC date back out of the BackUp registers
378+
uint32_t BackupDate;
379+
/* date from backup battery was not reset, load it */
380+
if (!reset) {
381+
BackupDate = getBackupRegister(RTC_BKP_DATE) << 16;
382+
BackupDate |= getBackupRegister(RTC_BKP_DATE + 1) & 0xFFFF;
383+
if (BackupDate != 0) {
384+
/* cannot force the date to be 0 but 1/1/2000 is the reset value, always */
385+
memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4);
386+
/* and fill the new RTC Date value */
387+
RTC_SetDate(RtcHandle.DateToUpdate.Year, RtcHandle.DateToUpdate.Month,
388+
RtcHandle.DateToUpdate.Date, RtcHandle.DateToUpdate.WeekDay);
389+
}
390+
}
391+
RTC_StoreDate();
392+
#endif /* STM32F1xx */
393+
372394
#if defined(RTC_CR_BYPSHAD)
373395
/* Enable Direct Read of the calendar registers (not through Shadow) */
374396
HAL_RTCEx_EnableBypassShadow(&RtcHandle);
375397
#endif
376398

377399
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO);
378400
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
379-
/* Ensure backup domain is enabled */
380-
enableBackupDomain();
381401
}
382402

383403
/**
@@ -460,6 +480,12 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s
460480
RTC_TimeTypeDef RTC_TimeStruct;
461481

462482
if ((hours != NULL) && (minutes != NULL) && (seconds != NULL)) {
483+
#if defined(STM32F1xx)
484+
/* Store the date prior to checking the time, this may roll over to the next day as part of the time check,
485+
we need to the new date details in the backup registers if it changes */
486+
uint8_t current_date = RtcHandle.DateToUpdate.Date;
487+
#endif
488+
463489
HAL_RTC_GetTime(&RtcHandle, &RTC_TimeStruct, RTC_FORMAT_BIN);
464490
*hours = RTC_TimeStruct.Hours;
465491
*minutes = RTC_TimeStruct.Minutes;
@@ -482,6 +508,10 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s
482508
#else
483509
UNUSED(period);
484510
UNUSED(subSeconds);
511+
512+
if (current_date != RtcHandle.DateToUpdate.Date) {
513+
RTC_StoreDate();
514+
}
485515
#endif /* !STM32F1xx */
486516
}
487517
}
@@ -505,6 +535,9 @@ void RTC_SetDate(uint8_t year, uint8_t month, uint8_t day, uint8_t wday)
505535
RTC_DateStruct.WeekDay = wday;
506536
HAL_RTC_SetDate(&RtcHandle, &RTC_DateStruct, RTC_FORMAT_BIN);
507537
setBackupRegister(RTC_BKP_INDEX, RTC_BKP_VALUE);
538+
#if defined(STM32F1xx)
539+
RTC_StoreDate();
540+
#endif /* STM32F1xx */
508541
}
509542
}
510543

@@ -526,6 +559,9 @@ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday)
526559
*month = RTC_DateStruct.Month;
527560
*day = RTC_DateStruct.Date;
528561
*wday = RTC_DateStruct.WeekDay;
562+
#if defined(STM32F1xx)
563+
RTC_StoreDate();
564+
#endif /* STM32F1xx */
529565
}
530566
}
531567

@@ -834,6 +870,17 @@ void RTC_WKUP_IRQHandler(void)
834870
#endif /* STM32F1xx */
835871
#endif /* ONESECOND_IRQn */
836872

873+
#if defined(STM32F1xx)
874+
void RTC_StoreDate(void)
875+
{
876+
/* Store the date in the backup registers */
877+
uint32_t dateToStore;
878+
memcpy(&dateToStore, &RtcHandle.DateToUpdate, 4);
879+
setBackupRegister(RTC_BKP_DATE, dateToStore >> 16);
880+
setBackupRegister(RTC_BKP_DATE + 1, dateToStore & 0xffff);
881+
}
882+
#endif
883+
837884
#ifdef __cplusplus
838885
}
839886
#endif

src/rtc.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ typedef enum {
7777
typedef void(*voidCallbackPtr)(void *);
7878

7979
/* Exported constants --------------------------------------------------------*/
80+
81+
#if defined(STM32F1xx)
82+
/* select 32 bits in backup memory to store date.
83+
2 consecutive 16bit reg. are reserved: RTC_BKP_DATE & RTC_BKP_DATE + 1 */
84+
#if !defined(RTC_BKP_DATE)
85+
/* can be changed for your convenience (here : LL_RTC_BKP_DR6 & LL_RTC_BKP_DR7) */
86+
#define RTC_BKP_DATE LL_RTC_BKP_DR6
87+
#endif
88+
#endif /* STM32F1xx */
89+
8090
/* Interrupt priority */
8191
#ifndef RTC_IRQ_PRIO
8292
#define RTC_IRQ_PRIO 2
@@ -188,6 +198,10 @@ void attachSecondsIrqCallback(voidCallbackPtr func);
188198
void detachSecondsIrqCallback(void);
189199
#endif /* ONESECOND_IRQn */
190200

201+
#if defined(STM32F1xx)
202+
void RTC_StoreDate(void);
203+
#endif
204+
191205
#ifdef __cplusplus
192206
}
193207
#endif

0 commit comments

Comments
 (0)