diff --git a/README.md b/README.md
index 57f537a..d0ab6e6 100644
--- a/README.md
+++ b/README.md
@@ -34,8 +34,8 @@ _RTC clock source_
* **`void setClockSource(Source_Clock source)`** : this function must be called before `begin()`.
_RTC Asynchronous and Synchronous prescaler_
-* **`void getPrediv(int8_t *predivA, int16_t *predivS)`** : get user (a)synchronous prescaler values if set else computed ones for the current clock source.
-* **`void setPrediv(int8_t predivA, int16_t predivS)`** : set user (a)synchronous prescaler values. This function must be called before `begin()`. Use -1 to reset value and use computed ones.
+* **`void getPrediv(int8_t *predivA, int16_t *predivS)`** : get (a)synchronous prescaler values if set else computed ones for the current clock source.
+* **`void setPrediv(int8_t predivA, int16_t predivS)`** : set (a)synchronous prescaler values. This function must be called before `begin()`. Use -1 to reset value and use computed ones. Those values have to match the following conditions: **_1Hz = RTC CLK source / ((predivA + 1) * (predivS + 1))_**
_SubSeconds management_
* **`uint32_t getSubSeconds(void)`**
@@ -62,6 +62,10 @@ _Time and date configuration (added for convenience)_
_SubSeconds alarm management_
+ Important note:
+ - STM32F1 and STM32L1xx (Ultra Low Power Medium (ULPM) density) series do not support subsecond.
+ - Subsecond “resolution” depends on synchronous prescaler value. Bigger than this value is, better resolution will get for subsecond.
+
* **`void setAlarmSubSeconds(uint32_t subSeconds)`**
* **Updated API:**
diff --git a/examples/Epoch/Epoch.ino b/examples/Epoch/Epoch.ino
index e23ec7a..60838fa 100644
--- a/examples/Epoch/Epoch.ino
+++ b/examples/Epoch/Epoch.ino
@@ -1,42 +1,20 @@
-/**
- ******************************************************************************
- * @file Epoch.ino
- * @author WI6LABS
- * @version V1.0.0
- * @date 12-December-2017
- * @brief RTC epoch example
- *
- ******************************************************************************
- * @attention
- *
- *
© COPYRIGHT(c) 2017 STMicroelectronics
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
+/*
+ Epoch
+
+ This sketch shows how to manage the RTC using Epoch time
+
+ Creation 12 Dec 2017
+ by Wi6Labs
+ Modified 03 Jul 2020
+ by Frederic Pillon for STMicroelectronics
+
+ This example code is in the public domain.
+
+ https://github.com/stm32duino/STM32RTC
+*/
#include
+#include
/* Get the rtc object */
STM32RTC& rtc = STM32RTC::getInstance();
@@ -54,35 +32,35 @@ void setup() {
}
void loop() {
+ uint32_t ss = rtc.getSubSeconds();
+ uint32_t epoch = rtc.getEpoch();
+ time_t rawtime = epoch;
+ struct tm ts;
+ char buf[80];
+
Serial.print("Unix time = ");
- Serial.println(rtc.getEpoch());
+ Serial.println(epoch);
Serial.print("Seconds since Jan 1 2000 = ");
Serial.println(rtc.getY2kEpoch());
- // Print date...
- Serial.print(rtc.getDay());
- Serial.print("/");
- Serial.print(rtc.getMonth());
- Serial.print("/");
- Serial.print(rtc.getYear());
- Serial.print("\t");
-
- // ...and time
- print2digits(rtc.getHours());
- Serial.print(":");
- print2digits(rtc.getMinutes());
- Serial.print(":");
- print2digits(rtc.getSeconds());
-
+ // Format time, "ddd yyyy-mm-dd hh:mm:ss zzz"
+ ts = *localtime(&rawtime);
+ strftime(buf, sizeof(buf), "%a %Y-%m-%d %H:%M:%S", &ts);
+ Serial.print(buf);
+ Serial.print(".");
+ print2digits(ss);
Serial.println();
- delay(1000);
+ delay(678);
}
-void print2digits(int number) {
+void print2digits(uint32_t number) {
+ if (number < 100) {
+ Serial.print("0");
+ }
if (number < 10) {
Serial.print("0");
}
Serial.print(number);
-}
+}
\ No newline at end of file
diff --git a/examples/RTCClockSelection/RTCClockSelection.ino b/examples/RTCClockSelection/RTCClockSelection.ino
index 8551355..7fdf46f 100644
--- a/examples/RTCClockSelection/RTCClockSelection.ino
+++ b/examples/RTCClockSelection/RTCClockSelection.ino
@@ -1,41 +1,22 @@
-/**
- ******************************************************************************
- * @file RTCClockSelection.ino
- * @author WI6LABS
- * @version V1.0.0
- * @date 15-March-2018
- * @brief RTC clock selection: LSI, LSE or HSE. Refer to board datasheet to
- * know available clock.
- *
- ******************************************************************************
- * @attention
- *
- * © COPYRIGHT(c) 2018 STMicroelectronics
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
+/*
+ RTCClockSelection
+
+ This sketch shows how to select one of the RTC clock:
+ - LSI (default)
+ - LSE
+ - HSE
+
+ Refer to board datasheet to know available clock
+
+ Creation 15 March 2018
+ by Wi6Labs
+ Modified 03 Jul 2020
+ by Frederic Pillon for STMicroelectronics
+
+ This example code is in the public domain.
+
+ https://github.com/stm32duino/STM32RTC
+*/
#include
@@ -96,17 +77,19 @@ void loop()
print2digits(rtc.getMinutes());
Serial.print(":");
print2digits(rtc.getSeconds());
-
+ Serial.print(".");
+ print2digits(rtc.getSubSeconds());
Serial.println();
delay(1000);
}
-
-
void print2digits(int number) {
+ if (number < 100) {
+ Serial.print("0");
+ }
if (number < 10) {
- Serial.print("0"); // print a 0 before if the number is < than 10
+ Serial.print("0");
}
Serial.print(number);
-}
+}
\ No newline at end of file
diff --git a/examples/SimpleRTC/SimpleRTC.ino b/examples/SimpleRTC/SimpleRTC.ino
index 0e11d6b..851a5b2 100644
--- a/examples/SimpleRTC/SimpleRTC.ino
+++ b/examples/SimpleRTC/SimpleRTC.ino
@@ -1,40 +1,18 @@
-/**
- ******************************************************************************
- * @file SimpleRTC.ino
- * @author WI6LABS
- * @version V1.0.0
- * @date 12-December-2017
- * @brief Simple RTC example.
- *
- ******************************************************************************
- * @attention
- *
- * © COPYRIGHT(c) 2017 STMicroelectronics
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
+/*
+ SimpleRTC
+
+ This sketch shows how to configure the RTC and to display
+ the date and time periodically
+
+ Creation 12 Dec 2017
+ by Wi6Labs
+ Modified 03 Jul 2020
+ by Frederic Pillon for STMicroelectronics
+
+ This example code is in the public domain.
+
+ https://github.com/stm32duino/STM32RTC
+*/
#include
@@ -95,17 +73,19 @@ void loop()
print2digits(rtc.getMinutes());
Serial.print(":");
print2digits(rtc.getSeconds());
-
+ Serial.print(".");
+ print2digits(rtc.getSubSeconds());
Serial.println();
delay(1000);
}
-
-
void print2digits(int number) {
+ if (number < 100) {
+ Serial.print("0");
+ }
if (number < 10) {
- Serial.print("0"); // print a 0 before if the number is < than 10
+ Serial.print("0");
}
Serial.print(number);
-}
+}
\ No newline at end of file
diff --git a/examples/advancedRTCAlarm/advancedRTCAlarm.ino b/examples/advancedRTCAlarm/advancedRTCAlarm.ino
index ec9e30e..4871d14 100644
--- a/examples/advancedRTCAlarm/advancedRTCAlarm.ino
+++ b/examples/advancedRTCAlarm/advancedRTCAlarm.ino
@@ -5,14 +5,14 @@
It uses the optional 'data' alarm callback parameters to
reload alarm with 'atime' offset indefinitely.
-
Creation 25 May 2018
by Frederic Pillon for STMicroelectronics
+ Modified 03 Jul 2020
+ by Frederic Pillon for STMicroelectronics
This example code is in the public domain.
https://github.com/stm32duino/STM32RTC
-
*/
#include
@@ -23,8 +23,9 @@ STM32RTC& rtc = STM32RTC::getInstance();
/* Declare it volatile since it's incremented inside an interrupt */
volatile int alarmMatch_counter = 0;
-/* Change this value to set alarm match offset */
-static uint32_t atime = 5;
+/* Change this value to set alarm match offset in millisecond */
+/* Note that STM32F1xx does not manage subsecond only second */
+static uint32_t atime = 678;
/* Change these values to set the current initial time */
const byte seconds = 0;
@@ -51,7 +52,7 @@ void setup()
rtc.attachInterrupt(alarmMatch, &atime);
rtc.setAlarmDay(day);
- rtc.setAlarmTime(16, 0, 10);
+ rtc.setAlarmTime(16, 0, 10, 567);
rtc.enableAlarm(rtc.MATCH_DHHMMSS);
}
@@ -62,16 +63,37 @@ void loop()
void alarmMatch(void *data)
{
- uint32_t sec = 1;
- if(data != NULL) {
- sec = *(uint32_t*)data;
+ uint32_t epoc;
+ uint32_t epoc_ms;
+ uint32_t sec = 0;
+ uint32_t _millis = 1000;
+
+ if (data != NULL) {
+ _millis = *(uint32_t*)data;
// Minimum is 1 second
- if (sec == 0){
+ if (sec == 0) {
sec = 1;
}
}
- alarmMatch_counter++;
- Serial.print("Alarm Match ");
- Serial.println(alarmMatch_counter);
- rtc.setAlarmEpoch( rtc.getEpoch() + sec);
+
+ sec = _millis / 1000;
+#ifdef STM32F1xx
+ // Minimum is 1 second
+ if (sec == 0) {
+ sec = 1;
+ }
+ epoc = rtc.getEpoch(&epoc_ms);
+#else
+ _millis = _millis % 1000;
+ epoc = rtc.getEpoch(&epoc_ms);
+
+ //Update epoch_ms - might need to add a second to epoch
+ epoc_ms += _millis;
+ if (epoc_ms >= 1000) {
+ sec ++;
+ epoc_ms -= 1000;
+ }
+#endif
+ Serial.printf("Alarm Match %i\n", ++alarmMatch_counter);
+ rtc.setAlarmEpoch(epoc + sec, STM32RTC::MATCH_SS, epoc_ms);
}
diff --git a/examples/simpleRTCAlarm/simpleRTCAlarm.ino b/examples/simpleRTCAlarm/simpleRTCAlarm.ino
index 4f37ddc..b884714 100644
--- a/examples/simpleRTCAlarm/simpleRTCAlarm.ino
+++ b/examples/simpleRTCAlarm/simpleRTCAlarm.ino
@@ -1,40 +1,17 @@
-/**
- ******************************************************************************
- * @file simpleRTCAlarm.ino
- * @author WI6LABS
- * @version V1.0.0
- * @date 12-December-2017
- * @brief Simple RTC with alarm example.
- *
- ******************************************************************************
- * @attention
- *
- * © COPYRIGHT(c) 2017 STMicroelectronics
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. Neither the name of STMicroelectronics nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- */
+/*
+ Epoch
+
+ This sketch shows how to configure the RTC alarm
+
+ Creation 12 Dec 2017
+ by Wi6Labs
+ Modified 03 Jul 2020
+ by Frederic Pillon for STMicroelectronics
+
+ This example code is in the public domain.
+
+ https://github.com/stm32duino/STM32RTC
+*/
#include
@@ -66,7 +43,7 @@ void setup()
rtc.attachInterrupt(alarmMatch);
rtc.setAlarmDay(day);
- rtc.setAlarmTime(16, 0, 10);
+ rtc.setAlarmTime(16, 0, 10, 123);
rtc.enableAlarm(rtc.MATCH_DHHMMSS);
}
@@ -79,4 +56,4 @@ void alarmMatch(void *data)
{
UNUSED(data);
Serial.println("Alarm Match!");
-}
+}
\ No newline at end of file
diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp
index 8eaf8c0..b95a6ea 100644
--- a/src/STM32RTC.cpp
+++ b/src/STM32RTC.cpp
@@ -1,15 +1,13 @@
/**
******************************************************************************
* @file STM32RTC.cpp
- * @author WI6LABS
- * @version V1.0.0
- * @date 12-December-2017
+ * @author Frederic Pillon
* @brief Provides a RTC interface for Arduino
*
******************************************************************************
* @attention
*
- * © COPYRIGHT(c) 2017 STMicroelectronics
+ * © COPYRIGHT(c) 2020 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
diff --git a/src/STM32RTC.h b/src/STM32RTC.h
index 904ba69..0fd0cc3 100644
--- a/src/STM32RTC.h
+++ b/src/STM32RTC.h
@@ -1,15 +1,13 @@
/**
******************************************************************************
* @file STM32RTC.h
- * @author WI6LABS
- * @version V1.0.0
- * @date 12-December-2017
+ * @author Frederic Pillon
* @brief Provides a RTC interface for Arduino
*
******************************************************************************
* @attention
*
- * © COPYRIGHT(c) 2017 STMicroelectronics
+ * © COPYRIGHT(c) 2020 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
@@ -40,10 +38,12 @@
#define __STM32_RTC_H
#include "Arduino.h"
-
+#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01090000)
+ #include "rtc.h"
+#endif
// Check if RTC HAL enable in variants/board_name/stm32yzxx_hal_conf.h
#ifndef HAL_RTC_MODULE_ENABLED
-#error "RTC configuration is missing. Check flag HAL_RTC_MODULE_ENABLED in variants/board_name/stm32yzxx_hal_conf.h"
+ #error "RTC configuration is missing. Check flag HAL_RTC_MODULE_ENABLED in variants/board_name/stm32yzxx_hal_conf.h"
#endif
/**
diff --git a/src/rtc.c b/src/rtc.c
new file mode 100644
index 0000000..d2c7674
--- /dev/null
+++ b/src/rtc.c
@@ -0,0 +1,716 @@
+/**
+ ******************************************************************************
+ * @file rtc.c
+ * @author Frederic Pillon
+ * @brief Provides a RTC driver
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2020 STMicroelectronics
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+#include "rtc.h"
+#include
+
+#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01090000) &&\
+ defined(HAL_RTC_MODULE_ENABLED) && !defined(HAL_RTC_MODULE_ONLY)
+#if defined(STM32MP1xx)
+ /**
+ * Currently there is no RTC driver for STM32MP1xx. If RTC is used in the future
+ * the function call HAL_RCCEx_PeriphCLKConfig() shall be done under
+ * if(IS_ENGINEERING_BOOT_MODE()), since clock source selection is done by
+ * First Stage Boot Loader on Cortex-A.
+ */
+ #error "RTC shall not be handled by Arduino in STM32MP1xx."
+#endif /* STM32MP1xx */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+static RTC_HandleTypeDef RtcHandle = {0};
+static voidCallbackPtr RTCUserCallback = NULL;
+static void *callbackUserData = NULL;
+
+static sourceClock_t clkSrc = LSI_CLOCK;
+static uint8_t HSEDiv = 0;
+#if !defined(STM32F1xx)
+/* predividers values */
+static uint8_t predivSync_bits = 0xFF;
+static int8_t predivAsync = -1;
+static int16_t predivSync = -1;
+#endif /* !STM32F1xx */
+
+static hourFormat_t initFormat = HOUR_FORMAT_12;
+
+/* Private function prototypes -----------------------------------------------*/
+static void RTC_initClock(sourceClock_t source);
+#if !defined(STM32F1xx)
+static void RTC_computePrediv(int8_t *asynch, int16_t *synch);
+#endif /* !STM32F1xx */
+
+/* Exported functions --------------------------------------------------------*/
+
+/**
+ * @brief Set RTC clock source
+ * @param source: RTC clock source: LSE, LSI or HSE
+ * @retval None
+ */
+void RTC_SetClockSource(sourceClock_t source)
+{
+ switch (source) {
+ case LSI_CLOCK:
+ case LSE_CLOCK:
+ case HSE_CLOCK:
+ clkSrc = source;
+ break;
+ default:
+ clkSrc = LSI_CLOCK;
+ break;
+ }
+}
+
+/**
+ * @brief RTC clock initialization
+ * This function configures the hardware resources used.
+ * @param source: RTC clock source: LSE, LSI or HSE
+ * @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
+ * the RTC clock source; in this case the Backup domain will be reset in
+ * order to modify the RTC Clock source, as consequence RTC registers (including
+ * the backup registers) and RCC_CSR register are set to their reset values.
+ * @retval None
+ */
+static void RTC_initClock(sourceClock_t source)
+{
+ RCC_PeriphCLKInitTypeDef PeriphClkInit;
+
+ if (source == LSE_CLOCK) {
+ /* Enable the clock if not already set by user */
+ enableClock(LSE_CLOCK);
+
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
+ Error_Handler();
+ }
+ clkSrc = LSE_CLOCK;
+ } else if (source == HSE_CLOCK) {
+ /* Enable the clock if not already set by user */
+ enableClock(HSE_CLOCK);
+
+ /* HSE division factor for RTC clock must be set to ensure that
+ * the clock supplied to the RTC is less than or equal to 1 MHz
+ */
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
+#if defined(STM32F1xx)
+ /* HSE max is 16 MHZ divided by 128 --> 125 KHz */
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV128;
+ HSEDiv = 128;
+#elif defined(STM32F0xx) || defined(STM32F3xx) || defined(STM32G0xx) ||\
+ defined(STM32G4xx) || defined(STM32L4xx) || defined(STM32WBxx)
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;
+ HSEDiv = 32;
+#elif defined(STM32L0xx) || defined(STM32L1xx)
+ if ((HSE_VALUE / 2) <= HSE_RTC_MAX) {
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV2;
+ HSEDiv = 2;
+ } else if ((HSE_VALUE / 4) <= HSE_RTC_MAX) {
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV4;
+ HSEDiv = 4;
+ } else if ((HSE_VALUE / 8) <= HSE_RTC_MAX) {
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV8;
+ HSEDiv = 8;
+ } else if ((HSE_VALUE / 16) <= HSE_RTC_MAX) {
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV16;
+ HSEDiv = 16;
+ }
+#elif defined(STM32F2xx) || defined(STM32F4xx) || defined(STM32F7xx) || defined(STM32H7xx)
+ /* Not defined for STM32F2xx */
+#ifndef RCC_RTCCLKSOURCE_HSE_DIVX
+#define RCC_RTCCLKSOURCE_HSE_DIVX 0x00000300U
+#endif /* RCC_RTCCLKSOURCE_HSE_DIVX */
+#if defined(STM32H7xx)
+#define HSEDIV_MAX 64
+#define HSESHIFT 12
+#else
+#define HSEDIV_MAX 32
+#define HSESHIFT 16
+#endif
+ for (HSEDiv = 2; HSEDiv < HSEDIV_MAX; HSEDiv++) {
+ if ((HSE_VALUE / HSEDiv) <= HSE_RTC_MAX) {
+ PeriphClkInit.RTCClockSelection = (HSEDiv << HSESHIFT) | RCC_RTCCLKSOURCE_HSE_DIVX;
+ break;
+ }
+ }
+#else
+#error "Unknown Family - could not define RTCClockSelection"
+#endif /* STM32F1xx */
+ if ((HSE_VALUE / HSEDiv) > HSE_RTC_MAX) {
+ Error_Handler();
+ }
+
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
+ Error_Handler();
+ }
+ clkSrc = HSE_CLOCK;
+ } else if (source == LSI_CLOCK) {
+ /* Enable the clock if not already set by user */
+ enableClock(LSI_CLOCK);
+
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
+ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
+ Error_Handler();
+ }
+ clkSrc = LSI_CLOCK;
+ } else {
+ Error_Handler();
+ }
+#ifdef __HAL_RCC_RTCAPB_CLK_ENABLE
+ __HAL_RCC_RTCAPB_CLK_ENABLE();
+#endif
+ __HAL_RCC_RTC_ENABLE();
+}
+
+/**
+ * @brief set user (a)synchronous prescaler values.
+ * @note use -1 to reset value and use computed ones
+ * @param asynch: asynchronous prescaler value in range 0 - PREDIVA_MAX
+ * @param synch: synchronous prescaler value in range 0 - PREDIVS_MAX
+ * @retval None
+ */
+void RTC_setPrediv(int8_t asynch, int16_t synch)
+{
+#if !defined(STM32F1xx)
+ if ((asynch >= -1) && ((uint32_t)asynch <= PREDIVA_MAX) && \
+ (synch >= -1) && ((uint32_t)synch <= PREDIVS_MAX)) {
+ predivAsync = asynch;
+ predivSync = synch;
+ } else {
+ RTC_computePrediv(&predivAsync, &predivSync);
+ }
+ predivSync_bits = (uint8_t)log2(predivSync) + 1;
+#else
+ UNUSED(asynch);
+ UNUSED(synch);
+#endif /* !STM32F1xx */
+}
+
+/**
+ * @brief get user (a)synchronous prescaler values if set else computed ones
+ * for the current clock source.
+ * @param asynch: pointer where return asynchronous prescaler value.
+ * @param synch: pointer where return synchronous prescaler value.
+ * @retval None
+ */
+void RTC_getPrediv(int8_t *asynch, int16_t *synch)
+{
+#if !defined(STM32F1xx)
+ if ((predivAsync == -1) || (predivSync == -1)) {
+ RTC_computePrediv(&predivAsync, &predivSync);
+ }
+ if ((asynch != NULL) && (synch != NULL)) {
+ *asynch = predivAsync;
+ *synch = predivSync;
+ }
+ predivSync_bits = (uint8_t)log2(predivSync) + 1;
+#else
+ UNUSED(asynch);
+ UNUSED(synch);
+#endif /* !STM32F1xx */
+}
+
+#if !defined(STM32F1xx)
+/**
+ * @brief Compute (a)synchronous prescaler
+ * RTC prescalers are compute to obtain the RTC clock to 1Hz. See AN4759.
+ * @param asynch: pointer where return asynchronous prescaler value.
+ * @param synch: pointer where return synchronous prescaler value.
+ * @retval None
+ */
+static void RTC_computePrediv(int8_t *asynch, int16_t *synch)
+{
+ uint32_t predivS = PREDIVS_MAX + 1;
+ uint32_t clk = 0;
+
+ /* Get user predividers if manually configured */
+ if ((asynch == NULL) || (synch == NULL)) {
+ return;
+ }
+
+ /* Get clock frequency */
+ if (clkSrc == LSE_CLOCK) {
+ clk = LSE_VALUE;
+ } else if (clkSrc == LSI_CLOCK) {
+ clk = LSI_VALUE;
+ } else if (clkSrc == HSE_CLOCK) {
+ clk = HSE_VALUE / HSEDiv;
+ } else {
+ Error_Handler();
+ }
+
+ /* Find (a)synchronous prescalers to obtain the 1Hz calendar clock */
+ for (*asynch = PREDIVA_MAX; *asynch >= 0; (*asynch)--) {
+ predivS = (clk / (*asynch + 1)) - 1;
+
+ if (((predivS + 1) * (*asynch + 1)) == clk) {
+ break;
+ }
+ }
+
+ /*
+ * Can't find a 1Hz, so give priority to RTC power consumption
+ * by choosing the higher possible value for predivA
+ */
+ if ((predivS > PREDIVS_MAX) || (*asynch < 0)) {
+ *asynch = PREDIVA_MAX;
+ predivS = (clk / (*asynch + 1)) - 1;
+ }
+
+ if (predivS > PREDIVS_MAX) {
+ Error_Handler();
+ }
+ *synch = (int16_t)predivS;
+}
+#endif /* !STM32F1xx */
+
+/**
+ * @brief RTC Initialization
+ * This function configures the RTC time and calendar. By default, the
+ * RTC is set to the 1st January 2017 0:0:0:00
+ * @param format: enable the RTC in 12 or 24 hours mode
+ * @retval None
+ */
+void RTC_init(hourFormat_t format, sourceClock_t source, bool reset)
+{
+ initFormat = format;
+
+ if (reset) {
+ resetBackupDomain();
+ }
+
+ /* Init RTC clock */
+ RTC_initClock(source);
+
+ RtcHandle.Instance = RTC;
+
+#if defined(STM32F1xx)
+ /* Let HAL calculate the prescaler */
+ RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
+ RtcHandle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
+ UNUSED(format);
+#else
+ if (format == HOUR_FORMAT_12) {
+ RtcHandle.Init.HourFormat = RTC_HOURFORMAT_12;
+ } else {
+ RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
+ }
+ RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
+ RTC_getPrediv((int8_t *) & (RtcHandle.Init.AsynchPrediv), (int16_t *) & (RtcHandle.Init.SynchPrediv));
+#if defined(STM32G0xx) || defined(STM32H7xx) || defined(STM32L0xx) || defined(STM32L4xx)
+ RtcHandle.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
+#endif /* STM32H7xx || STM32L0xx || STM32L4xx */
+ RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
+ RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
+#endif /* STM32F1xx */
+
+ HAL_RTC_Init(&RtcHandle);
+
+#if !defined(STM32F1xx) && !defined(STM32F2xx) && !defined(STM32L1xx) || defined(STM32L1_ULPH)
+ /* Enable Direct Read of the calendar registers (not through Shadow) */
+ HAL_RTCEx_EnableBypassShadow(&RtcHandle);
+#endif /* !STM32F1xx && !STM32F2xx */
+
+ HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO);
+ HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
+ /* Ensure backup domain is enabled */
+ enableBackupDomain();
+}
+
+/**
+ * @brief RTC deinitialization. Stop the RTC.
+ * @retval None
+ */
+void RTC_DeInit(void)
+{
+ HAL_RTC_DeInit(&RtcHandle);
+ RTCUserCallback = NULL;
+ callbackUserData = NULL;
+}
+
+/**
+ * @brief Check if time is already set
+ * @retval True if set else false
+ */
+bool RTC_IsTimeSet(void)
+{
+ return (getBackupRegister(RTC_BKP_INDEX) == RTC_BKP_VALUE) ? true : false;
+}
+
+/**
+ * @brief Set RTC time
+ * @param hours: 0-12 or 0-23. Depends on the format used.
+ * @param minutes: 0-59
+ * @param seconds: 0-59
+ * @param subSeconds: 0-999
+ * @param period: select HOUR_AM or HOUR_PM period in case RTC is set in 12 hours mode. Else ignored.
+ * @retval None
+ */
+void RTC_SetTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period)
+{
+ RTC_TimeTypeDef RTC_TimeStruct;
+ UNUSED(subSeconds);
+ /* Ignore time AM PM configuration if in 24 hours format */
+ if (initFormat == HOUR_FORMAT_24) {
+ period = HOUR_AM;
+ }
+
+ if ((((initFormat == HOUR_FORMAT_24) && IS_RTC_HOUR24(hours)) || IS_RTC_HOUR12(hours))
+ && IS_RTC_MINUTES(minutes) && IS_RTC_SECONDS(seconds)) {
+ RTC_TimeStruct.Hours = hours;
+ RTC_TimeStruct.Minutes = minutes;
+ RTC_TimeStruct.Seconds = seconds;
+#if !defined(STM32F1xx)
+ if (period == HOUR_PM) {
+ RTC_TimeStruct.TimeFormat = RTC_HOURFORMAT12_PM;
+ } else {
+ RTC_TimeStruct.TimeFormat = RTC_HOURFORMAT12_AM;
+ }
+#if !defined(STM32F2xx) && !defined(STM32L1xx) || defined(STM32L1_ULPH)
+ /* subSeconds is read only, so no need to set it */
+ /*RTC_TimeStruct.SubSeconds = subSeconds;*/
+ /*RTC_TimeStruct.SecondFraction = 0;*/
+#endif /* !STM32F2xx && !STM32L1xx || STM32L1_ULPH */
+ RTC_TimeStruct.DayLightSaving = RTC_STOREOPERATION_RESET;
+ RTC_TimeStruct.StoreOperation = RTC_DAYLIGHTSAVING_NONE;
+#else
+ UNUSED(period);
+#endif /* !STM32F1xx */
+
+ HAL_RTC_SetTime(&RtcHandle, &RTC_TimeStruct, RTC_FORMAT_BIN);
+ setBackupRegister(RTC_BKP_INDEX, RTC_BKP_VALUE);
+ }
+}
+
+/**
+ * @brief Get RTC time
+ * @param hours: 0-12 or 0-23. Depends on the format used.
+ * @param minutes: 0-59
+ * @param seconds: 0-59
+ * @param subSeconds: 0-999 (optional could be NULL)
+ * @param period: HOUR_AM or HOUR_PM period in case RTC is set in 12 hours mode (optional could be NULL).
+ * @retval None
+ */
+void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, hourAM_PM_t *period)
+{
+ RTC_TimeTypeDef RTC_TimeStruct;
+
+ if ((hours != NULL) && (minutes != NULL) && (seconds != NULL)) {
+ HAL_RTC_GetTime(&RtcHandle, &RTC_TimeStruct, RTC_FORMAT_BIN);
+ *hours = RTC_TimeStruct.Hours;
+ *minutes = RTC_TimeStruct.Minutes;
+ *seconds = RTC_TimeStruct.Seconds;
+#if !defined(STM32F1xx)
+ if (period != NULL) {
+ if (RTC_TimeStruct.TimeFormat == RTC_HOURFORMAT12_PM) {
+ *period = HOUR_PM;
+ } else {
+ *period = HOUR_AM;
+ }
+ }
+#if (!defined(STM32F2xx) && !defined(STM32L1xx)) || defined(STM32L1_ULPH)
+ if (subSeconds != NULL) {
+ *subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1);
+ }
+#else
+ UNUSED(subSeconds);
+#endif
+#else
+ UNUSED(period);
+ UNUSED(subSeconds);
+#endif /* !STM32F1xx */
+ }
+}
+
+/**
+ * @brief Set RTC calendar
+ * @param year: 0-99
+ * @param month: 1-12
+ * @param day: 1-31
+ * @param wday: 1-7
+ * @retval None
+ */
+void RTC_SetDate(uint8_t year, uint8_t month, uint8_t day, uint8_t wday)
+{
+ RTC_DateTypeDef RTC_DateStruct;
+
+ if (IS_RTC_YEAR(year) && IS_RTC_MONTH(month) && IS_RTC_DATE(day) && IS_RTC_WEEKDAY(wday)) {
+ RTC_DateStruct.Year = year;
+ RTC_DateStruct.Month = month;
+ RTC_DateStruct.Date = day;
+ RTC_DateStruct.WeekDay = wday;
+ HAL_RTC_SetDate(&RtcHandle, &RTC_DateStruct, RTC_FORMAT_BIN);
+ setBackupRegister(RTC_BKP_INDEX, RTC_BKP_VALUE);
+ }
+}
+
+/**
+ * @brief Get RTC calendar
+ * @param year: 0-99
+ * @param month: 1-12
+ * @param day: 1-31
+ * @param wday: 1-7
+ * @retval None
+ */
+void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday)
+{
+ RTC_DateTypeDef RTC_DateStruct;
+
+ if ((year != NULL) && (month != NULL) && (day != NULL) && (wday != NULL)) {
+ HAL_RTC_GetDate(&RtcHandle, &RTC_DateStruct, RTC_FORMAT_BIN);
+ *year = RTC_DateStruct.Year;
+ *month = RTC_DateStruct.Month;
+ *day = RTC_DateStruct.Date;
+ *wday = RTC_DateStruct.WeekDay;
+ }
+}
+
+/**
+ * @brief Set RTC alarm and activate it with IT mode
+ * @param day: 1-31 (day of the month)
+ * @param hours: 0-12 or 0-23 depends on the hours mode.
+ * @param minutes: 0-59
+ * @param seconds: 0-59
+ * @param subSeconds: 0-999
+ * @param period: HOUR_AM or HOUR_PM if in 12 hours mode else ignored.
+ * @param mask: configure alarm behavior using alarmMask_t combination.
+ * See AN4579 Table 5 for possible values.
+ * @retval None
+ */
+void RTC_StartAlarm(uint8_t day, uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period, uint8_t mask)
+{
+ RTC_AlarmTypeDef RTC_AlarmStructure;
+
+ /* Ignore time AM PM configuration if in 24 hours format */
+ if (initFormat == HOUR_FORMAT_24) {
+ period = HOUR_AM;
+ }
+
+ if ((((initFormat == HOUR_FORMAT_24) && IS_RTC_HOUR24(hours)) || IS_RTC_HOUR12(hours))
+ && IS_RTC_DATE(day) && IS_RTC_MINUTES(minutes) && IS_RTC_SECONDS(seconds)) {
+ /* Set RTC_AlarmStructure with calculated values*/
+ /* Use alarm A by default because it is common to all STM32 HAL */
+ RTC_AlarmStructure.Alarm = RTC_ALARM_A;
+ RTC_AlarmStructure.AlarmTime.Seconds = seconds;
+ RTC_AlarmStructure.AlarmTime.Minutes = minutes;
+ RTC_AlarmStructure.AlarmTime.Hours = hours;
+#if !defined(STM32F1xx)
+#if !defined(STM32F2xx) && !defined(STM32L1xx) || defined(STM32L1_ULPH)
+ if (subSeconds < 1000) {
+ RTC_AlarmStructure.AlarmSubSecondMask = predivSync_bits << RTC_ALRMASSR_MASKSS_Pos;
+ RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000;
+ } else {
+ RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
+ }
+#else
+ UNUSED(subSeconds);
+#endif /* !STM32F2xx && !STM32L1xx || STM32L1_ULPH */
+ if (period == HOUR_PM) {
+ RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_HOURFORMAT12_PM;
+ } else {
+ RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
+ }
+ RTC_AlarmStructure.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
+ RTC_AlarmStructure.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
+ RTC_AlarmStructure.AlarmDateWeekDay = day;
+ RTC_AlarmStructure.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
+ /* configure AlarmMask (M_MSK and Y_MSK ignored) */
+ if (mask == OFF_MSK) {
+ RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_ALL;
+ } else {
+ RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_NONE;
+ if (!(mask & SS_MSK)) {
+ RTC_AlarmStructure.AlarmMask |= RTC_ALARMMASK_SECONDS;
+ }
+ if (!(mask & MM_MSK)) {
+ RTC_AlarmStructure.AlarmMask |= RTC_ALARMMASK_MINUTES;
+ }
+ if (!(mask & HH_MSK)) {
+ RTC_AlarmStructure.AlarmMask |= RTC_ALARMMASK_HOURS;
+ }
+ if (!(mask & D_MSK)) {
+ RTC_AlarmStructure.AlarmMask |= RTC_ALARMMASK_DATEWEEKDAY;
+ }
+ }
+#else
+ UNUSED(subSeconds);
+ UNUSED(period);
+ UNUSED(day);
+ UNUSED(mask);
+#endif /* !STM32F1xx */
+
+ /* Set RTC_Alarm */
+ HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN);
+ }
+}
+
+/**
+ * @brief Disable RTC alarm
+ * @param None
+ * @retval None
+ */
+void RTC_StopAlarm(void)
+{
+ /* Clear RTC Alarm Flag */
+ __HAL_RTC_ALARM_CLEAR_FLAG(&RtcHandle, RTC_FLAG_ALRAF);
+
+ /* Disable the Alarm A interrupt */
+ HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A);
+}
+
+/**
+ * @brief Get RTC alarm
+ * @param day: 1-31 day of the month (optional could be NULL)
+ * @param hours: 0-12 or 0-23 depends on the hours mode
+ * @param minutes: 0-59
+ * @param seconds: 0-59
+ * @param subSeconds: 0-999 (optional could be NULL)
+ * @param period: HOUR_AM or HOUR_PM (optional could be NULL)
+ * @param mask: alarm behavior using alarmMask_t combination (optional could be NULL)
+ * See AN4579 Table 5 for possible values
+ * @retval None
+ */
+void RTC_GetAlarm(uint8_t *day, uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, hourAM_PM_t *period, uint8_t *mask)
+{
+ RTC_AlarmTypeDef RTC_AlarmStructure;
+
+ if ((hours != NULL) && (minutes != NULL) && (seconds != NULL)) {
+ HAL_RTC_GetAlarm(&RtcHandle, &RTC_AlarmStructure, RTC_ALARM_A, RTC_FORMAT_BIN);
+
+ *seconds = RTC_AlarmStructure.AlarmTime.Seconds;
+ *minutes = RTC_AlarmStructure.AlarmTime.Minutes;
+ *hours = RTC_AlarmStructure.AlarmTime.Hours;
+
+#if !defined(STM32F1xx)
+ if (day != NULL) {
+ *day = RTC_AlarmStructure.AlarmDateWeekDay;
+ }
+ if (period != NULL) {
+ if (RTC_AlarmStructure.AlarmTime.TimeFormat == RTC_HOURFORMAT12_PM) {
+ *period = HOUR_PM;
+ } else {
+ *period = HOUR_AM;
+ }
+ }
+#if !defined(STM32F2xx) && !defined(STM32L1xx) || defined(STM32L1_ULPH)
+ if (subSeconds != NULL) {
+ *subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1);
+ }
+#else
+ UNUSED(subSeconds);
+#endif /* !STM32F2xx && !STM32L1xx || STM32L1_ULPH */
+ if (mask != NULL) {
+ *mask = OFF_MSK;
+ if (!(RTC_AlarmStructure.AlarmMask & RTC_ALARMMASK_SECONDS)) {
+ *mask |= SS_MSK;
+ }
+ if (!(RTC_AlarmStructure.AlarmMask & RTC_ALARMMASK_MINUTES)) {
+ *mask |= MM_MSK;
+ }
+ if (!(RTC_AlarmStructure.AlarmMask & RTC_ALARMMASK_HOURS)) {
+ *mask |= HH_MSK;
+ }
+ if (!(RTC_AlarmStructure.AlarmMask & RTC_ALARMMASK_DATEWEEKDAY)) {
+ *mask |= D_MSK;
+ }
+ }
+#else
+ UNUSED(day);
+ UNUSED(period);
+ UNUSED(subSeconds);
+ UNUSED(mask);
+#endif /* !STM32F1xx */
+ }
+}
+
+/**
+ * @brief Attach alarm callback.
+ * @param func: pointer to the callback
+ * @retval None
+ */
+void attachAlarmCallback(voidCallbackPtr func, void *data)
+{
+ RTCUserCallback = func;
+ callbackUserData = data;
+}
+
+/**
+ * @brief Detach alarm callback.
+ * @param None
+ * @retval None
+ */
+void detachAlarmCallback(void)
+{
+ RTCUserCallback = NULL;
+ callbackUserData = NULL;
+}
+
+/**
+ * @brief Alarm A callback.
+ * @param hrtc RTC handle
+ * @retval None
+ */
+void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
+{
+ UNUSED(hrtc);
+
+ if (RTCUserCallback != NULL) {
+ RTCUserCallback(callbackUserData);
+ }
+}
+
+/**
+ * @brief RTC Alarm IRQHandler
+ * @param None
+ * @retval None
+ */
+void RTC_Alarm_IRQHandler(void)
+{
+ HAL_RTC_AlarmIRQHandler(&RtcHandle);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_RTC_MODULE_ENABLED && !HAL_RTC_MODULE_ONLY */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/rtc.h b/src/rtc.h
new file mode 100644
index 0000000..4457a8b
--- /dev/null
+++ b/src/rtc.h
@@ -0,0 +1,176 @@
+/**
+ ******************************************************************************
+ * @file rtc.h
+ * @author Frederic Pillon
+ * @brief Header for RTC driver
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2020 STMicroelectronics
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __RTC_H
+#define __RTC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include
+#include "stm32_def.h"
+#include "backup.h"
+#include "clock.h"
+
+#if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION > 0x01090000) &&\
+ defined(HAL_RTC_MODULE_ENABLED) && !defined(HAL_RTC_MODULE_ONLY)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+typedef enum {
+ HOUR_FORMAT_12,
+ HOUR_FORMAT_24
+} hourFormat_t;
+
+typedef enum {
+ HOUR_AM,
+ HOUR_PM
+} hourAM_PM_t;
+
+/* See AN4579 Table 5 for possible values */
+typedef enum {
+ OFF_MSK = 0,
+ SS_MSK = 1, /* MSK0 */
+ MM_MSK = 2, /* MSK1 */
+ HH_MSK = 4, /* MSK2 */
+ D_MSK = 8, /* MSK3 */
+ /* NOTE: STM32 RTC can't assign a month or a year to an alarm. Those enum
+ are kept for compatibility but are ignored inside enableAlarm(). */
+ M_MSK = 16,
+ Y_MSK = 32
+} alarmMask_t;
+
+typedef void(*voidCallbackPtr)(void *);
+
+/* Exported constants --------------------------------------------------------*/
+/* Interrupt priority */
+#ifndef RTC_IRQ_PRIO
+#define RTC_IRQ_PRIO 2
+#endif
+#ifndef RTC_IRQ_SUBPRIO
+#define RTC_IRQ_SUBPRIO 0
+#endif
+
+
+#define HSE_RTC_MAX 1000000U
+
+#if !defined(STM32F1xx)
+#if !defined(RTC_PRER_PREDIV_S) || !defined(RTC_PRER_PREDIV_S)
+#error "Unknown Family - unknown synchronous prescaler"
+#endif
+#define PREDIVA_MAX (RTC_PRER_PREDIV_A >> RTC_PRER_PREDIV_A_Pos)
+#define PREDIVS_MAX (RTC_PRER_PREDIV_S >> RTC_PRER_PREDIV_S_Pos)
+#endif /* !STM32F1xx */
+
+/* Ultra Low Power High (ULPH) density */
+#if defined(STM32L100xBA) || defined (STM32L151xBA) || defined (STM32L152xBA) ||\
+ defined(STM32L100xC) || defined (STM32L151xC) || defined (STM32L152xC) ||\
+ defined (STM32L162xC) || defined(STM32L151xCA) || defined (STM32L151xD) ||\
+ defined (STM32L152xCA) || defined (STM32L152xD) || defined (STM32L162xCA) ||\
+ defined (STM32L162xD) || defined(STM32L151xE) || defined(STM32L151xDX) ||\
+ defined (STM32L152xE) || defined (STM32L152xDX) || defined (STM32L162xE) ||\
+ defined (STM32L162xDX)
+#define STM32L1_ULPH
+#endif
+
+#if defined(STM32F0xx) || defined(STM32L0xx)
+#define RTC_Alarm_IRQn RTC_IRQn
+#define RTC_Alarm_IRQHandler RTC_IRQHandler
+#endif
+#if defined(STM32G0xx)
+#define RTC_Alarm_IRQn RTC_TAMP_IRQn
+#define RTC_Alarm_IRQHandler RTC_TAMP_IRQHandler
+#endif
+
+#if defined(STM32F1xx) && !defined(IS_RTC_WEEKDAY)
+/* Compensate missing HAL definition */
+#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \
+ ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \
+ ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \
+ ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \
+ ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \
+ ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \
+ ((WEEKDAY) == RTC_WEEKDAY_SUNDAY))
+
+/* F1 doesn't manage 12h format */
+#define IS_RTC_HOUR12(HOUR) IS_RTC_HOUR24(HOUR)
+#endif /* !STM32F1xx && !IS_RTC_WEEKDAY */
+
+/* __HAL_RCC_GET_RTC_SOURCE is not defined for F2*/
+/*
+#ifndef __HAL_RCC_GET_RTC_SOURCE
+static uint32_t RTC_getSource(void) {
+ RCC_PeriphCLKInitTypeDef *PeriphClkInit;
+ HAL_RCCEx_GetPeriphCLKConfig(PeriphClkInit);
+ return PeriphClkInit->RTCClockSelection;
+}
+#define __HAL_RCC_GET_RTC_SOURCE() RTC_getSource()
+#endif
+*/
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void RTC_SetClockSource(sourceClock_t source);
+
+void RTC_getPrediv(int8_t *asynch, int16_t *synch);
+void RTC_setPrediv(int8_t asynch, int16_t synch);
+
+void RTC_init(hourFormat_t format, sourceClock_t source, bool reset);
+void RTC_DeInit(void);
+bool RTC_IsTimeSet(void);
+
+void RTC_SetTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period);
+void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, hourAM_PM_t *period);
+
+void RTC_SetDate(uint8_t year, uint8_t month, uint8_t day, uint8_t wday);
+void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday);
+
+void RTC_StartAlarm(uint8_t day, uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period, uint8_t mask);
+void RTC_StopAlarm(void);
+void RTC_GetAlarm(uint8_t *day, uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, hourAM_PM_t *period, uint8_t *mask);
+void attachAlarmCallback(voidCallbackPtr func, void *data);
+void detachAlarmCallback(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_RTC_MODULE_ENABLED && !HAL_RTC_MODULE_ONLY */
+
+#endif /* __RTC_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/