1 /**
2   ******************************************************************************
3   * @file    stm32l5xx_hal_timebase_rtc_wakeup_template.c
4   * @author  MCD Application Team
5   * @brief   HAL time base based on the hardware RTC_WAKEUP Template.
6   *
7   *          This file overrides the native HAL time base functions (defined as weak)
8   *          to use the RTC WAKEUP for the time base generation:
9   *           + Initializes the RTC peripheral and configures the wakeup timer to be
10   *             incremented each 1ms when uwTickFreq is set to default value, else
11   *              10 ms or 100 ms, depending of above global variable value.
12   *           + HAL_IncTick is called inside the HAL_RTCEx_WakeUpTimerEventCallback
13   *           + HSE (default), LSE or LSI can be selected as RTC clock source
14   *
15   ******************************************************************************
16   * @attention
17   *
18   * Copyright (c) 2019 STMicroelectronics.
19   * All rights reserved.
20   *
21   * This software is licensed under terms that can be found in the LICENSE file
22   * in the root directory of this software component.
23   * If no LICENSE file comes with this software, it is provided AS-IS.
24   *
25   ******************************************************************************
26  @verbatim
27   ==============================================================================
28                         ##### How to use this driver #####
29   ==============================================================================
30     [..]
31     This file must be copied to the application folder and modified as follows:
32     (#) Rename it to 'stm32l5xx_hal_timebase_rtc_wakeup.c'
33     (#) Add this file and the RTC HAL drivers to your project and uncomment
34        HAL_RTC_MODULE_ENABLED define in stm32l5xx_hal_conf.h
35 
36   @endverbatim
37   ******************************************************************************
38   */
39 
40 /* Includes ------------------------------------------------------------------*/
41 #include "stm32l5xx_hal.h"
42 
43 /** @addtogroup STM32L5xx_HAL_Driver
44   * @{
45   */
46 
47 /** @defgroup HAL_TimeBase_RTC_WakeUp_Template  HAL TimeBase RTC WakeUp Template
48   * @{
49   */
50 
51 /* Private typedef -----------------------------------------------------------*/
52 /* Private define ------------------------------------------------------------*/
53 
54 /* Uncomment the line below to select the appropriate RTC Clock source for your application:
55   + RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision.
56   + RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing
57                           precision.
58   + RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing
59                           precision.
60   */
61 #define RTC_CLOCK_SOURCE_HSE
62 /* #define RTC_CLOCK_SOURCE_LSE */
63 /* #define RTC_CLOCK_SOURCE_LSI */
64 
65 #ifdef RTC_CLOCK_SOURCE_HSE
66 #define RTC_ASYNCH_PREDIV       99U
67 #define RTC_SYNCH_PREDIV        4U
68 #else /* RTC_CLOCK_SOURCE_LSE || RTC_CLOCK_SOURCE_LSI */
69 #define RTC_ASYNCH_PREDIV       31U
70 #define RTC_SYNCH_PREDIV        0U
71 #endif /* RTC_CLOCK_SOURCE_HSE */
72 
73 /* Private macro -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 RTC_HandleTypeDef hRTC_Handle = {.Init = {0}};
76 
77 /* Private function prototypes -----------------------------------------------*/
78 void RTC_IRQHandler(void);
79 
80 /* Private functions ---------------------------------------------------------*/
81 
82 /**
83   * @brief  This function configures the RTC wakeup timer as a time base source.
84   *         The time source is configured  to have 1ms time base with a dedicated
85   *         Tick interrupt priority.
86   *         Wakeup Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK
87                              = 1ms
88   *         Wakeup Time = WakeupTimebase * WakeUpCounter (0 + 1)
89                         = 1 ms
90   * @note   This function is called  automatically at the beginning of program after
91   *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
92   * @param  TickPriority Tick interrupt priority.
93   * @retval HAL status
94   */
HAL_InitTick(uint32_t TickPriority)95 HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
96 {
97   HAL_StatusTypeDef status;
98   __IO uint32_t counter = 0U;
99 
100   RCC_OscInitTypeDef        RCC_OscInitStruct;
101   RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
102 
103 
104   /* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
105   if ((uint32_t)uwTickFreq != 0U)
106   {
107 #ifdef RTC_CLOCK_SOURCE_LSE
108     /* Configure LSE as RTC clock source */
109     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
110     RCC_OscInitStruct.LSEState = RCC_LSE_ON_RTC_ONLY;
111     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
112 
113     PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
114 #elif defined (RTC_CLOCK_SOURCE_LSI)
115     /* Configure LSI as RTC clock source */
116     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
117     RCC_OscInitStruct.LSIState = RCC_LSI_ON;
118     RCC_OscInitStruct.LSIDiv = RCC_LSI_DIV1;
119     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
120 
121     PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
122 #elif defined (RTC_CLOCK_SOURCE_HSE)
123     /* Configure HSE as RTC clock source */
124     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
125     RCC_OscInitStruct.HSEState = RCC_HSE_ON;
126     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
127 
128     PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;
129 #else
130 #error Please select the RTC Clock source
131 #endif /* RTC_CLOCK_SOURCE_LSE */
132 
133     status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
134     if(status == HAL_OK)
135     {
136       PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
137       status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
138 
139       /* Enable RTC Clock */
140       if(status == HAL_OK)
141       {
142         /* Enable RTC Clock */
143         __HAL_RCC_RTC_ENABLE();
144         __HAL_RCC_RTCAPB_CLK_ENABLE();
145 
146         /* The time base should be 1ms
147            Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK
148            HSE as RTC clock
149              Time base = ((99 + 1) * (4 + 1)) / 500kHz
150                        = 1ms
151            LSE as RTC clock
152              Time base = ((31 + 1) * (0 + 1)) / 32.768kHz
153                        = ~1ms
154            LSI as RTC clock
155              Time base = ((31 + 1) * (0 + 1)) / 32kHz
156                        = 1ms
157         */
158         hRTC_Handle.Instance = RTC;
159         hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24;
160         hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
161         hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
162         hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE;
163         hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
164         hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
165         status = HAL_RTC_Init(&hRTC_Handle);
166         if(status == HAL_OK)
167         {
168           /* Disable the write protection for RTC registers */
169           __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
170 
171           /* Disable the Wake-up Timer */
172           __HAL_RTC_WAKEUPTIMER_DISABLE(&hRTC_Handle);
173 
174           /* In case of interrupt mode is used, the interrupt source must disabled */
175           __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hRTC_Handle, RTC_IT_WUT);
176 
177           /* Wait till RTC WUTWF flag is set  */
178           while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hRTC_Handle, RTC_FLAG_WUTWF) == 0U)
179           {
180             counter++;
181             if (counter == (SystemCoreClock / 56U))
182             {
183               status = HAL_ERROR;
184               break;
185             }
186           }
187 
188           if(status == HAL_OK)
189           {
190             /* Clear PWR wake up Flag */
191             __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
192 
193             /* Clear RTC Wake Up timer Flag */
194             __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_WUTF);
195 
196             /* Configure the Wake-up Timer counter */
197             hRTC_Handle.Instance->WUTR = 0U;
198 
199             /* Clear the Wake-up Timer clock source bits in CR register */
200             hRTC_Handle.Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL;
201 
202             /* Configure the clock source */
203             hRTC_Handle.Instance->CR |= (uint32_t)RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
204 
205             /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */
206             __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
207 
208             /* Configure the Interrupt in the RTC_CR register */
209             __HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hRTC_Handle, RTC_IT_WUT);
210 
211             /* Enable the Wake-up Timer */
212             __HAL_RTC_WAKEUPTIMER_ENABLE(&hRTC_Handle);
213 
214             /* Enable the write protection for RTC registers */
215             __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
216 
217             HAL_NVIC_EnableIRQ(RTC_IRQn);
218 
219             /* Configure the SysTick IRQ priority */
220             if (TickPriority < (1UL << __NVIC_PRIO_BITS))
221             {
222               HAL_NVIC_SetPriority(RTC_IRQn, TickPriority, 0U);
223               uwTickPrio = TickPriority;
224             }
225             else
226             {
227               status = HAL_ERROR;
228             }
229           }
230         }
231       }
232     }
233   }
234   else
235   {
236     status = HAL_ERROR;
237   }
238   return status;
239 }
240 
241 /**
242   * @brief  Suspend Tick increment.
243   * @note   Disable the tick increment by disabling RTC interrupt.
244   * @retval None
245   */
HAL_SuspendTick(void)246 void HAL_SuspendTick(void)
247 {
248   /* Disable the write protection for RTC registers */
249   __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
250   /* Disable RTC WAKE UP TIMER Interrupt */
251   __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hRTC_Handle, RTC_IT_WUT);
252   /* Enable the write protection for RTC registers */
253   __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
254 }
255 
256 /**
257   * @brief  Resume Tick increment.
258   * @note   Enable the tick increment by enabling RTC interrupt.
259   * @retval None
260   */
HAL_ResumeTick(void)261 void HAL_ResumeTick(void)
262 {
263   /* Disable the write protection for RTC registers */
264   __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
265   /* Enable RTC WAKE UP TIMER  interrupt */
266   __HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hRTC_Handle, RTC_IT_WUT);
267   /* Enable the write protection for RTC registers */
268   __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
269 }
270 
271 /**
272   * @brief  Wake Up Timer Event Callback in non blocking mode
273   * @note   This function is called  when RTC interrupt took place, inside
274   * RTC_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
275   * a global variable "uwTick" used as application time base.
276   * @param  hrtc : RTC handle
277   * @retval None
278   */
HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef * hrtc)279 void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
280 {
281   /* Prevent unused argument(s) compilation warning */
282   UNUSED(hrtc);
283 
284   HAL_IncTick();
285 }
286 
287 /**
288   * @brief  This function handles RTC WAKE UP TIMER interrupt request.
289   * @retval None
290   */
RTC_IRQHandler(void)291 void RTC_IRQHandler(void)
292 {
293   HAL_RTCEx_WakeUpTimerIRQHandler(&hRTC_Handle);
294 }
295 
296 /**
297   * @}
298   */
299 
300 /**
301   * @}
302   */
303 
304