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