1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_hal_rtc.c
4   * @author  MCD Application Team
5   * @brief   RTC HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Real Time Clock (RTC) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + RTC Time and Date functions
10   *           + RTC Alarm functions
11   *           + Peripheral Control functions
12   *           + Peripheral State functions
13   *
14   ******************************************************************************
15   * @attention
16   *
17   * Copyright (c) 2016 STMicroelectronics.
18   * All rights reserved.
19   *
20   * This software is licensed under terms that can be found in the LICENSE file
21   * in the root directory of this software component.
22   * If no LICENSE file comes with this software, it is provided AS-IS.
23   *
24   ******************************************************************************
25   @verbatim
26   ==============================================================================
27                   ##### How to use this driver #####
28   ==============================================================================
29   [..]
30     (+) Enable the RTC domain access (see description in the section above).
31     (+) Configure the RTC Prescaler (Asynchronous prescaler to generate RTC 1Hz time base)
32         using the HAL_RTC_Init() function.
33 
34   *** Time and Date configuration ***
35   ===================================
36   [..]
37     (+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
38         and HAL_RTC_SetDate() functions.
39     (+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions.
40 
41   *** Alarm configuration ***
42   ===========================
43   [..]
44     (+) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function.
45         You can also configure the RTC Alarm with interrupt mode using the HAL_RTC_SetAlarm_IT() function.
46     (+) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function.
47 
48   *** Tamper configuration ***
49   ============================
50   [..]
51     (+) Enable the RTC Tamper and configure the Tamper Level using the
52         HAL_RTCEx_SetTamper() function. You can configure RTC Tamper with interrupt
53         mode using HAL_RTCEx_SetTamper_IT() function.
54     (+) The TAMPER1 alternate function can be mapped to PC13
55 
56   *** Backup Data Registers configuration ***
57   ===========================================
58   [..]
59     (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite()
60         function.
61     (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead()
62         function.
63 
64                   ##### WARNING: Drivers Restrictions  #####
65   ==================================================================
66   [..] RTC version used on STM32F1 families is version V1. All the features supported by V2
67        (other families) will be not supported on F1.
68   [..] As on V2, main RTC features are managed by HW. But on F1, date feature is completely
69        managed by SW.
70   [..] Then, there are some restrictions compared to other families:
71     (+) Only format 24 hours supported in HAL (format 12 hours not supported)
72     (+) Date is saved in SRAM. Then, when MCU is in STOP or STANDBY mode, date will be lost.
73         User should implement a way to save date before entering in low power mode (an
74         example is provided with firmware package based on backup registers)
75     (+) Date is automatically updated each time a HAL_RTC_GetTime or HAL_RTC_GetDate is called.
76     (+) Alarm detection is limited to 1 day. It will expire only 1 time (no alarm repetition, need
77         to program a new alarm)
78 
79               ##### Backup Domain Operating Condition #####
80   ==============================================================================
81   [..] The real-time clock (RTC) and the RTC backup registers can be powered
82        from the VBAT voltage when the main VDD supply is powered off.
83        To retain the content of the RTC backup registers and supply the RTC
84        when VDD is turned off, VBAT pin can be connected to an optional
85        standby voltage supplied by a battery or by another source.
86 
87   [..] To allow the RTC operating even when the main digital supply (VDD) is turned
88        off, the VBAT pin powers the following blocks:
89     (#) The RTC
90     (#) The LSE oscillator
91     (#) The backup SRAM when the low power backup regulator is enabled
92     (#) PC13 to PC15 I/Os, plus PI8 I/O (when available)
93 
94   [..] When the backup domain is supplied by VDD (analog switch connected to VDD),
95        the following pins are available:
96     (+) PC13 can be used as a Tamper pin
97 
98   [..] When the backup domain is supplied by VBAT (analog switch connected to VBAT
99        because VDD is not present), the following pins are available:
100     (+) PC13 can be used as the Tamper pin
101 
102                    ##### Backup Domain Reset #####
103   ==================================================================
104   [..] The backup domain reset sets all RTC registers and the RCC_BDCR register
105        to their reset values.
106   [..] A backup domain reset is generated when one of the following events occurs:
107     (#) Software reset, triggered by setting the BDRST bit in the
108         RCC Backup domain control register (RCC_BDCR).
109     (#) VDD or VBAT power on, if both supplies have previously been powered off.
110     (#) Tamper detection event resets all data backup registers.
111 
112                    ##### Backup Domain Access #####
113   ==================================================================
114   [..] After reset, the backup domain (RTC registers, RTC backup data
115        registers and backup SRAM) is protected against possible unwanted write
116        accesses.
117   [..] To enable access to the RTC Domain and RTC registers, proceed as follows:
118     (+) Call the function HAL_RCCEx_PeriphCLKConfig in using RCC_PERIPHCLK_RTC for
119         PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSE)
120     (+) Enable the BKP clock in using __HAL_RCC_BKP_CLK_ENABLE()
121 
122                   ##### RTC and low power modes #####
123   ==================================================================
124   [..] The MCU can be woken up from a low power mode by an RTC alternate
125        function.
126   [..] The RTC alternate functions are the RTC alarms (Alarm A),
127        and RTC tamper event detection.
128        These RTC alternate functions can wake up the system from the Stop and
129        Standby low power modes.
130   [..] The system can also wake up from low power modes without depending
131        on an external interrupt (Auto-wakeup mode), by using the RTC alarm.
132 
133   *** Callback registration ***
134   =============================================
135   [..]
136   The compilation define  USE_HAL_RTC_REGISTER_CALLBACKS when set to 1
137   allows the user to configure dynamically the driver callbacks.
138   Use Function HAL_RTC_RegisterCallback() to register an interrupt callback.
139 
140   [..]
141   Function HAL_RTC_RegisterCallback() allows to register following callbacks:
142     (+) AlarmAEventCallback          : RTC Alarm A Event callback.
143     (+) Tamper1EventCallback         : RTC Tamper 1 Event callback.
144     (+) MspInitCallback              : RTC MspInit callback.
145     (+) MspDeInitCallback            : RTC MspDeInit callback.
146   [..]
147   This function takes as parameters the HAL peripheral handle, the Callback ID
148   and a pointer to the user callback function.
149 
150   [..]
151   Use function HAL_RTC_UnRegisterCallback() to reset a callback to the default
152   weak function.
153   HAL_RTC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
154   and the Callback ID.
155   This function allows to reset following callbacks:
156     (+) AlarmAEventCallback          : RTC Alarm A Event callback.
157     (+) Tamper1EventCallback         : RTC Tamper 1 Event callback.
158     (+) MspInitCallback              : RTC MspInit callback.
159     (+) MspDeInitCallback            : RTC MspDeInit callback.
160   [..]
161   By default, after the HAL_RTC_Init() and when the state is HAL_RTC_STATE_RESET,
162   all callbacks are set to the corresponding weak functions :
163   example AlarmAEventCallback().
164   Exception done for MspInit and MspDeInit callbacks that are reset to the legacy weak function
165   in the HAL_RTC_Init()/HAL_RTC_DeInit() only when these callbacks are null
166   (not registered beforehand).
167   If not, MspInit or MspDeInit are not null, HAL_RTC_Init()/HAL_RTC_DeInit()
168   keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
169   [..]
170   Callbacks can be registered/unregistered in HAL_RTC_STATE_READY state only.
171   Exception done MspInit/MspDeInit that can be registered/unregistered
172   in HAL_RTC_STATE_READY or HAL_RTC_STATE_RESET state,
173   thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
174   In that case first register the MspInit/MspDeInit user callbacks
175   using HAL_RTC_RegisterCallback() before calling HAL_RTC_DeInit()
176   or HAL_RTC_Init() function.
177   [..]
178   When The compilation define USE_HAL_RTC_REGISTER_CALLBACKS is set to 0 or
179   not defined, the callback registration feature is not available and all callbacks
180   are set to the corresponding weak functions.
181 
182   @endverbatim
183   ******************************************************************************
184   */
185 
186 /* Includes ------------------------------------------------------------------*/
187 #include "stm32f1xx_hal.h"
188 
189 /** @addtogroup STM32F1xx_HAL_Driver
190   * @{
191   */
192 
193 /** @defgroup RTC RTC
194   * @brief RTC HAL module driver
195   * @{
196   */
197 
198 #ifdef HAL_RTC_MODULE_ENABLED
199 
200 /* Private typedef -----------------------------------------------------------*/
201 /* Private define ------------------------------------------------------------*/
202 /** @defgroup RTC_Private_Constants RTC Private Constants
203   * @{
204   */
205 #define RTC_ALARM_RESETVALUE_REGISTER    (uint16_t)0xFFFF
206 #define RTC_ALARM_RESETVALUE             0xFFFFFFFFU
207 
208 /**
209   * @}
210   */
211 
212 /* Private macro -------------------------------------------------------------*/
213 /** @defgroup RTC_Private_Macros RTC Private Macros
214   * @{
215   */
216 /**
217   * @}
218   */
219 
220 /* Private variables ---------------------------------------------------------*/
221 /* Private function prototypes -----------------------------------------------*/
222 /** @defgroup RTC_Private_Functions RTC Private Functions
223   * @{
224   */
225 static uint32_t           RTC_ReadTimeCounter(RTC_HandleTypeDef *hrtc);
226 static HAL_StatusTypeDef  RTC_WriteTimeCounter(RTC_HandleTypeDef *hrtc, uint32_t TimeCounter);
227 static uint32_t           RTC_ReadAlarmCounter(RTC_HandleTypeDef *hrtc);
228 static HAL_StatusTypeDef  RTC_WriteAlarmCounter(RTC_HandleTypeDef *hrtc, uint32_t AlarmCounter);
229 static HAL_StatusTypeDef  RTC_EnterInitMode(RTC_HandleTypeDef *hrtc);
230 static HAL_StatusTypeDef  RTC_ExitInitMode(RTC_HandleTypeDef *hrtc);
231 static uint8_t            RTC_ByteToBcd2(uint8_t Value);
232 static uint8_t            RTC_Bcd2ToByte(uint8_t Value);
233 static uint8_t            RTC_IsLeapYear(uint16_t nYear);
234 static void               RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed);
235 static uint8_t            RTC_WeekDayNum(uint32_t nYear, uint8_t nMonth, uint8_t nDay);
236 
237 /**
238   * @}
239   */
240 
241 /* Private functions ---------------------------------------------------------*/
242 /** @defgroup RTC_Exported_Functions RTC Exported Functions
243   * @{
244   */
245 
246 /** @defgroup RTC_Exported_Functions_Group1 Initialization and de-initialization functions
247  *  @brief    Initialization and Configuration functions
248  *
249 @verbatim
250  ===============================================================================
251               ##### Initialization and de-initialization functions #####
252  ===============================================================================
253    [..] This section provides functions allowing to initialize and configure the
254          RTC Prescaler (Asynchronous), disable RTC registers Write protection,
255          enter and exit the RTC initialization mode,
256          RTC registers synchronization check and reference clock detection enable.
257          (#) The RTC Prescaler should be programmed to generate the RTC 1Hz time base.
258          (#) All RTC registers are Write protected. Writing to the RTC registers
259              is enabled by setting the CNF bit in the RTC_CRL register.
260          (#) To read the calendar after wakeup from low power modes (Standby or Stop)
261              the software must first wait for the RSF bit (Register Synchronized Flag)
262              in the RTC_CRL register to be set by hardware.
263              The HAL_RTC_WaitForSynchro() function implements the above software
264              sequence (RSF clear and RSF check).
265 
266 @endverbatim
267   * @{
268   */
269 
270 /**
271   * @brief  Initializes the RTC peripheral
272   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
273   *                the configuration information for RTC.
274   * @retval HAL status
275   */
HAL_RTC_Init(RTC_HandleTypeDef * hrtc)276 HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
277 {
278   uint32_t prescaler = 0U;
279   /* Check input parameters */
280   if (hrtc == NULL)
281   {
282     return HAL_ERROR;
283   }
284 
285   /* Check the parameters */
286   assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
287   assert_param(IS_RTC_CALIB_OUTPUT(hrtc->Init.OutPut));
288   assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv));
289 
290 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
291   if (hrtc->State == HAL_RTC_STATE_RESET)
292   {
293     /* Allocate lock resource and initialize it */
294     hrtc->Lock = HAL_UNLOCKED;
295 
296     hrtc->AlarmAEventCallback          =  HAL_RTC_AlarmAEventCallback;        /* Legacy weak AlarmAEventCallback      */
297     hrtc->Tamper1EventCallback         =  HAL_RTCEx_Tamper1EventCallback;     /* Legacy weak Tamper1EventCallback     */
298 
299     if (hrtc->MspInitCallback == NULL)
300     {
301       hrtc->MspInitCallback = HAL_RTC_MspInit;
302     }
303     /* Init the low level hardware */
304     hrtc->MspInitCallback(hrtc);
305 
306     if (hrtc->MspDeInitCallback == NULL)
307     {
308       hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
309     }
310   }
311 #else
312   if (hrtc->State == HAL_RTC_STATE_RESET)
313   {
314     /* Allocate lock resource and initialize it */
315     hrtc->Lock = HAL_UNLOCKED;
316 
317     /* Initialize RTC MSP */
318     HAL_RTC_MspInit(hrtc);
319   }
320 #endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
321 
322   /* Set RTC state */
323   hrtc->State = HAL_RTC_STATE_BUSY;
324 
325   /* Waiting for synchro */
326   if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
327   {
328     /* Set RTC state */
329     hrtc->State = HAL_RTC_STATE_ERROR;
330 
331     return HAL_ERROR;
332   }
333 
334   /* Set Initialization mode */
335   if (RTC_EnterInitMode(hrtc) != HAL_OK)
336   {
337     /* Set RTC state */
338     hrtc->State = HAL_RTC_STATE_ERROR;
339 
340     return HAL_ERROR;
341   }
342   else
343   {
344     /* Clear Flags Bits */
345     CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_OW | RTC_FLAG_ALRAF | RTC_FLAG_SEC));
346 
347     if (hrtc->Init.OutPut != RTC_OUTPUTSOURCE_NONE)
348     {
349       /* Disable the selected Tamper pin */
350       CLEAR_BIT(BKP->CR, BKP_CR_TPE);
351     }
352 
353     /* Set the signal which will be routed to RTC Tamper pin*/
354     MODIFY_REG(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE | BKP_RTCCR_ASOS), hrtc->Init.OutPut);
355 
356     if (hrtc->Init.AsynchPrediv != RTC_AUTO_1_SECOND)
357     {
358       /* RTC Prescaler provided directly by end-user*/
359       prescaler = hrtc->Init.AsynchPrediv;
360     }
361     else
362     {
363       /* RTC Prescaler will be automatically calculated to get 1 second timebase */
364       /* Get the RTCCLK frequency */
365       prescaler = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_RTC);
366 
367       /* Check that RTC clock is enabled*/
368       if (prescaler == 0U)
369       {
370         /* Should not happen. Frequency is not available*/
371         hrtc->State = HAL_RTC_STATE_ERROR;
372         return HAL_ERROR;
373       }
374       else
375       {
376         /* RTC period = RTCCLK/(RTC_PR + 1) */
377         prescaler = prescaler - 1U;
378       }
379     }
380 
381     /* Configure the RTC_PRLH / RTC_PRLL */
382     WRITE_REG(hrtc->Instance->PRLH, ((prescaler >> 16U) & RTC_PRLH_PRL));
383     WRITE_REG(hrtc->Instance->PRLL, (prescaler & RTC_PRLL_PRL));
384 
385     /* Wait for synchro */
386     if (RTC_ExitInitMode(hrtc) != HAL_OK)
387     {
388       hrtc->State = HAL_RTC_STATE_ERROR;
389 
390       return HAL_ERROR;
391     }
392 
393     /* Initialize date to 1st of January 2000 */
394     hrtc->DateToUpdate.Year = 0x00U;
395     hrtc->DateToUpdate.Month = RTC_MONTH_JANUARY;
396     hrtc->DateToUpdate.Date = 0x01U;
397 
398     /* Set RTC state */
399     hrtc->State = HAL_RTC_STATE_READY;
400 
401     return HAL_OK;
402   }
403 }
404 
405 /**
406   * @brief  DeInitializes the RTC peripheral
407   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
408   *                the configuration information for RTC.
409   * @note   This function does not reset the RTC Backup Data registers.
410   * @retval HAL status
411   */
HAL_RTC_DeInit(RTC_HandleTypeDef * hrtc)412 HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
413 {
414   /* Check input parameters */
415   if (hrtc == NULL)
416   {
417     return HAL_ERROR;
418   }
419 
420   /* Check the parameters */
421   assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
422 
423   /* Set RTC state */
424   hrtc->State = HAL_RTC_STATE_BUSY;
425 
426   /* Set Initialization mode */
427   if (RTC_EnterInitMode(hrtc) != HAL_OK)
428   {
429     /* Set RTC state */
430     hrtc->State = HAL_RTC_STATE_ERROR;
431 
432     /* Release Lock */
433     __HAL_UNLOCK(hrtc);
434 
435     return HAL_ERROR;
436   }
437   else
438   {
439     CLEAR_REG(hrtc->Instance->CNTL);
440     CLEAR_REG(hrtc->Instance->CNTH);
441     WRITE_REG(hrtc->Instance->PRLL, 0x00008000U);
442     CLEAR_REG(hrtc->Instance->PRLH);
443 
444     /* Reset All CRH/CRL bits */
445     CLEAR_REG(hrtc->Instance->CRH);
446     CLEAR_REG(hrtc->Instance->CRL);
447 
448     if (RTC_ExitInitMode(hrtc) != HAL_OK)
449     {
450       hrtc->State = HAL_RTC_STATE_ERROR;
451 
452       /* Process Unlocked */
453       __HAL_UNLOCK(hrtc);
454 
455       return HAL_ERROR;
456     }
457   }
458 
459   /* Wait for synchro*/
460   HAL_RTC_WaitForSynchro(hrtc);
461 
462   /* Clear RSF flag */
463   CLEAR_BIT(hrtc->Instance->CRL, RTC_FLAG_RSF);
464 
465 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
466   if (hrtc->MspDeInitCallback == NULL)
467   {
468     hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
469   }
470 
471   /* DeInit the low level hardware: CLOCK, NVIC.*/
472   hrtc->MspDeInitCallback(hrtc);
473 
474 #else
475   /* De-Initialize RTC MSP */
476   HAL_RTC_MspDeInit(hrtc);
477 #endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
478 
479   hrtc->State = HAL_RTC_STATE_RESET;
480 
481   /* Release Lock */
482   __HAL_UNLOCK(hrtc);
483 
484   return HAL_OK;
485 }
486 
487 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
488 /**
489   * @brief  Register a User RTC Callback
490   *         To be used instead of the weak predefined callback
491   * @param  hrtc RTC handle
492   * @param  CallbackID ID of the callback to be registered
493   *         This parameter can be one of the following values:
494   *          @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID          Alarm A Event Callback ID
495   *          @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID          Tamper 1 Callback ID
496   *          @arg @ref HAL_RTC_MSPINIT_CB_ID                Msp Init callback ID
497   *          @arg @ref HAL_RTC_MSPDEINIT_CB_ID              Msp DeInit callback ID
498   * @param  pCallback pointer to the Callback function
499   * @retval HAL status
500   */
HAL_RTC_RegisterCallback(RTC_HandleTypeDef * hrtc,HAL_RTC_CallbackIDTypeDef CallbackID,pRTC_CallbackTypeDef pCallback)501 HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback)
502 {
503   HAL_StatusTypeDef status = HAL_OK;
504 
505   if (pCallback == NULL)
506   {
507     return HAL_ERROR;
508   }
509 
510   /* Process locked */
511   __HAL_LOCK(hrtc);
512 
513   if (HAL_RTC_STATE_READY == hrtc->State)
514   {
515     switch (CallbackID)
516     {
517       case HAL_RTC_ALARM_A_EVENT_CB_ID :
518         hrtc->AlarmAEventCallback = pCallback;
519         break;
520 
521       case HAL_RTC_TAMPER1_EVENT_CB_ID :
522         hrtc->Tamper1EventCallback = pCallback;
523         break;
524 
525       case HAL_RTC_MSPINIT_CB_ID :
526         hrtc->MspInitCallback = pCallback;
527         break;
528 
529       case HAL_RTC_MSPDEINIT_CB_ID :
530         hrtc->MspDeInitCallback = pCallback;
531         break;
532 
533       default :
534         /* Return error status */
535         status =  HAL_ERROR;
536         break;
537     }
538   }
539   else if (HAL_RTC_STATE_RESET == hrtc->State)
540   {
541     switch (CallbackID)
542     {
543       case HAL_RTC_MSPINIT_CB_ID :
544         hrtc->MspInitCallback = pCallback;
545         break;
546 
547       case HAL_RTC_MSPDEINIT_CB_ID :
548         hrtc->MspDeInitCallback = pCallback;
549         break;
550 
551       default :
552         /* Return error status */
553         status =  HAL_ERROR;
554         break;
555     }
556   }
557   else
558   {
559     /* Return error status */
560     status =  HAL_ERROR;
561   }
562 
563   /* Release Lock */
564   __HAL_UNLOCK(hrtc);
565 
566   return status;
567 }
568 
569 /**
570   * @brief  Unregister an RTC Callback
571   *         RTC callback is redirected to the weak predefined callback
572   * @param  hrtc RTC handle
573   * @param  CallbackID ID of the callback to be unregistered
574   *         This parameter can be one of the following values:
575   *          @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID          Alarm A Event Callback ID
576   *          @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID          Tamper 1 Callback ID
577   *          @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
578   *          @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
579   * @retval HAL status
580   */
HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef * hrtc,HAL_RTC_CallbackIDTypeDef CallbackID)581 HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID)
582 {
583   HAL_StatusTypeDef status = HAL_OK;
584 
585   /* Process locked */
586   __HAL_LOCK(hrtc);
587 
588   if (HAL_RTC_STATE_READY == hrtc->State)
589   {
590     switch (CallbackID)
591     {
592       case HAL_RTC_ALARM_A_EVENT_CB_ID :
593         hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback;         /* Legacy weak AlarmAEventCallback    */
594         break;
595 
596       case HAL_RTC_TAMPER1_EVENT_CB_ID :
597         hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback;         /* Legacy weak Tamper1EventCallback   */
598         break;
599 
600       case HAL_RTC_MSPINIT_CB_ID :
601         hrtc->MspInitCallback = HAL_RTC_MspInit;
602         break;
603 
604       case HAL_RTC_MSPDEINIT_CB_ID :
605         hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
606         break;
607 
608       default :
609         /* Return error status */
610         status =  HAL_ERROR;
611         break;
612     }
613   }
614   else if (HAL_RTC_STATE_RESET == hrtc->State)
615   {
616     switch (CallbackID)
617     {
618       case HAL_RTC_MSPINIT_CB_ID :
619         hrtc->MspInitCallback = HAL_RTC_MspInit;
620         break;
621 
622       case HAL_RTC_MSPDEINIT_CB_ID :
623         hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
624         break;
625 
626       default :
627         /* Return error status */
628         status =  HAL_ERROR;
629         break;
630     }
631   }
632   else
633   {
634     /* Return error status */
635     status =  HAL_ERROR;
636   }
637 
638   /* Release Lock */
639   __HAL_UNLOCK(hrtc);
640 
641   return status;
642 }
643 #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
644 
645 /**
646   * @brief  Initializes the RTC MSP.
647   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
648   *                the configuration information for RTC.
649   * @retval None
650   */
HAL_RTC_MspInit(RTC_HandleTypeDef * hrtc)651 __weak void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
652 {
653   /* Prevent unused argument(s) compilation warning */
654   UNUSED(hrtc);
655   /* NOTE : This function Should not be modified, when the callback is needed,
656             the HAL_RTC_MspInit could be implemented in the user file
657    */
658 }
659 
660 /**
661   * @brief  DeInitializes the RTC MSP.
662   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
663   *                the configuration information for RTC.
664   * @retval None
665   */
HAL_RTC_MspDeInit(RTC_HandleTypeDef * hrtc)666 __weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc)
667 {
668   /* Prevent unused argument(s) compilation warning */
669   UNUSED(hrtc);
670   /* NOTE : This function Should not be modified, when the callback is needed,
671             the HAL_RTC_MspDeInit could be implemented in the user file
672    */
673 }
674 
675 /**
676   * @}
677   */
678 
679 /** @defgroup RTC_Exported_Functions_Group2 Time and Date functions
680  *  @brief   RTC Time and Date functions
681  *
682 @verbatim
683  ===============================================================================
684                  ##### RTC Time and Date functions #####
685  ===============================================================================
686 
687  [..] This section provides functions allowing to configure Time and Date features
688 
689 @endverbatim
690   * @{
691   */
692 
693 /**
694   * @brief  Sets RTC current time.
695   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
696   *                the configuration information for RTC.
697   * @param  sTime: Pointer to Time structure
698   * @param  Format: Specifies the format of the entered parameters.
699   *          This parameter can be one of the following values:
700   *            @arg RTC_FORMAT_BIN: Binary data format
701   *            @arg RTC_FORMAT_BCD: BCD data format
702   * @retval HAL status
703   */
HAL_RTC_SetTime(RTC_HandleTypeDef * hrtc,RTC_TimeTypeDef * sTime,uint32_t Format)704 HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
705 {
706   uint32_t counter_time = 0U, counter_alarm = 0U;
707 
708   /* Check input parameters */
709   if ((hrtc == NULL) || (sTime == NULL))
710   {
711     return HAL_ERROR;
712   }
713 
714   /* Check the parameters */
715   assert_param(IS_RTC_FORMAT(Format));
716 
717   /* Process Locked */
718   __HAL_LOCK(hrtc);
719 
720   hrtc->State = HAL_RTC_STATE_BUSY;
721 
722   if (Format == RTC_FORMAT_BIN)
723   {
724     assert_param(IS_RTC_HOUR24(sTime->Hours));
725     assert_param(IS_RTC_MINUTES(sTime->Minutes));
726     assert_param(IS_RTC_SECONDS(sTime->Seconds));
727 
728     counter_time = (uint32_t)(((uint32_t)sTime->Hours * 3600U) + \
729                               ((uint32_t)sTime->Minutes * 60U) + \
730                               ((uint32_t)sTime->Seconds));
731   }
732   else
733   {
734     assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
735     assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
736     assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
737 
738     counter_time = (((uint32_t)(RTC_Bcd2ToByte(sTime->Hours)) * 3600U) + \
739                     ((uint32_t)(RTC_Bcd2ToByte(sTime->Minutes)) * 60U) + \
740                     ((uint32_t)(RTC_Bcd2ToByte(sTime->Seconds))));
741   }
742 
743   /* Write time counter in RTC registers */
744   if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
745   {
746     /* Set RTC state */
747     hrtc->State = HAL_RTC_STATE_ERROR;
748 
749     /* Process Unlocked */
750     __HAL_UNLOCK(hrtc);
751 
752     return HAL_ERROR;
753   }
754   else
755   {
756     /* Clear Second and overflow flags */
757     CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
758 
759     /* Read current Alarm counter in RTC registers */
760     counter_alarm = RTC_ReadAlarmCounter(hrtc);
761 
762     /* Set again alarm to match with new time if enabled */
763     if (counter_alarm != RTC_ALARM_RESETVALUE)
764     {
765       if (counter_alarm < counter_time)
766       {
767         /* Add 1 day to alarm counter*/
768         counter_alarm += (uint32_t)(24U * 3600U);
769 
770         /* Write new Alarm counter in RTC registers */
771         if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
772         {
773           /* Set RTC state */
774           hrtc->State = HAL_RTC_STATE_ERROR;
775 
776           /* Process Unlocked */
777           __HAL_UNLOCK(hrtc);
778 
779           return HAL_ERROR;
780         }
781       }
782     }
783 
784     hrtc->State = HAL_RTC_STATE_READY;
785 
786     __HAL_UNLOCK(hrtc);
787 
788     return HAL_OK;
789   }
790 }
791 
792 /**
793   * @brief  Gets RTC current time.
794   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
795   *                the configuration information for RTC.
796   * @param  sTime: Pointer to Time structure
797   * @param  Format: Specifies the format of the entered parameters.
798   *          This parameter can be one of the following values:
799   *            @arg RTC_FORMAT_BIN: Binary data format
800   *            @arg RTC_FORMAT_BCD: BCD data format
801   * @retval HAL status
802   */
HAL_RTC_GetTime(RTC_HandleTypeDef * hrtc,RTC_TimeTypeDef * sTime,uint32_t Format)803 HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
804 {
805   uint32_t counter_time = 0U, counter_alarm = 0U, days_elapsed = 0U, hours = 0U;
806 
807   /* Check input parameters */
808   if ((hrtc == NULL) || (sTime == NULL))
809   {
810     return HAL_ERROR;
811   }
812 
813   /* Check the parameters */
814   assert_param(IS_RTC_FORMAT(Format));
815 
816   /* Check if counter overflow occurred */
817   if (__HAL_RTC_OVERFLOW_GET_FLAG(hrtc, RTC_FLAG_OW))
818   {
819     return HAL_ERROR;
820   }
821 
822   /* Read the time counter*/
823   counter_time = RTC_ReadTimeCounter(hrtc);
824 
825   /* Fill the structure fields with the read parameters */
826   hours = counter_time / 3600U;
827   sTime->Minutes  = (uint8_t)((counter_time % 3600U) / 60U);
828   sTime->Seconds  = (uint8_t)((counter_time % 3600U) % 60U);
829 
830   if (hours >= 24U)
831   {
832     /* Get number of days elapsed from last calculation */
833     days_elapsed = (hours / 24U);
834 
835     /* Set Hours in RTC_TimeTypeDef structure*/
836     sTime->Hours = (hours % 24U);
837 
838     /* Read Alarm counter in RTC registers */
839     counter_alarm = RTC_ReadAlarmCounter(hrtc);
840 
841     /* Calculate remaining time to reach alarm (only if set and not yet expired)*/
842     if ((counter_alarm != RTC_ALARM_RESETVALUE) && (counter_alarm > counter_time))
843     {
844       counter_alarm -= counter_time;
845     }
846     else
847     {
848       /* In case of counter_alarm < counter_time */
849       /* Alarm expiration already occurred but alarm not deactivated */
850       counter_alarm = RTC_ALARM_RESETVALUE;
851     }
852 
853     /* Set updated time in decreasing counter by number of days elapsed */
854     counter_time -= (days_elapsed * 24U * 3600U);
855 
856     /* Write time counter in RTC registers */
857     if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
858     {
859       return HAL_ERROR;
860     }
861 
862     /* Set updated alarm to be set */
863     if (counter_alarm != RTC_ALARM_RESETVALUE)
864     {
865       counter_alarm += counter_time;
866 
867       /* Write time counter in RTC registers */
868       if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
869       {
870         return HAL_ERROR;
871       }
872     }
873     else
874     {
875       /* Alarm already occurred. Set it to reset values to avoid unexpected expiration */
876       if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
877       {
878         return HAL_ERROR;
879       }
880     }
881 
882     /* Update date */
883     RTC_DateUpdate(hrtc, days_elapsed);
884   }
885   else
886   {
887     sTime->Hours = hours;
888   }
889 
890   /* Check the input parameters format */
891   if (Format != RTC_FORMAT_BIN)
892   {
893     /* Convert the time structure parameters to BCD format */
894     sTime->Hours    = (uint8_t)RTC_ByteToBcd2(sTime->Hours);
895     sTime->Minutes  = (uint8_t)RTC_ByteToBcd2(sTime->Minutes);
896     sTime->Seconds  = (uint8_t)RTC_ByteToBcd2(sTime->Seconds);
897   }
898 
899   return HAL_OK;
900 }
901 
902 
903 /**
904   * @brief  Sets RTC current date.
905   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
906   *                the configuration information for RTC.
907   * @param  sDate: Pointer to date structure
908   * @param  Format: specifies the format of the entered parameters.
909   *          This parameter can be one of the following values:
910   *            @arg RTC_FORMAT_BIN: Binary data format
911   *            @arg RTC_FORMAT_BCD: BCD data format
912   * @retval HAL status
913   */
HAL_RTC_SetDate(RTC_HandleTypeDef * hrtc,RTC_DateTypeDef * sDate,uint32_t Format)914 HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
915 {
916   uint32_t counter_time = 0U, counter_alarm = 0U, hours = 0U;
917 
918   /* Check input parameters */
919   if ((hrtc == NULL) || (sDate == NULL))
920   {
921     return HAL_ERROR;
922   }
923 
924   /* Check the parameters */
925   assert_param(IS_RTC_FORMAT(Format));
926 
927   /* Process Locked */
928   __HAL_LOCK(hrtc);
929 
930   hrtc->State = HAL_RTC_STATE_BUSY;
931 
932   if (Format == RTC_FORMAT_BIN)
933   {
934     assert_param(IS_RTC_YEAR(sDate->Year));
935     assert_param(IS_RTC_MONTH(sDate->Month));
936     assert_param(IS_RTC_DATE(sDate->Date));
937 
938     /* Change the current date */
939     hrtc->DateToUpdate.Year  = sDate->Year;
940     hrtc->DateToUpdate.Month = sDate->Month;
941     hrtc->DateToUpdate.Date  = sDate->Date;
942   }
943   else
944   {
945     assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year)));
946     assert_param(IS_RTC_MONTH(RTC_Bcd2ToByte(sDate->Month)));
947     assert_param(IS_RTC_DATE(RTC_Bcd2ToByte(sDate->Date)));
948 
949     /* Change the current date */
950     hrtc->DateToUpdate.Year  = RTC_Bcd2ToByte(sDate->Year);
951     hrtc->DateToUpdate.Month = RTC_Bcd2ToByte(sDate->Month);
952     hrtc->DateToUpdate.Date  = RTC_Bcd2ToByte(sDate->Date);
953   }
954 
955   /* WeekDay set by user can be ignored because automatically calculated */
956   hrtc->DateToUpdate.WeekDay = RTC_WeekDayNum(hrtc->DateToUpdate.Year, hrtc->DateToUpdate.Month, hrtc->DateToUpdate.Date);
957   sDate->WeekDay = hrtc->DateToUpdate.WeekDay;
958 
959   /* Reset time to be aligned on the same day */
960   /* Read the time counter*/
961   counter_time = RTC_ReadTimeCounter(hrtc);
962 
963   /* Fill the structure fields with the read parameters */
964   hours = counter_time / 3600U;
965   if (hours > 24U)
966   {
967     /* Set updated time in decreasing counter by number of days elapsed */
968     counter_time -= ((hours / 24U) * 24U * 3600U);
969     /* Write time counter in RTC registers */
970     if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
971     {
972       /* Set RTC state */
973       hrtc->State = HAL_RTC_STATE_ERROR;
974 
975       /* Process Unlocked */
976       __HAL_UNLOCK(hrtc);
977 
978       return HAL_ERROR;
979     }
980 
981     /* Read current Alarm counter in RTC registers */
982     counter_alarm = RTC_ReadAlarmCounter(hrtc);
983 
984     /* Set again alarm to match with new time if enabled */
985     if (counter_alarm != RTC_ALARM_RESETVALUE)
986     {
987       if (counter_alarm < counter_time)
988       {
989         /* Add 1 day to alarm counter*/
990         counter_alarm += (uint32_t)(24U * 3600U);
991 
992         /* Write new Alarm counter in RTC registers */
993         if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
994         {
995           /* Set RTC state */
996           hrtc->State = HAL_RTC_STATE_ERROR;
997 
998           /* Process Unlocked */
999           __HAL_UNLOCK(hrtc);
1000 
1001           return HAL_ERROR;
1002         }
1003       }
1004     }
1005 
1006 
1007   }
1008 
1009   hrtc->State = HAL_RTC_STATE_READY ;
1010 
1011   /* Process Unlocked */
1012   __HAL_UNLOCK(hrtc);
1013 
1014   return HAL_OK;
1015 }
1016 
1017 /**
1018   * @brief  Gets RTC current date.
1019   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1020   *                the configuration information for RTC.
1021   * @param  sDate: Pointer to Date structure
1022   * @param  Format: Specifies the format of the entered parameters.
1023   *          This parameter can be one of the following values:
1024   *            @arg RTC_FORMAT_BIN:  Binary data format
1025   *            @arg RTC_FORMAT_BCD:  BCD data format
1026   * @retval HAL status
1027   */
HAL_RTC_GetDate(RTC_HandleTypeDef * hrtc,RTC_DateTypeDef * sDate,uint32_t Format)1028 HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
1029 {
1030   RTC_TimeTypeDef stime = {0U};
1031 
1032   /* Check input parameters */
1033   if ((hrtc == NULL) || (sDate == NULL))
1034   {
1035     return HAL_ERROR;
1036   }
1037 
1038   /* Check the parameters */
1039   assert_param(IS_RTC_FORMAT(Format));
1040 
1041   /* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
1042   if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
1043   {
1044     return HAL_ERROR;
1045   }
1046 
1047   /* Fill the structure fields with the read parameters */
1048   sDate->WeekDay  = hrtc->DateToUpdate.WeekDay;
1049   sDate->Year     = hrtc->DateToUpdate.Year;
1050   sDate->Month    = hrtc->DateToUpdate.Month;
1051   sDate->Date     = hrtc->DateToUpdate.Date;
1052 
1053   /* Check the input parameters format */
1054   if (Format != RTC_FORMAT_BIN)
1055   {
1056     /* Convert the date structure parameters to BCD format */
1057     sDate->Year   = (uint8_t)RTC_ByteToBcd2(sDate->Year);
1058     sDate->Month  = (uint8_t)RTC_ByteToBcd2(sDate->Month);
1059     sDate->Date   = (uint8_t)RTC_ByteToBcd2(sDate->Date);
1060   }
1061   return HAL_OK;
1062 }
1063 
1064 /**
1065   * @}
1066   */
1067 
1068 /** @defgroup RTC_Exported_Functions_Group3 Alarm functions
1069  *  @brief   RTC Alarm functions
1070  *
1071 @verbatim
1072  ===============================================================================
1073                  ##### RTC Alarm functions #####
1074  ===============================================================================
1075 
1076  [..] This section provides functions allowing to configure Alarm feature
1077 
1078 @endverbatim
1079   * @{
1080   */
1081 
1082 /**
1083   * @brief  Sets the specified RTC Alarm.
1084   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1085   *                the configuration information for RTC.
1086   * @param  sAlarm: Pointer to Alarm structure
1087   * @param  Format: Specifies the format of the entered parameters.
1088   *          This parameter can be one of the following values:
1089   *             @arg RTC_FORMAT_BIN: Binary data format
1090   *             @arg RTC_FORMAT_BCD: BCD data format
1091   * @retval HAL status
1092   */
HAL_RTC_SetAlarm(RTC_HandleTypeDef * hrtc,RTC_AlarmTypeDef * sAlarm,uint32_t Format)1093 HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
1094 {
1095   uint32_t counter_alarm = 0U, counter_time;
1096   RTC_TimeTypeDef stime = {0U};
1097 
1098   /* Check input parameters */
1099   if ((hrtc == NULL) || (sAlarm == NULL))
1100   {
1101     return HAL_ERROR;
1102   }
1103 
1104   /* Check the parameters */
1105   assert_param(IS_RTC_FORMAT(Format));
1106   assert_param(IS_RTC_ALARM(sAlarm->Alarm));
1107 
1108   /* Process Locked */
1109   __HAL_LOCK(hrtc);
1110 
1111   hrtc->State = HAL_RTC_STATE_BUSY;
1112 
1113   /* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
1114   if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
1115   {
1116     return HAL_ERROR;
1117   }
1118 
1119   /* Convert time in seconds */
1120   counter_time = (uint32_t)(((uint32_t)stime.Hours * 3600U) + \
1121                             ((uint32_t)stime.Minutes * 60U) + \
1122                             ((uint32_t)stime.Seconds));
1123 
1124   if (Format == RTC_FORMAT_BIN)
1125   {
1126     assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
1127     assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
1128     assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
1129 
1130     counter_alarm = (uint32_t)(((uint32_t)sAlarm->AlarmTime.Hours * 3600U) + \
1131                                ((uint32_t)sAlarm->AlarmTime.Minutes * 60U) + \
1132                                ((uint32_t)sAlarm->AlarmTime.Seconds));
1133   }
1134   else
1135   {
1136     assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
1137     assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
1138     assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
1139 
1140     counter_alarm = (((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)) * 3600U) + \
1141                      ((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)) * 60U) + \
1142                      ((uint32_t)RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
1143   }
1144 
1145   /* Check that requested alarm should expire in the same day (otherwise add 1 day) */
1146   if (counter_alarm < counter_time)
1147   {
1148     /* Add 1 day to alarm counter*/
1149     counter_alarm += (uint32_t)(24U * 3600U);
1150   }
1151 
1152   /* Write Alarm counter in RTC registers */
1153   if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
1154   {
1155     /* Set RTC state */
1156     hrtc->State = HAL_RTC_STATE_ERROR;
1157 
1158     /* Process Unlocked */
1159     __HAL_UNLOCK(hrtc);
1160 
1161     return HAL_ERROR;
1162   }
1163   else
1164   {
1165     hrtc->State = HAL_RTC_STATE_READY;
1166 
1167     __HAL_UNLOCK(hrtc);
1168 
1169     return HAL_OK;
1170   }
1171 }
1172 
1173 /**
1174   * @brief  Sets the specified RTC Alarm with Interrupt
1175   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1176   *                the configuration information for RTC.
1177   * @param  sAlarm: Pointer to Alarm structure
1178   * @param  Format: Specifies the format of the entered parameters.
1179   *          This parameter can be one of the following values:
1180   *             @arg RTC_FORMAT_BIN: Binary data format
1181   *             @arg RTC_FORMAT_BCD: BCD data format
1182   * @note   The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
1183   * @retval HAL status
1184   */
HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef * hrtc,RTC_AlarmTypeDef * sAlarm,uint32_t Format)1185 HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
1186 {
1187   uint32_t counter_alarm = 0U, counter_time;
1188   RTC_TimeTypeDef stime = {0U};
1189 
1190   /* Check input parameters */
1191   if ((hrtc == NULL) || (sAlarm == NULL))
1192   {
1193     return HAL_ERROR;
1194   }
1195 
1196   /* Check the parameters */
1197   assert_param(IS_RTC_FORMAT(Format));
1198   assert_param(IS_RTC_ALARM(sAlarm->Alarm));
1199 
1200   /* Process Locked */
1201   __HAL_LOCK(hrtc);
1202 
1203   hrtc->State = HAL_RTC_STATE_BUSY;
1204 
1205   /* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
1206   if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
1207   {
1208     return HAL_ERROR;
1209   }
1210 
1211   /* Convert time in seconds */
1212   counter_time = (uint32_t)(((uint32_t)stime.Hours * 3600U) + \
1213                             ((uint32_t)stime.Minutes * 60U) + \
1214                             ((uint32_t)stime.Seconds));
1215 
1216   if (Format == RTC_FORMAT_BIN)
1217   {
1218     assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
1219     assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
1220     assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
1221 
1222     counter_alarm = (uint32_t)(((uint32_t)sAlarm->AlarmTime.Hours * 3600U) + \
1223                                ((uint32_t)sAlarm->AlarmTime.Minutes * 60U) + \
1224                                ((uint32_t)sAlarm->AlarmTime.Seconds));
1225   }
1226   else
1227   {
1228     assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
1229     assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
1230     assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
1231 
1232     counter_alarm = (((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)) * 3600U) + \
1233                      ((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)) * 60U) + \
1234                      ((uint32_t)RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
1235   }
1236 
1237   /* Check that requested alarm should expire in the same day (otherwise add 1 day) */
1238   if (counter_alarm < counter_time)
1239   {
1240     /* Add 1 day to alarm counter*/
1241     counter_alarm += (uint32_t)(24U * 3600U);
1242   }
1243 
1244   /* Write alarm counter in RTC registers */
1245   if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
1246   {
1247     /* Set RTC state */
1248     hrtc->State = HAL_RTC_STATE_ERROR;
1249 
1250     /* Process Unlocked */
1251     __HAL_UNLOCK(hrtc);
1252 
1253     return HAL_ERROR;
1254   }
1255   else
1256   {
1257     /* Clear flag alarm A */
1258     __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
1259 
1260     /* Configure the Alarm interrupt */
1261     __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRA);
1262 
1263     /* RTC Alarm Interrupt Configuration: EXTI configuration */
1264     __HAL_RTC_ALARM_EXTI_ENABLE_IT();
1265 
1266     __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
1267 
1268     hrtc->State = HAL_RTC_STATE_READY;
1269 
1270     __HAL_UNLOCK(hrtc);
1271 
1272     return HAL_OK;
1273   }
1274 }
1275 
1276 /**
1277   * @brief  Gets the RTC Alarm value and masks.
1278   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1279   *                the configuration information for RTC.
1280   * @param  sAlarm: Pointer to Date structure
1281   * @param  Alarm: Specifies the Alarm.
1282   *          This parameter can be one of the following values:
1283   *             @arg RTC_ALARM_A: Alarm
1284   * @param  Format: Specifies the format of the entered parameters.
1285   *          This parameter can be one of the following values:
1286   *             @arg RTC_FORMAT_BIN: Binary data format
1287   *             @arg RTC_FORMAT_BCD: BCD data format
1288   * @retval HAL status
1289   */
HAL_RTC_GetAlarm(RTC_HandleTypeDef * hrtc,RTC_AlarmTypeDef * sAlarm,uint32_t Alarm,uint32_t Format)1290 HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format)
1291 {
1292   uint32_t counter_alarm = 0U;
1293 
1294   /* Prevent unused argument(s) compilation warning */
1295   UNUSED(Alarm);
1296 
1297   /* Check input parameters */
1298   if ((hrtc == NULL) || (sAlarm == NULL))
1299   {
1300     return HAL_ERROR;
1301   }
1302 
1303   /* Check the parameters */
1304   assert_param(IS_RTC_FORMAT(Format));
1305   assert_param(IS_RTC_ALARM(Alarm));
1306 
1307   /* Read Alarm counter in RTC registers */
1308   counter_alarm = RTC_ReadAlarmCounter(hrtc);
1309 
1310   /* Fill the structure with the read parameters */
1311   /* Set hours in a day range (between 0 to 24)*/
1312   sAlarm->AlarmTime.Hours   = (uint32_t)((counter_alarm / 3600U) % 24U);
1313   sAlarm->AlarmTime.Minutes = (uint32_t)((counter_alarm % 3600U) / 60U);
1314   sAlarm->AlarmTime.Seconds = (uint32_t)((counter_alarm % 3600U) % 60U);
1315 
1316   if (Format != RTC_FORMAT_BIN)
1317   {
1318     sAlarm->AlarmTime.Hours   = RTC_ByteToBcd2(sAlarm->AlarmTime.Hours);
1319     sAlarm->AlarmTime.Minutes = RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes);
1320     sAlarm->AlarmTime.Seconds = RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds);
1321   }
1322 
1323   return HAL_OK;
1324 }
1325 
1326 /**
1327   * @brief  Deactivate the specified RTC Alarm
1328   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1329   *                the configuration information for RTC.
1330   * @param  Alarm: Specifies the Alarm.
1331   *          This parameter can be one of the following values:
1332   *            @arg RTC_ALARM_A:  AlarmA
1333   * @retval HAL status
1334   */
HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef * hrtc,uint32_t Alarm)1335 HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm)
1336 {
1337   /* Prevent unused argument(s) compilation warning */
1338   UNUSED(Alarm);
1339 
1340   /* Check the parameters */
1341   assert_param(IS_RTC_ALARM(Alarm));
1342 
1343   /* Check input parameters */
1344   if (hrtc == NULL)
1345   {
1346     return HAL_ERROR;
1347   }
1348 
1349   /* Process Locked */
1350   __HAL_LOCK(hrtc);
1351 
1352   hrtc->State = HAL_RTC_STATE_BUSY;
1353 
1354   /* In case of interrupt mode is used, the interrupt source must disabled */
1355   __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
1356 
1357   /* Set Initialization mode */
1358   if (RTC_EnterInitMode(hrtc) != HAL_OK)
1359   {
1360     /* Set RTC state */
1361     hrtc->State = HAL_RTC_STATE_ERROR;
1362 
1363     /* Process Unlocked */
1364     __HAL_UNLOCK(hrtc);
1365 
1366     return HAL_ERROR;
1367   }
1368   else
1369   {
1370     /* Clear flag alarm A */
1371     __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
1372 
1373     /* Set to default values ALRH & ALRL registers */
1374     WRITE_REG(hrtc->Instance->ALRH, RTC_ALARM_RESETVALUE_REGISTER);
1375     WRITE_REG(hrtc->Instance->ALRL, RTC_ALARM_RESETVALUE_REGISTER);
1376 
1377     /* RTC Alarm Interrupt Configuration: Disable EXTI configuration */
1378     __HAL_RTC_ALARM_EXTI_DISABLE_IT();
1379 
1380     /* Wait for synchro */
1381     if (RTC_ExitInitMode(hrtc) != HAL_OK)
1382     {
1383       hrtc->State = HAL_RTC_STATE_ERROR;
1384 
1385       /* Process Unlocked */
1386       __HAL_UNLOCK(hrtc);
1387 
1388       return HAL_ERROR;
1389     }
1390   }
1391   hrtc->State = HAL_RTC_STATE_READY;
1392 
1393   /* Process Unlocked */
1394   __HAL_UNLOCK(hrtc);
1395 
1396   return HAL_OK;
1397 }
1398 
1399 /**
1400   * @brief  This function handles Alarm interrupt request.
1401   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1402   *                the configuration information for RTC.
1403   * @retval None
1404   */
HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef * hrtc)1405 void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc)
1406 {
1407   if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA))
1408   {
1409     /* Get the status of the Interrupt */
1410     if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != (uint32_t)RESET)
1411     {
1412       /* AlarmA callback */
1413 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
1414       hrtc->AlarmAEventCallback(hrtc);
1415 #else
1416       HAL_RTC_AlarmAEventCallback(hrtc);
1417 #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
1418 
1419       /* Clear the Alarm interrupt pending bit */
1420       __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
1421     }
1422   }
1423 
1424   /* Clear the EXTI's line Flag for RTC Alarm */
1425   __HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
1426 
1427   /* Change RTC state */
1428   hrtc->State = HAL_RTC_STATE_READY;
1429 }
1430 
1431 /**
1432   * @brief  Alarm A callback.
1433   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1434   *                the configuration information for RTC.
1435   * @retval None
1436   */
HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef * hrtc)1437 __weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
1438 {
1439   /* Prevent unused argument(s) compilation warning */
1440   UNUSED(hrtc);
1441   /* NOTE : This function Should not be modified, when the callback is needed,
1442             the HAL_RTC_AlarmAEventCallback could be implemented in the user file
1443    */
1444 }
1445 
1446 /**
1447   * @brief  This function handles AlarmA Polling request.
1448   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1449   *                the configuration information for RTC.
1450   * @param  Timeout: Timeout duration
1451   * @retval HAL status
1452   */
HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef * hrtc,uint32_t Timeout)1453 HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
1454 {
1455   uint32_t tickstart = HAL_GetTick();
1456 
1457   /* Check input parameters */
1458   if (hrtc == NULL)
1459   {
1460     return HAL_ERROR;
1461   }
1462 
1463   while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == RESET)
1464   {
1465     if (Timeout != HAL_MAX_DELAY)
1466     {
1467       if ((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout))
1468       {
1469         hrtc->State = HAL_RTC_STATE_TIMEOUT;
1470         return HAL_TIMEOUT;
1471       }
1472     }
1473   }
1474 
1475   /* Clear the Alarm interrupt pending bit */
1476   __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
1477 
1478   /* Change RTC state */
1479   hrtc->State = HAL_RTC_STATE_READY;
1480 
1481   return HAL_OK;
1482 }
1483 
1484 /**
1485   * @}
1486   */
1487 
1488 /** @defgroup RTC_Exported_Functions_Group4 Peripheral State functions
1489  *  @brief   Peripheral State functions
1490  *
1491 @verbatim
1492  ===============================================================================
1493                      ##### Peripheral State functions #####
1494  ===============================================================================
1495     [..]
1496     This subsection provides functions allowing to
1497       (+) Get RTC state
1498 
1499 @endverbatim
1500   * @{
1501   */
1502 /**
1503   * @brief  Returns the RTC state.
1504   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1505   *                the configuration information for RTC.
1506   * @retval HAL state
1507   */
HAL_RTC_GetState(RTC_HandleTypeDef * hrtc)1508 HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc)
1509 {
1510   return hrtc->State;
1511 }
1512 
1513 /**
1514   * @}
1515   */
1516 
1517 /** @defgroup RTC_Exported_Functions_Group5 Peripheral Control functions
1518  *  @brief   Peripheral Control functions
1519  *
1520 @verbatim
1521  ===============================================================================
1522                      ##### Peripheral Control functions #####
1523  ===============================================================================
1524     [..]
1525     This subsection provides functions allowing to
1526       (+) Wait for RTC Time and Date Synchronization
1527 
1528 @endverbatim
1529   * @{
1530   */
1531 
1532 /**
1533   * @brief  Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL)
1534   *   are synchronized with RTC APB clock.
1535   * @note   This function must be called before any read operation after an APB reset
1536   *   or an APB clock stop.
1537   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1538   *                the configuration information for RTC.
1539   * @retval HAL status
1540   */
HAL_RTC_WaitForSynchro(RTC_HandleTypeDef * hrtc)1541 HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc)
1542 {
1543   uint32_t tickstart = 0U;
1544 
1545   /* Check input parameters */
1546   if (hrtc == NULL)
1547   {
1548     return HAL_ERROR;
1549   }
1550 
1551   /* Clear RSF flag */
1552   CLEAR_BIT(hrtc->Instance->CRL, RTC_FLAG_RSF);
1553 
1554   tickstart = HAL_GetTick();
1555 
1556   /* Wait the registers to be synchronised */
1557   while ((hrtc->Instance->CRL & RTC_FLAG_RSF) == (uint32_t)RESET)
1558   {
1559     if ((HAL_GetTick() - tickstart) >  RTC_TIMEOUT_VALUE)
1560     {
1561       return HAL_TIMEOUT;
1562     }
1563   }
1564 
1565   return HAL_OK;
1566 }
1567 
1568 /**
1569   * @}
1570   */
1571 
1572 
1573 /**
1574   * @}
1575   */
1576 
1577 /** @addtogroup RTC_Private_Functions
1578   * @{
1579   */
1580 
1581 
1582 /**
1583   * @brief  Read the time counter available in RTC_CNT registers.
1584   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1585   *                the configuration information for RTC.
1586   * @retval Time counter
1587   */
RTC_ReadTimeCounter(RTC_HandleTypeDef * hrtc)1588 static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef *hrtc)
1589 {
1590   uint16_t high1 = 0U, high2 = 0U, low = 0U;
1591   uint32_t timecounter = 0U;
1592 
1593   high1 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
1594   low   = READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT);
1595   high2 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
1596 
1597   if (high1 != high2)
1598   {
1599     /* In this case the counter roll over during reading of CNTL and CNTH registers,
1600        read again CNTL register then return the counter value */
1601     timecounter = (((uint32_t) high2 << 16U) | READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT));
1602   }
1603   else
1604   {
1605     /* No counter roll over during reading of CNTL and CNTH registers, counter
1606        value is equal to first value of CNTL and CNTH */
1607     timecounter = (((uint32_t) high1 << 16U) | low);
1608   }
1609 
1610   return timecounter;
1611 }
1612 
1613 /**
1614   * @brief  Write the time counter in RTC_CNT registers.
1615   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1616   *                the configuration information for RTC.
1617   * @param  TimeCounter: Counter to write in RTC_CNT registers
1618   * @retval HAL status
1619   */
RTC_WriteTimeCounter(RTC_HandleTypeDef * hrtc,uint32_t TimeCounter)1620 static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef *hrtc, uint32_t TimeCounter)
1621 {
1622   HAL_StatusTypeDef status = HAL_OK;
1623 
1624   /* Set Initialization mode */
1625   if (RTC_EnterInitMode(hrtc) != HAL_OK)
1626   {
1627     status = HAL_ERROR;
1628   }
1629   else
1630   {
1631     /* Set RTC COUNTER MSB word */
1632     WRITE_REG(hrtc->Instance->CNTH, (TimeCounter >> 16U));
1633     /* Set RTC COUNTER LSB word */
1634     WRITE_REG(hrtc->Instance->CNTL, (TimeCounter & RTC_CNTL_RTC_CNT));
1635 
1636     /* Wait for synchro */
1637     if (RTC_ExitInitMode(hrtc) != HAL_OK)
1638     {
1639       status = HAL_ERROR;
1640     }
1641   }
1642 
1643   return status;
1644 }
1645 
1646 /**
1647   * @brief  Read the time counter available in RTC_ALR registers.
1648   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1649   *                the configuration information for RTC.
1650   * @retval Time counter
1651   */
RTC_ReadAlarmCounter(RTC_HandleTypeDef * hrtc)1652 static uint32_t RTC_ReadAlarmCounter(RTC_HandleTypeDef *hrtc)
1653 {
1654   uint16_t high1 = 0U, low = 0U;
1655 
1656   high1 = READ_REG(hrtc->Instance->ALRH & RTC_CNTH_RTC_CNT);
1657   low   = READ_REG(hrtc->Instance->ALRL & RTC_CNTL_RTC_CNT);
1658 
1659   return (((uint32_t) high1 << 16U) | low);
1660 }
1661 
1662 /**
1663   * @brief  Write the time counter in RTC_ALR registers.
1664   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1665   *                the configuration information for RTC.
1666   * @param  AlarmCounter: Counter to write in RTC_ALR registers
1667   * @retval HAL status
1668   */
RTC_WriteAlarmCounter(RTC_HandleTypeDef * hrtc,uint32_t AlarmCounter)1669 static HAL_StatusTypeDef RTC_WriteAlarmCounter(RTC_HandleTypeDef *hrtc, uint32_t AlarmCounter)
1670 {
1671   HAL_StatusTypeDef status = HAL_OK;
1672 
1673   /* Set Initialization mode */
1674   if (RTC_EnterInitMode(hrtc) != HAL_OK)
1675   {
1676     status = HAL_ERROR;
1677   }
1678   else
1679   {
1680     /* Set RTC COUNTER MSB word */
1681     WRITE_REG(hrtc->Instance->ALRH, (AlarmCounter >> 16U));
1682     /* Set RTC COUNTER LSB word */
1683     WRITE_REG(hrtc->Instance->ALRL, (AlarmCounter & RTC_ALRL_RTC_ALR));
1684 
1685     /* Wait for synchro */
1686     if (RTC_ExitInitMode(hrtc) != HAL_OK)
1687     {
1688       status = HAL_ERROR;
1689     }
1690   }
1691 
1692   return status;
1693 }
1694 
1695 /**
1696   * @brief  Enters the RTC Initialization mode.
1697   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1698   *                the configuration information for RTC.
1699   * @retval HAL status
1700   */
RTC_EnterInitMode(RTC_HandleTypeDef * hrtc)1701 static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
1702 {
1703   uint32_t tickstart = 0U;
1704 
1705   tickstart = HAL_GetTick();
1706   /* Wait till RTC is in INIT state and if Time out is reached exit */
1707   while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
1708   {
1709     if ((HAL_GetTick() - tickstart) >  RTC_TIMEOUT_VALUE)
1710     {
1711       return HAL_TIMEOUT;
1712     }
1713   }
1714 
1715   /* Disable the write protection for RTC registers */
1716   __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
1717 
1718 
1719   return HAL_OK;
1720 }
1721 
1722 /**
1723   * @brief  Exit the RTC Initialization mode.
1724   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1725   *                the configuration information for RTC.
1726   * @retval HAL status
1727   */
RTC_ExitInitMode(RTC_HandleTypeDef * hrtc)1728 static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc)
1729 {
1730   uint32_t tickstart = 0U;
1731 
1732   /* Disable the write protection for RTC registers */
1733   __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
1734 
1735   tickstart = HAL_GetTick();
1736   /* Wait till RTC is in INIT state and if Time out is reached exit */
1737   while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
1738   {
1739     if ((HAL_GetTick() - tickstart) >  RTC_TIMEOUT_VALUE)
1740     {
1741       return HAL_TIMEOUT;
1742     }
1743   }
1744 
1745   return HAL_OK;
1746 }
1747 
1748 /**
1749   * @brief  Converts a 2 digit decimal to BCD format.
1750   * @param  Value: Byte to be converted
1751   * @retval Converted byte
1752   */
RTC_ByteToBcd2(uint8_t Value)1753 static uint8_t RTC_ByteToBcd2(uint8_t Value)
1754 {
1755   uint32_t bcdhigh = 0U;
1756 
1757   while (Value >= 10U)
1758   {
1759     bcdhigh++;
1760     Value -= 10U;
1761   }
1762 
1763   return ((uint8_t)(bcdhigh << 4U) | Value);
1764 }
1765 
1766 /**
1767   * @brief  Converts from 2 digit BCD to Binary.
1768   * @param  Value: BCD value to be converted
1769   * @retval Converted word
1770   */
RTC_Bcd2ToByte(uint8_t Value)1771 static uint8_t RTC_Bcd2ToByte(uint8_t Value)
1772 {
1773   uint32_t tmp = 0U;
1774   tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10U;
1775   return (tmp + (Value & (uint8_t)0x0F));
1776 }
1777 
1778 /**
1779   * @brief  Updates date when time is 23:59:59.
1780   * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
1781   *                the configuration information for RTC.
1782   * @param  DayElapsed: Number of days elapsed from last date update
1783   * @retval None
1784   */
RTC_DateUpdate(RTC_HandleTypeDef * hrtc,uint32_t DayElapsed)1785 static void RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed)
1786 {
1787   uint32_t year = 0U, month = 0U, day = 0U;
1788   uint32_t loop = 0U;
1789 
1790   /* Get the current year*/
1791   year = hrtc->DateToUpdate.Year;
1792 
1793   /* Get the current month and day */
1794   month = hrtc->DateToUpdate.Month;
1795   day = hrtc->DateToUpdate.Date;
1796 
1797   for (loop = 0U; loop < DayElapsed; loop++)
1798   {
1799     if ((month == 1U) || (month == 3U) || (month == 5U) || (month == 7U) || \
1800         (month == 8U) || (month == 10U) || (month == 12U))
1801     {
1802       if (day < 31U)
1803       {
1804         day++;
1805       }
1806       /* Date structure member: day = 31 */
1807       else
1808       {
1809         if (month != 12U)
1810         {
1811           month++;
1812           day = 1U;
1813         }
1814         /* Date structure member: day = 31 & month =12 */
1815         else
1816         {
1817           month = 1U;
1818           day = 1U;
1819           year++;
1820         }
1821       }
1822     }
1823     else if ((month == 4U) || (month == 6U) || (month == 9U) || (month == 11U))
1824     {
1825       if (day < 30U)
1826       {
1827         day++;
1828       }
1829       /* Date structure member: day = 30 */
1830       else
1831       {
1832         month++;
1833         day = 1U;
1834       }
1835     }
1836     else if (month == 2U)
1837     {
1838       if (day < 28U)
1839       {
1840         day++;
1841       }
1842       else if (day == 28U)
1843       {
1844         /* Leap year */
1845         if (RTC_IsLeapYear(year))
1846         {
1847           day++;
1848         }
1849         else
1850         {
1851           month++;
1852           day = 1U;
1853         }
1854       }
1855       else if (day == 29U)
1856       {
1857         month++;
1858         day = 1U;
1859       }
1860     }
1861   }
1862 
1863   /* Update year */
1864   hrtc->DateToUpdate.Year = year;
1865 
1866   /* Update day and month */
1867   hrtc->DateToUpdate.Month = month;
1868   hrtc->DateToUpdate.Date = day;
1869 
1870   /* Update day of the week */
1871   hrtc->DateToUpdate.WeekDay = RTC_WeekDayNum(year, month, day);
1872 }
1873 
1874 /**
1875   * @brief  Check whether the passed year is Leap or not.
1876   * @param  nYear  year to check
1877   * @retval 1: leap year
1878   *         0: not leap year
1879   */
RTC_IsLeapYear(uint16_t nYear)1880 static uint8_t RTC_IsLeapYear(uint16_t nYear)
1881 {
1882   if ((nYear % 4U) != 0U)
1883   {
1884     return 0U;
1885   }
1886 
1887   if ((nYear % 100U) != 0U)
1888   {
1889     return 1U;
1890   }
1891 
1892   if ((nYear % 400U) == 0U)
1893   {
1894     return 1U;
1895   }
1896   else
1897   {
1898     return 0U;
1899   }
1900 }
1901 
1902 /**
1903   * @brief  Determines the week number, the day number and the week day number.
1904   * @param  nYear   year to check
1905   * @param  nMonth  Month to check
1906   * @param  nDay    Day to check
1907   * @note   Day is calculated with hypothesis that year > 2000
1908   * @retval Value which can take one of the following parameters:
1909   *         @arg RTC_WEEKDAY_MONDAY
1910   *         @arg RTC_WEEKDAY_TUESDAY
1911   *         @arg RTC_WEEKDAY_WEDNESDAY
1912   *         @arg RTC_WEEKDAY_THURSDAY
1913   *         @arg RTC_WEEKDAY_FRIDAY
1914   *         @arg RTC_WEEKDAY_SATURDAY
1915   *         @arg RTC_WEEKDAY_SUNDAY
1916   */
RTC_WeekDayNum(uint32_t nYear,uint8_t nMonth,uint8_t nDay)1917 static uint8_t RTC_WeekDayNum(uint32_t nYear, uint8_t nMonth, uint8_t nDay)
1918 {
1919   uint32_t year = 0U, weekday = 0U;
1920 
1921   year = 2000U + nYear;
1922 
1923   if (nMonth < 3U)
1924   {
1925     /*D = { [(23 x month)/9] + day + 4 + year + [(year-1)/4] - [(year-1)/100] + [(year-1)/400] } mod 7*/
1926     weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + ((year - 1U) / 4U) - ((year - 1U) / 100U) + ((year - 1U) / 400U)) % 7U;
1927   }
1928   else
1929   {
1930     /*D = { [(23 x month)/9] + day + 4 + year + [year/4] - [year/100] + [year/400] - 2 } mod 7*/
1931     weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + (year / 4U) - (year / 100U) + (year / 400U) - 2U) % 7U;
1932   }
1933 
1934   return (uint8_t)weekday;
1935 }
1936 
1937 /**
1938   * @}
1939   */
1940 
1941 #endif /* HAL_RTC_MODULE_ENABLED */
1942 /**
1943   * @}
1944   */
1945 
1946 /**
1947   * @}
1948   */
1949