1 /**
2 ******************************************************************************
3 * @file stm32f2xx_hal_timebase_rtc_alarm_template.c
4 * @author MCD Application Team
5 * @brief HAL time base based on the hardware RTC_ALARM Template.
6 *
7 * This file override the native HAL time base functions (defined as weak)
8 * to use the RTC ALARM for time base generation:
9 * + Intializes the RTC peripheral with required prescalers value for each
10 * RTC clock source (HSE, LSE or LSI)
11 * + The alarm is configured to assert an interrupt when the RTC reaches 1ms
12 * + HAL_IncTick is called at each Alarm event and the time is reset to 00:00:00
13 * + HSE (default), LSE or LSI can be selected as RTC clock source
14 @verbatim
15 ==============================================================================
16 ##### How to use this driver #####
17 ==============================================================================
18 [..]
19 This file must be copied to the application folder and modified as follows:
20 (#) Rename it to 'stm32f2xx_hal_timebase_rtc_alarm.c'
21 (#) Add this file and the RTC HAL drivers to your project and uncomment
22 HAL_RTC_MODULE_ENABLED define in stm32f2xx_hal_conf.h
23
24 [..]
25 (@) HAL RTC alarm and HAL RTC wakeup drivers can�t be used with low power modes:
26 The wake up capability of the RTC may be intrusive in case of prior low power mode
27 configuration requiring different wake up sources.
28 Application/Example behavior is no more guaranteed
29 (@) The stm32f2xx_hal_timebase_tim use is recommended for the Applications/Examples
30 requiring low power modes
31
32 @endverbatim
33 ******************************************************************************
34 * @attention
35 *
36 * <h2><center>© Copyright (c) 2016 STMicroelectronics.
37 * All rights reserved.</center></h2>
38 *
39 * This software component is licensed by ST under BSD 3-Clause license,
40 * the "License"; You may not use this file except in compliance with the
41 * License. You may obtain a copy of the License at:
42 * opensource.org/licenses/BSD-3-Clause
43 *
44 ******************************************************************************
45 */
46
47 /* Includes ------------------------------------------------------------------*/
48 #include "stm32f2xx_hal.h"
49
50 /** @addtogroup STM32F2xx_HAL_Driver
51 * @{
52 */
53
54 /** @defgroup HAL_TimeBase_RTC_Alarm_Template HAL TimeBase RTC Alarm Template
55 * @{
56 */
57
58 /* Private typedef -----------------------------------------------------------*/
59 /* Private define ------------------------------------------------------------*/
60
61 /* Uncomment the line below to select the appropriate RTC Clock source for your application:
62 + RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision.
63 + RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing
64 precision.
65 + RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing
66 precision.
67 */
68 #define RTC_CLOCK_SOURCE_HSE
69 /* #define RTC_CLOCK_SOURCE_LSE */
70 /* #define RTC_CLOCK_SOURCE_LSI */
71
72 #ifdef RTC_CLOCK_SOURCE_HSE
73 #define RTC_ASYNCH_PREDIV 9U
74 #define RTC_SYNCH_PREDIV 9U
75 #define RCC_RTCCLKSOURCE_1MHZ ((uint32_t)((uint32_t)RCC_BDCR_RTCSEL | (uint32_t)((HSE_VALUE/1000000U) << 16U)))
76 #elif defined (RTC_CLOCK_SOURCE_LSE)
77 #define RTC_ASYNCH_PREDIV 2U
78 #define RTC_SYNCH_PREDIV 0U
79 #else /* RTC_CLOCK_SOURCE_LSI */
80 #define RTC_ASYNCH_PREDIV 1U
81 #define RTC_SYNCH_PREDIV 0U
82 #endif /* RTC_CLOCK_SOURCE_HSE */
83
84 /* Private macro -------------------------------------------------------------*/
85 /* Private variables ---------------------------------------------------------*/
86 RTC_HandleTypeDef hRTC_Handle;
87 /* Private function prototypes -----------------------------------------------*/
88 void RTC_Alarm_IRQHandler(void);
89 /* Private functions ---------------------------------------------------------*/
90
91 /**
92 * @brief This function configures the RTC_ALARMA as a time base source.
93 * The time source is configured to have 1ms time base with a dedicated
94 * Tick interrupt priority.
95 * @note This function is called automatically at the beginning of program after
96 * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
97 * @param TickPriority Tick interrupt priority.
98 * @retval HAL status
99 */
HAL_InitTick(uint32_t TickPriority)100 HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
101 {
102 __IO uint32_t counter = 0U;
103
104 RCC_OscInitTypeDef RCC_OscInitStruct;
105 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
106 HAL_StatusTypeDef status;
107
108 #ifdef RTC_CLOCK_SOURCE_LSE
109 /* Configue LSE as RTC clock soucre */
110 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
111 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
112 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
113 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
114 #elif defined (RTC_CLOCK_SOURCE_LSI)
115 /* Configue LSI as RTC clock soucre */
116 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
117 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
118 RCC_OscInitStruct.LSIState = RCC_LSI_ON;
119 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
120 #elif defined (RTC_CLOCK_SOURCE_HSE)
121 /* Configue HSE as RTC clock soucre */
122 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
123 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
124 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
125 /* Ensure that RTC is clocked by 1MHz */
126 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_1MHZ;
127 #else
128 #error Please select the RTC Clock source
129 #endif /* RTC_CLOCK_SOURCE_LSE */
130
131 status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
132 if (status == HAL_OK)
133 {
134 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
135 status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
136 }
137 if (status == HAL_OK)
138 {
139 /* Enable RTC Clock */
140 __HAL_RCC_RTC_ENABLE();
141
142 /* The time base should be 1ms
143 Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1) * ALARM_VALUE) / RTC_CLOCK
144 HSE as RTC clock
145 Time base = ((9 + 1) * (9 + 1) * 10) / 1MHz
146 = 1ms
147 LSE as RTC clock
148 Time base = ((2 + 1) * (0 + 1) * 11) / 32.768KHz
149 = ~1ms
150 LSI as RTC clock
151 Time base = ((1 + 1) * (0 + 1) * 16) / 32KHz
152 = 1ms
153 */
154 hRTC_Handle.Instance = RTC;
155 hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24;
156 hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
157 hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
158 hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE;
159 hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
160 hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
161 status = HAL_RTC_Init(&hRTC_Handle);
162 }
163 if (status == HAL_OK)
164 {
165 /* Disable the write protection for RTC registers */
166 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
167
168 /* Disable the Alarm A interrupt */
169 __HAL_RTC_ALARMA_DISABLE(&hRTC_Handle);
170
171 /* Clear flag alarm A */
172 __HAL_RTC_ALARM_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF);
173
174 counter = 0U;
175 /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */
176 while (__HAL_RTC_ALARM_GET_FLAG(&hRTC_Handle, RTC_FLAG_ALRAWF) == RESET)
177 {
178 if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
179 {
180 status = HAL_ERROR;
181 }
182 }
183 }
184 if (status == HAL_OK)
185 {
186 /* Set alarm value for each RTC clock source */
187 #ifdef RTC_CLOCK_SOURCE_HSE
188 hRTC_Handle.Instance->ALRMAR = 0x10U;
189 #elif defined (RTC_CLOCK_SOURCE_LSE)
190 hRTC_Handle.Instance->ALRMAR = 0x11U;
191 #else
192 hRTC_Handle.Instance->ALRMAR = 0x16U;
193 #endif
194
195 /* Configure the Alarm state: Enable Alarm */
196 __HAL_RTC_ALARMA_ENABLE(&hRTC_Handle);
197
198 /* Configure the Alarm interrupt */
199 __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
200
201 /* RTC Alarm Interrupt Configuration: EXTI configuration */
202 __HAL_RTC_ALARM_EXTI_ENABLE_IT();
203 __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
204
205 /* Check if the Initialization mode is set */
206 if ((hRTC_Handle.Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
207 {
208 /* Set the Initialization mode */
209 hRTC_Handle.Instance->ISR = (uint32_t)RTC_INIT_MASK;
210 counter = 0U;
211 while ((hRTC_Handle.Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
212 {
213 if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
214 {
215 status = HAL_ERROR;
216 }
217 }
218 }
219 }
220 if (status == HAL_OK)
221 {
222 hRTC_Handle.Instance->DR = 0U;
223 hRTC_Handle.Instance->TR = 0U;
224
225 hRTC_Handle.Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
226
227 /* Enable the write protection for RTC registers */
228 __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
229
230 /* Enable the RTC Alarm Interrupt */
231 HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
232
233 /* Configure the SysTick IRQ priority */
234 if (TickPriority < (1UL << __NVIC_PRIO_BITS))
235 {
236 HAL_NVIC_SetPriority(RTC_Alarm_IRQn, TickPriority, 0U);
237 uwTickPrio = TickPriority;
238 }
239 else
240 {
241 status = HAL_ERROR;
242 }
243
244 }
245 return status;
246 }
247
248 /**
249 * @brief Suspend Tick increment.
250 * @note Disable the tick increment by disabling RTC ALARM interrupt.
251 * @param None
252 * @retval None
253 */
HAL_SuspendTick(void)254 void HAL_SuspendTick(void)
255 {
256 /* Disable the write protection for RTC registers */
257 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
258 /* Disable RTC ALARM update Interrupt */
259 __HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
260 /* Enable the write protection for RTC registers */
261 __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
262 }
263
264 /**
265 * @brief Resume Tick increment.
266 * @note Enable the tick increment by Enabling RTC ALARM interrupt.
267 * @param None
268 * @retval None
269 */
HAL_ResumeTick(void)270 void HAL_ResumeTick(void)
271 {
272 /* Disable the write protection for RTC registers */
273 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
274 /* Enable RTC ALARM Update interrupt */
275 __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
276 /* Enable the write protection for RTC registers */
277 __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
278 }
279
280 /**
281 * @brief ALARM A Event Callback in non blocking mode
282 * @note This function is called when RTC_ALARM interrupt took place, inside
283 * RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
284 * a global variable "uwTick" used as application time base.
285 * @param hrtc RTC handle
286 * @retval None
287 */
HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef * hrtc)288 void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
289 {
290 __IO uint32_t counter = 0U;
291
292 HAL_IncTick();
293
294 __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
295
296 /* Set the Initialization mode */
297 hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK;
298
299 while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
300 {
301 if(counter++ == SystemCoreClock /48U) /* Timeout = ~ 1s */
302 {
303 break;
304 }
305 }
306
307 hrtc->Instance->DR = 0U;
308 hrtc->Instance->TR = 0U;
309
310 hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
311
312 /* Enable the write protection for RTC registers */
313 __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
314 }
315
316 /**
317 * @brief This function handles RTC ALARM interrupt request.
318 * @param None
319 * @retval None
320 */
RTC_Alarm_IRQHandler(void)321 void RTC_Alarm_IRQHandler(void)
322 {
323 HAL_RTC_AlarmIRQHandler(&hRTC_Handle);
324 }
325
326 /**
327 * @}
328 */
329
330 /**
331 * @}
332 */
333
334 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
335