Subversion Repositories LedShow

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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