diff --git a/examples/F1RTCDateRetention/F1RTCDateRetention.ino b/examples/F1RTCDateRetention/F1RTCDateRetention.ino index 4827da4..0e925d8 100644 --- a/examples/F1RTCDateRetention/F1RTCDateRetention.ino +++ b/examples/F1RTCDateRetention/F1RTCDateRetention.ino @@ -66,8 +66,9 @@ void setup() // Check if date is valid = read in the backUp reg. // Note that backup reg only keep the date /time // and a power off reset the content if not saved by Vbat - // HAL_RTC init date is set to 1st of January 2000 -if ((day == 1) && (month == RTC_MONTH_JANUARY) && (year == 0)) { + // Stm32duino RTC init date is set to 1st of January 2001 + // https://github.com/stm32duino/STM32RTC/blob/f620b534f7bffe24f031fc5935324027cfe51320/src/rtc.c#L395 +if ((day == 1) && (month == RTC_MONTH_JANUARY) && (year == 1)) { // Set the time rtc.setHours(INITIAL_HOUR); rtc.setMinutes(INITIAL_MIN); diff --git a/library.json b/library.json index 5146af7..74a0a08 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/stm32duino/STM32RTC" }, - "version": "1.3.1", + "version": "1.3.2", "frameworks": "arduino", "platforms": "ststm32", "build": { diff --git a/library.properties b/library.properties index ed07d91..85e98a8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino RTC -version=1.3.1 +version=1.3.2 author=STMicroelectronics, Wi6Labs maintainer=stm32duino sentence=Allows to use the RTC functionalities of STM32 based boards. diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 31ce159..8f1f859 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -64,29 +64,26 @@ void STM32RTC::begin(bool resetTime, Hour_Format format) { bool reinit; - if (resetTime == true) { - _timeSet = false; - } _format = format; reinit = RTC_init((format == HOUR_12) ? HOUR_FORMAT_12 : HOUR_FORMAT_24, (_clockSource == LSE_CLOCK) ? ::LSE_CLOCK : (_clockSource == HSE_CLOCK) ? ::HSE_CLOCK : ::LSI_CLOCK , resetTime); + _timeSet = !reinit; + + syncTime(); + syncDate(); - if (reinit == true) { - _timeSet = false; - syncTime(); - syncDate(); - // Use current time to init alarm members + if (!IS_RTC_DATE(_alarmDay)) { + // Use current time to init alarm members, + // specially in case _alarmDay is 0 (reset value) which is an invalid value _alarmDay = _day; _alarmHours = _hours; _alarmMinutes = _minutes; _alarmSeconds = _seconds; _alarmSubSeconds = _subSeconds; _alarmPeriod = _hoursPeriod; - } else { - _timeSet = true; } } @@ -927,38 +924,9 @@ void STM32RTC::configForLowPower(Source_Clock source) __HAL_RCC_RTCAPB_CLKAM_ENABLE(); #endif + setClockSource(source); begin(); - if (_clockSource != source) { - // Save current config - AM_PM period, alarmPeriod = _alarmPeriod; - uint32_t subSeconds; - uint8_t seconds, minutes, hours, weekDay, day, month, years; - uint8_t alarmSeconds, alarmMinutes, alarmHours, alarmDay; - Alarm_Match alarmMatch = _alarmMatch; - - alarmDay = _alarmDay; - alarmHours = _alarmHours; - alarmMinutes = _alarmMinutes; - alarmSeconds = _alarmSeconds; - - getDate(&weekDay, &day, &month, &years); - getTime(&seconds, &minutes, &hours, &subSeconds, &period); - - end(); - _clockSource = source; - // Enable RTC - begin(_format); - // Restore config - setTime(seconds, minutes, hours, subSeconds, period); - setDate(weekDay, day, month, years); - setAlarmTime(alarmHours, alarmMinutes, alarmSeconds, alarmPeriod); - setAlarmDay(alarmDay); - if (RTC_IsAlarmSet()) { - enableAlarm(alarmMatch); - } - } - if (!isTimeSet()) { // Set arbitrary time for Lowpower; if not already set setTime(12, 0, 0, 0, AM); @@ -984,6 +952,9 @@ void STM32RTC::syncTime(void) void STM32RTC::syncDate(void) { RTC_GetDate(&_year, &_month, &_day, &_wday); +#if defined(STM32F1xx) + RTC_StoreDate(); +#endif /* STM32F1xx */ } /** diff --git a/src/rtc.c b/src/rtc.c index 7d7f212..adaf1d2 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -202,10 +202,6 @@ static void RTC_initClock(sourceClock_t source) } else { Error_Handler(); } -#ifdef __HAL_RCC_RTCAPB_CLK_ENABLE - __HAL_RCC_RTCAPB_CLK_ENABLE(); -#endif - __HAL_RCC_RTC_ENABLE(); } #if defined(STM32F1xx) @@ -342,12 +338,19 @@ static void RTC_computePrediv(int8_t *asynch, int16_t *synch) bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) { bool reinit = false; + hourAM_PM_t period = HOUR_AM, alarmPeriod = HOUR_AM; + uint32_t subSeconds = 0, alarmSubseconds = 0; + uint8_t seconds = 0, minutes = 0, hours = 0, weekDay = 0, days = 0, month = 0, years = 0; + uint8_t alarmMask = 0, alarmDay = 0, alarmHours = 0, alarmMinutes = 0, alarmSeconds = 0; + bool isAlarmSet = false; +#if defined(STM32F1xx) + uint32_t asynch; +#else + int8_t asynch; + int16_t sync; +#endif initFormat = format; - - /* Init RTC clock */ - RTC_initClock(source); - RtcHandle.Instance = RTC; /* Ensure backup domain is enabled before we init the RTC so we can use the backup registers for date retention on stm32f1xx boards */ @@ -355,31 +358,27 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) if (reset) { resetBackupDomain(); - RTC_initClock(source); } +#ifdef __HAL_RCC_RTCAPB_CLK_ENABLE + __HAL_RCC_RTCAPB_CLK_ENABLE(); +#endif + __HAL_RCC_RTC_ENABLE(); + + isAlarmSet = RTC_IsAlarmSet(); + #if defined(STM32F1xx) uint32_t BackupDate; BackupDate = getBackupRegister(RTC_BKP_DATE) << 16; BackupDate |= getBackupRegister(RTC_BKP_DATE + 1) & 0xFFFF; if ((BackupDate == 0) || reset) { + // RTC needs initialization /* Let HAL calculate the prescaler */ - RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND; + RtcHandle.Init.AsynchPrediv = prediv; RtcHandle.Init.OutPut = RTC_OUTPUTSOURCE_NONE; - HAL_RTC_Init(&RtcHandle); - // Default: saturday 1st of January 2001 - // Note: year 2000 is invalid as it is the hardware reset value and doesn't raise INITS flag - RTC_SetDate(1, 1, 1, 6); - reinit = true; - } else { - 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); - } #else - if (!LL_RTC_IsActiveFlag_INITS(RtcHandle.Instance) || reset) { + // RTC needs initialization RtcHandle.Init.HourFormat = format == HOUR_FORMAT_12 ? RTC_HOURFORMAT_12 : RTC_HOURFORMAT_24; RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; @@ -389,14 +388,87 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #endif /* RTC_OUTPUT_REMAP_NONE */ RTC_getPrediv((int8_t *) & (RtcHandle.Init.AsynchPrediv), (int16_t *) & (RtcHandle.Init.SynchPrediv)); +#endif // STM32F1xx + // Init RTC clock + RTC_initClock(source); HAL_RTC_Init(&RtcHandle); // Default: saturday 1st of January 2001 // Note: year 2000 is invalid as it is the hardware reset value and doesn't raise INITS flag RTC_SetDate(1, 1, 1, 6); reinit = true; + } else { + // RTC is already initialized + uint32_t oldRtcClockSource = __HAL_RCC_GET_RTC_SOURCE(); + oldRtcClockSource = ((oldRtcClockSource == RCC_RTCCLKSOURCE_LSE) ? LSE_CLOCK : + (oldRtcClockSource == RCC_RTCCLKSOURCE_LSI) ? LSI_CLOCK : +#if defined(RCC_RTCCLKSOURCE_HSE_DIVX) + (oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIVX) ? HSE_CLOCK : +#elif defined(RCC_RTCCLKSOURCE_HSE_DIV32) + (oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIV32) ? HSE_CLOCK : +#elif defined(RCC_RTCCLKSOURCE_HSE_DIV) + (oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIV) ? HSE_CLOCK : +#elif defined(RCC_RTCCLKSOURCE_HSE_DIV128) + (oldRtcClockSource == RCC_RTCCLKSOURCE_HSE_DIV128) ? HSE_CLOCK : +#endif + // default case corresponding to no clock source + 0xFFFFFFFF); + +#if defined(STM32F1xx) + if ((RtcHandle.DateToUpdate.WeekDay == 0) + && (RtcHandle.DateToUpdate.Month == 0) + && (RtcHandle.DateToUpdate.Date == 0) + && (RtcHandle.DateToUpdate.Year == 0)) { + // After a reset for example, restore HAL handle date with values from BackupRegister date + memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4); + } +#endif // STM32F1xx + + if (source != oldRtcClockSource) { + // RTC is already initialized, but RTC clock source is changed + // In case of RTC source clock change, Backup Domain is reset by RTC_initClock() + // Save current config before call to RTC_initClock() + RTC_GetDate(&years, &month, &days, &weekDay); + RTC_GetTime(&hours, &minutes, &seconds, &subSeconds, &period); +#if defined(STM32F1xx) + RTC_getPrediv(&asynch); +#else + RTC_getPrediv(&asynch, &sync); +#endif // STM32F1xx + if (isAlarmSet) { + RTC_GetAlarm(&alarmDay, &alarmHours, &alarmMinutes, &alarmSeconds, &alarmSubseconds, &alarmPeriod, &alarmMask); + } + + // Init RTC clock + RTC_initClock(source); + + // Restore config + RTC_SetTime(hours, minutes, seconds, subSeconds, period); + RTC_SetDate(years, month, days, weekDay); +#if defined(STM32F1xx) + RTC_setPrediv(asynch); +#else + RTC_setPrediv(asynch, sync); +#endif // STM32F1xx + if (isAlarmSet) { + RTC_StartAlarm(alarmDay, alarmHours, alarmMinutes, alarmSeconds, alarmSubseconds, alarmPeriod, alarmMask); + } + } else { + // RTC is already initialized, and RTC stays on the same clock source + + // Init RTC clock + RTC_initClock(source); +#if defined(STM32F1xx) + 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); +#else + // This initialize variables: predivAsync, predivSync and predivSync_bits + RTC_getPrediv(NULL, NULL); +#endif // STM32F1xx + } } -#endif /* STM32F1xx */ #if defined(RTC_CR_BYPSHAD) /* Enable Direct Read of the calendar registers (not through Shadow) */ @@ -570,9 +642,6 @@ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday) *month = RTC_DateStruct.Month; *day = RTC_DateStruct.Date; *wday = RTC_DateStruct.WeekDay; -#if defined(STM32F1xx) - RTC_StoreDate(); -#endif /* STM32F1xx */ } }