Skip to content

Commit d9dc7ba

Browse files
ABOSTMfpistm
authored andcommitted
fix: ability to set alarm after reset
Be sure to set default value for alarmday, and thus avoid IS_RTC_DATE(day) being false when is not usd in alarm setting Take into account Reset usecase (being able to set new alarma after a reset) Factorize change of RTC clock source in the RTC_begin() function which imply a reset of BackupDomain. Save configuration before this BackupDomain reset, and restore after. fixes stm32duino#82 Signed-off-by: Alexandre Bourdiol <[email protected]>
1 parent f620b53 commit d9dc7ba

File tree

3 files changed

+107
-69
lines changed

3 files changed

+107
-69
lines changed

examples/F1RTCDateRetention/F1RTCDateRetention.ino

+3-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ void setup()
6666
// Check if date is valid = read in the backUp reg.
6767
// Note that backup reg only keep the date /time
6868
// 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)) {
69+
// Stm32duino RTC init date is set to 1st of January 2001
70+
// https://github.com/stm32duino/STM32RTC/blob/f620b534f7bffe24f031fc5935324027cfe51320/src/rtc.c#L395
71+
if ((day == 1) && (month == RTC_MONTH_JANUARY) && (year == 1)) {
7172
// Set the time
7273
rtc.setHours(INITIAL_HOUR);
7374
rtc.setMinutes(INITIAL_MIN);

src/STM32RTC.cpp

+11-40
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,26 @@ void STM32RTC::begin(bool resetTime, Hour_Format format)
6464
{
6565
bool reinit;
6666

67-
if (resetTime == true) {
68-
_timeSet = false;
69-
}
7067

7168
_format = format;
7269
reinit = RTC_init((format == HOUR_12) ? HOUR_FORMAT_12 : HOUR_FORMAT_24,
7370
(_clockSource == LSE_CLOCK) ? ::LSE_CLOCK :
7471
(_clockSource == HSE_CLOCK) ? ::HSE_CLOCK : ::LSI_CLOCK
7572
, resetTime);
73+
_timeSet = !reinit;
74+
75+
syncTime();
76+
syncDate();
7677

77-
if (reinit == true) {
78-
_timeSet = false;
79-
syncTime();
80-
syncDate();
81-
// Use current time to init alarm members
78+
if (!IS_RTC_DATE(_alarmDay)) {
79+
// Use current time to init alarm members,
80+
// specially in case _alarmDay is 0 (reset value) which is an invalid value
8281
_alarmDay = _day;
8382
_alarmHours = _hours;
8483
_alarmMinutes = _minutes;
8584
_alarmSeconds = _seconds;
8685
_alarmSubSeconds = _subSeconds;
8786
_alarmPeriod = _hoursPeriod;
88-
} else {
89-
_timeSet = true;
9087
}
9188
}
9289

@@ -927,38 +924,9 @@ void STM32RTC::configForLowPower(Source_Clock source)
927924
__HAL_RCC_RTCAPB_CLKAM_ENABLE();
928925
#endif
929926

927+
setClockSource(source);
930928
begin();
931929

932-
if (_clockSource != source) {
933-
// Save current config
934-
AM_PM period, alarmPeriod = _alarmPeriod;
935-
uint32_t subSeconds;
936-
uint8_t seconds, minutes, hours, weekDay, day, month, years;
937-
uint8_t alarmSeconds, alarmMinutes, alarmHours, alarmDay;
938-
Alarm_Match alarmMatch = _alarmMatch;
939-
940-
alarmDay = _alarmDay;
941-
alarmHours = _alarmHours;
942-
alarmMinutes = _alarmMinutes;
943-
alarmSeconds = _alarmSeconds;
944-
945-
getDate(&weekDay, &day, &month, &years);
946-
getTime(&seconds, &minutes, &hours, &subSeconds, &period);
947-
948-
end();
949-
_clockSource = source;
950-
// Enable RTC
951-
begin(_format);
952-
// Restore config
953-
setTime(seconds, minutes, hours, subSeconds, period);
954-
setDate(weekDay, day, month, years);
955-
setAlarmTime(alarmHours, alarmMinutes, alarmSeconds, alarmPeriod);
956-
setAlarmDay(alarmDay);
957-
if (RTC_IsAlarmSet()) {
958-
enableAlarm(alarmMatch);
959-
}
960-
}
961-
962930
if (!isTimeSet()) {
963931
// Set arbitrary time for Lowpower; if not already set
964932
setTime(12, 0, 0, 0, AM);
@@ -984,6 +952,9 @@ void STM32RTC::syncTime(void)
984952
void STM32RTC::syncDate(void)
985953
{
986954
RTC_GetDate(&_year, &_month, &_day, &_wday);
955+
#if defined(STM32F1xx)
956+
RTC_StoreDate();
957+
#endif /* STM32F1xx */
987958
}
988959

989960
/**

src/rtc.c

+93-27
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,6 @@ static void RTC_initClock(sourceClock_t source)
202202
} else {
203203
Error_Handler();
204204
}
205-
#ifdef __HAL_RCC_RTCAPB_CLK_ENABLE
206-
__HAL_RCC_RTCAPB_CLK_ENABLE();
207-
#endif
208-
__HAL_RCC_RTC_ENABLE();
209205
}
210206

211207
#if defined(STM32F1xx)
@@ -342,44 +338,47 @@ static void RTC_computePrediv(int8_t *asynch, int16_t *synch)
342338
bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset)
343339
{
344340
bool reinit = false;
341+
hourAM_PM_t period = HOUR_AM, alarmPeriod = HOUR_AM;
342+
uint32_t subSeconds = 0, alarmSubseconds = 0;
343+
uint8_t seconds = 0, minutes = 0, hours = 0, weekDay = 0, days = 0, month = 0, years = 0;
344+
uint8_t alarmMask = 0, alarmDay = 0, alarmHours = 0, alarmMinutes = 0, alarmSeconds = 0;
345+
bool isAlarmSet = false;
346+
#if defined(STM32F1xx)
347+
uint32_t asynch;
348+
#else
349+
int8_t asynch;
350+
int16_t sync;
351+
#endif
345352

346353
initFormat = format;
347-
348-
/* Init RTC clock */
349-
RTC_initClock(source);
350-
351354
RtcHandle.Instance = RTC;
352355

353356
/* Ensure backup domain is enabled before we init the RTC so we can use the backup registers for date retention on stm32f1xx boards */
354357
enableBackupDomain();
355358

356359
if (reset) {
357360
resetBackupDomain();
358-
RTC_initClock(source);
359361
}
360362

363+
#ifdef __HAL_RCC_RTCAPB_CLK_ENABLE
364+
__HAL_RCC_RTCAPB_CLK_ENABLE();
365+
#endif
366+
__HAL_RCC_RTC_ENABLE();
367+
368+
isAlarmSet = RTC_IsAlarmSet();
369+
361370
#if defined(STM32F1xx)
362371
uint32_t BackupDate;
363372
BackupDate = getBackupRegister(RTC_BKP_DATE) << 16;
364373
BackupDate |= getBackupRegister(RTC_BKP_DATE + 1) & 0xFFFF;
365374
if ((BackupDate == 0) || reset) {
375+
// RTC needs initialization
366376
/* Let HAL calculate the prescaler */
367377
RtcHandle.Init.AsynchPrediv = prediv;
368378
RtcHandle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
369-
HAL_RTC_Init(&RtcHandle);
370-
// Default: saturday 1st of January 2001
371-
// Note: year 2000 is invalid as it is the hardware reset value and doesn't raise INITS flag
372-
RTC_SetDate(1, 1, 1, 6);
373-
reinit = true;
374-
} else {
375-
memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4);
376-
/* and fill the new RTC Date value */
377-
RTC_SetDate(RtcHandle.DateToUpdate.Year, RtcHandle.DateToUpdate.Month,
378-
RtcHandle.DateToUpdate.Date, RtcHandle.DateToUpdate.WeekDay);
379-
}
380379
#else
381-
382380
if (!LL_RTC_IsActiveFlag_INITS(RtcHandle.Instance) || reset) {
381+
// RTC needs initialization
383382
RtcHandle.Init.HourFormat = format == HOUR_FORMAT_12 ? RTC_HOURFORMAT_12 : RTC_HOURFORMAT_24;
384383
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
385384
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
@@ -389,17 +388,87 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset)
389388
#endif /* RTC_OUTPUT_REMAP_NONE */
390389

391390
RTC_getPrediv((int8_t *) & (RtcHandle.Init.AsynchPrediv), (int16_t *) & (RtcHandle.Init.SynchPrediv));
391+
#endif // STM32F1xx
392+
// Init RTC clock
393+
RTC_initClock(source);
392394

393395
HAL_RTC_Init(&RtcHandle);
394396
// Default: saturday 1st of January 2001
395397
// Note: year 2000 is invalid as it is the hardware reset value and doesn't raise INITS flag
396398
RTC_SetDate(1, 1, 1, 6);
397399
reinit = true;
398400
} else {
399-
// This initialize variables: predivAsync, redivSync and predivSync_bits
400-
RTC_getPrediv(NULL, NULL);
401+
// RTC is already initialized
402+
uint32_t oldRtcClockSource = __HAL_RCC_GET_RTC_SOURCE();
403+
oldRtcClockSource = ((oldRtcClockSource == RCC_RTCCLKSOURCE_LSE) ? LSE_CLOCK :
404+
(oldRtcClockSource == RCC_RTCCLKSOURCE_LSI) ? LSI_CLOCK :
405+
#if defined(RCC_RTCCLKSOURCE_HSE_DIVX)
406+
(oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIVX) ? HSE_CLOCK :
407+
#elif defined(RCC_RTCCLKSOURCE_HSE_DIV32)
408+
(oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIV32) ? HSE_CLOCK :
409+
#elif defined(RCC_RTCCLKSOURCE_HSE_DIV)
410+
(oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIV) ? HSE_CLOCK :
411+
#elif defined(RCC_RTCCLKSOURCE_HSE_DIV128)
412+
(oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIV128) ? HSE_CLOCK :
413+
#endif
414+
// default case corresponding to no clock source
415+
0xFFFFFFFF);
416+
417+
#if defined(STM32F1xx)
418+
if ((RtcHandle.DateToUpdate.WeekDay == 0)
419+
&& (RtcHandle.DateToUpdate.Month == 0)
420+
&& (RtcHandle.DateToUpdate.Date == 0)
421+
&& (RtcHandle.DateToUpdate.Year == 0)) {
422+
// After a reset for example, restore HAL handle date with values from BackupRegister date
423+
memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4);
424+
}
425+
#endif // STM32F1xx
426+
427+
if (source != oldRtcClockSource) {
428+
// RTC is already initialized, but RTC clock source is changed
429+
// In case of RTC source clock change, Backup Domain is reset by RTC_initClock()
430+
// Save current config before call to RTC_initClock()
431+
RTC_GetDate(&years, &month, &days, &weekDay);
432+
RTC_GetTime(&hours, &minutes, &seconds, &subSeconds, &period);
433+
#if defined(STM32F1xx)
434+
RTC_getPrediv(&asynch);
435+
#else
436+
RTC_getPrediv(&asynch, &sync);
437+
#endif // STM32F1xx
438+
if (isAlarmSet) {
439+
RTC_GetAlarm(&alarmDay, &alarmHours, &alarmMinutes, &alarmSeconds, &alarmSubseconds, &alarmPeriod, &alarmMask);
440+
}
441+
442+
// Init RTC clock
443+
RTC_initClock(source);
444+
445+
// Restore config
446+
RTC_SetTime(hours, minutes, seconds, subSeconds, period);
447+
RTC_SetDate(years, month, days, weekDay);
448+
#if defined(STM32F1xx)
449+
RTC_setPrediv(asynch);
450+
#else
451+
RTC_setPrediv(asynch, sync);
452+
#endif // STM32F1xx
453+
if (isAlarmSet) {
454+
RTC_StartAlarm(alarmDay, alarmHours, alarmMinutes, alarmSeconds, alarmSubseconds, alarmPeriod, alarmMask);
455+
}
456+
} else {
457+
// RTC is already initialized, and RTC stays on the same clock source
458+
459+
// Init RTC clock
460+
RTC_initClock(source);
461+
#if defined(STM32F1xx)
462+
memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4);
463+
/* and fill the new RTC Date value */
464+
RTC_SetDate(RtcHandle.DateToUpdate.Year, RtcHandle.DateToUpdate.Month,
465+
RtcHandle.DateToUpdate.Date, RtcHandle.DateToUpdate.WeekDay);
466+
#else
467+
// This initialize variables: predivAsync, predivSync and predivSync_bits
468+
RTC_getPrediv(NULL, NULL);
469+
#endif // STM32F1xx
470+
}
401471
}
402-
#endif /* STM32F1xx */
403472

404473
#if defined(RTC_CR_BYPSHAD)
405474
/* Enable Direct Read of the calendar registers (not through Shadow) */
@@ -573,9 +642,6 @@ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday)
573642
*month = RTC_DateStruct.Month;
574643
*day = RTC_DateStruct.Date;
575644
*wday = RTC_DateStruct.WeekDay;
576-
#if defined(STM32F1xx)
577-
RTC_StoreDate();
578-
#endif /* STM32F1xx */
579645
}
580646
}
581647

0 commit comments

Comments
 (0)