1 /**
2 ******************************************************************************
3 * @file stm32f7xx_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 * + Initializes the RTC peripheral to increment the seconds registers each 1ms
10 * + The alarm is configured to assert an interrupt when the RTC reaches 1ms
11 * + HAL_IncTick is called at each Alarm event and the time is reset to 00:00:00
12 * + HSE (default), LSE or LSI can be selected as RTC clock source
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2017 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 'stm32f7xx_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 stm32f7xx_hal_conf.h
33
34 [..]
35 (@) HAL RTC alarm and HAL RTC wakeup drivers cant 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 stm32f7xx_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 "stm32f7xx_hal.h"
48 /** @addtogroup STM32F7xx_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 #ifdef RTC_CLOCK_SOURCE_HSE
71 #define RTC_ASYNCH_PREDIV 99U
72 #define RTC_SYNCH_PREDIV 9U
73 #define RCC_RTCCLKSOURCE_1MHZ ((uint32_t)((uint32_t)RCC_BDCR_RTCSEL | (uint32_t)((HSE_VALUE/1000000U) << 16U)))
74 #else /* RTC_CLOCK_SOURCE_LSE || RTC_CLOCK_SOURCE_LSI */
75 #define RTC_ASYNCH_PREDIV 0U
76 #define RTC_SYNCH_PREDIV 31U
77 #endif /* RTC_CLOCK_SOURCE_HSE */
78
79 /* Private macro -------------------------------------------------------------*/
80 /* Private variables ---------------------------------------------------------*/
81 RTC_HandleTypeDef hRTC_Handle;
82 /* Private function prototypes -----------------------------------------------*/
83 void RTC_Alarm_IRQHandler(void);
84 /* Private functions ---------------------------------------------------------*/
85
86 /**
87 * @brief This function configures the RTC_ALARMA as a time base source.
88 * The time source is configured to have 1ms time base with a dedicated
89 * Tick interrupt priority.
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 __IO uint32_t counter = 0U;
98
99 RCC_OscInitTypeDef RCC_OscInitStruct;
100 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
101 HAL_StatusTypeDef status;
102
103 #ifdef RTC_CLOCK_SOURCE_LSE
104 /* Configure LSE as RTC clock source */
105 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
106 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
107 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
108 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
109 #elif defined (RTC_CLOCK_SOURCE_LSI)
110 /* Configure LSI as RTC clock source */
111 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
112 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
113 RCC_OscInitStruct.LSIState = RCC_LSI_ON;
114 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
115 #elif defined (RTC_CLOCK_SOURCE_HSE)
116 /* Configure HSE as RTC clock source */
117 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
118 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
119 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
120 /* Ensure that RTC is clocked by 1MHz */
121 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_1MHZ;
122 #else
123 #error Please select the RTC Clock source
124 #endif /* RTC_CLOCK_SOURCE_LSE */
125
126 status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
127 if (status == HAL_OK)
128 {
129 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
130 status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
131 }
132 if (status == HAL_OK)
133 {
134 /* Enable RTC Clock */
135 __HAL_RCC_RTC_ENABLE();
136 /* The time base should be 1ms
137 Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK
138 HSE as RTC clock
139 Time base = ((99 + 1) * (9 + 1)) / 1MHz
140 = 1ms
141 LSE as RTC clock
142 Time base = ((31 + 1) * (0 + 1)) / 32.768KHz
143 = ~1ms
144 LSI as RTC clock
145 ime base = ((31 + 1) * (0 + 1)) / 32KHz
146 = 1ms
147 */
148 hRTC_Handle.Instance = RTC;
149 hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24;
150 hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
151 hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
152 hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE;
153 hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
154 hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
155 status = HAL_RTC_Init(&hRTC_Handle);
156 }
157 if (status == HAL_OK)
158 {
159 /* Disable the write protection for RTC registers */
160 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
161
162 /* Disable the Alarm A interrupt */
163 __HAL_RTC_ALARMA_DISABLE(&hRTC_Handle);
164
165 /* Clear flag alarm A */
166 __HAL_RTC_ALARM_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF);
167
168 counter = 0U;
169 /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */
170 while (__HAL_RTC_ALARM_GET_FLAG(&hRTC_Handle, RTC_FLAG_ALRAWF) == RESET)
171 {
172 if (counter++ == (SystemCoreClock / 48U)) /* Timeout = ~ 1s */
173 {
174 status = HAL_ERROR;
175 }
176 }
177 }
178 if (status == HAL_OK)
179 {
180 hRTC_Handle.Instance->ALRMAR = (uint32_t)0x01U;
181
182 /* Configure the Alarm state: Enable Alarm */
183 __HAL_RTC_ALARMA_ENABLE(&hRTC_Handle);
184
185 /* Configure the Alarm interrupt */
186 __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
187
188 /* RTC Alarm Interrupt Configuration: EXTI configuration */
189 __HAL_RTC_ALARM_EXTI_ENABLE_IT();
190 __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
191
192 /* Check if the Initialization mode is set */
193 if ((hRTC_Handle.Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
194 {
195 /* Set the Initialization mode */
196 hRTC_Handle.Instance->ISR = (uint32_t)RTC_INIT_MASK;
197 counter = 0U;
198 while ((hRTC_Handle.Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
199 {
200 if (counter++ == (SystemCoreClock / 48U)) /* Timeout = ~ 1s */
201 {
202 status = HAL_ERROR;
203 }
204 }
205 }
206 }
207 if (status == HAL_OK)
208 {
209 hRTC_Handle.Instance->DR = 0U;
210 hRTC_Handle.Instance->TR = 0U;
211
212 hRTC_Handle.Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
213
214 /* Enable the write protection for RTC registers */
215 __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
216
217 /* Enable the RTC Alarm Interrupt */
218 HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
219
220 /* Configure the SysTick IRQ priority */
221 if (TickPriority < (1UL << __NVIC_PRIO_BITS))
222 {
223 HAL_NVIC_SetPriority(RTC_Alarm_IRQn, TickPriority, 0U);
224 uwTickPrio = TickPriority;
225 }
226 else
227 {
228 status = HAL_ERROR;
229 }
230 }
231 return status;
232 }
233
234 /**
235 * @brief Suspend Tick increment.
236 * @note Disable the tick increment by disabling RTC ALARM interrupt.
237 * @retval None
238 */
HAL_SuspendTick(void)239 void HAL_SuspendTick(void)
240 {
241 /* Disable the write protection for RTC registers */
242 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
243 /* Disable RTC ALARM update Interrupt */
244 __HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
245 /* Enable the write protection for RTC registers */
246 __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
247 }
248
249 /**
250 * @brief Resume Tick increment.
251 * @note Enable the tick increment by Enabling RTC ALARM interrupt.
252 * @retval None
253 */
HAL_ResumeTick(void)254 void HAL_ResumeTick(void)
255 {
256 /* Disable the write protection for RTC registers */
257 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
258 /* Enable RTC ALARM Update interrupt */
259 __HAL_RTC_ALARM_ENABLE_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 ALARM A Event Callback in non blocking mode
266 * @note This function is called when RTC_ALARM interrupt took place, inside
267 * RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
268 * a global variable "uwTick" used as application time base.
269 * @param hrtc RTC handle
270 * @retval None
271 */
HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef * hrtc)272 void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
273 {
274 __IO uint32_t counter = 0U;
275
276 HAL_IncTick();
277
278 __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
279
280 /* Set the Initialization mode */
281 hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK;
282
283 while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET)
284 {
285 if(counter++ == (SystemCoreClock /48U)) /* Timeout = ~ 1s */
286 {
287 break;
288 }
289 }
290
291 hrtc->Instance->DR = 0U;
292 hrtc->Instance->TR = 0U;
293
294 hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
295
296 /* Enable the write protection for RTC registers */
297 __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
298 }
299
300 /**
301 * @brief This function handles RTC ALARM interrupt request.
302 * @retval None
303 */
RTC_Alarm_IRQHandler(void)304 void RTC_Alarm_IRQHandler(void)
305 {
306 HAL_RTC_AlarmIRQHandler(&hRTC_Handle);
307 }
308
309 /**
310 * @}
311 */
312
313 /**
314 * @}
315 */
316
317