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****/