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