1 /**
2 ******************************************************************************
3 * @file stm32h5xx_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 overrides 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
12 * + HSE (default), LSE or LSI can be selected as RTC clock source
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2022 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 'stm32h5xx_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 stm32h5xx_hal_conf.h
33
34 [..]
35 (@) HAL RTC alarm and HAL RTC wakeup drivers can not 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 stm32h5xx_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 "stm32h5xx_hal.h"
48 /** @addtogroup STM32H5xx_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 /* The time base should be 1ms
71 Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK
72 HSE as RTC clock
73 Time base = ((99 + 1) * (9 + 1)) / 1MHz
74 = 1ms
75 LSE as RTC clock
76 Time base = ((32 + 1) * (0 + 1)) / 32.768KHz
77 = ~1ms
78 LSI as RTC clock
79 Time base = ((31 + 1) * (0 + 1)) / 32KHz
80 = 1ms
81 */
82 #if defined (RTC_CLOCK_SOURCE_HSE)
83 #define RTC_ASYNCH_PREDIV 99U
84 #define RTC_SYNCH_PREDIV 9U
85 #elif defined (RTC_CLOCK_SOURCE_LSE)
86 #define RTC_ASYNCH_PREDIV 0U
87 #define RTC_SYNCH_PREDIV 32U
88 #elif defined (RTC_CLOCK_SOURCE_LSI)
89 #define RTC_ASYNCH_PREDIV 0U
90 #define RTC_SYNCH_PREDIV 31U
91 #else
92 #error Please select the RTC Clock source
93 #endif /* RTC_CLOCK_SOURCE_LSE */
94
95 /* Private macro -------------------------------------------------------------*/
96 /* Private variables ---------------------------------------------------------*/
97 static RTC_HandleTypeDef hRTC_Handle;
98
99 /* Private function prototypes -----------------------------------------------*/
100 void RTC_IRQHandler(void);
101 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1U)
102 void TimeBase_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc);
103 #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
104 /* Private functions ---------------------------------------------------------*/
105
106 /**
107 * @brief This function configures the RTC_ALARMA as a time base source.
108 * The time source is configured to have 1ms time base with a dedicated
109 * Tick interrupt priority.
110 * @note This function is called automatically at the beginning of program after
111 * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
112 * @param TickPriority Tick interrupt priority.
113 * @retval HAL status
114 */
HAL_InitTick(uint32_t TickPriority)115 HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
116 {
117 HAL_StatusTypeDef Status;
118
119 RCC_OscInitTypeDef RCC_OscInitStruct;
120 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
121
122 /* Disable bkup domain protection */
123 HAL_PWR_EnableBkUpAccess();
124
125 /* Force and Release the Backup domain reset */
126 __HAL_RCC_BACKUPRESET_FORCE();
127 __HAL_RCC_BACKUPRESET_RELEASE();
128
129 /* Enable RTC Clock */
130 __HAL_RCC_RTC_ENABLE();
131 __HAL_RCC_RTC_CLK_ENABLE();
132
133 #if defined (RTC_CLOCK_SOURCE_LSE)
134 /* Configure LSE as RTC clock source */
135 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
136 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
137 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
138 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
139 #elif defined (RTC_CLOCK_SOURCE_LSI)
140 /* Configure LSI as RTC clock source */
141 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
142 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
143 RCC_OscInitStruct.LSIState = RCC_LSI_ON;
144 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
145 #elif defined (RTC_CLOCK_SOURCE_HSE)
146 /* Configure HSE as RTC clock source */
147 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
148 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
149 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
150 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;
151 #else
152 #error Please select the RTC Clock source
153 #endif /* RTC_CLOCK_SOURCE_LSE */
154
155 Status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
156
157 if (Status == HAL_OK)
158 {
159 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
160 Status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
161 }
162
163 if (Status == HAL_OK)
164 {
165 hRTC_Handle.Instance = RTC;
166 hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24;
167 hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
168 hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
169 hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE;
170 hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
171 hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
172 hRTC_Handle.Init.BinMode = RTC_BINARY_NONE;
173
174 Status = HAL_RTC_Init(&hRTC_Handle);
175
176 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1U)
177 HAL_RTC_RegisterCallback(&hRTC_Handle, HAL_RTC_ALARM_A_EVENT_CB_ID, TimeBase_RTC_AlarmAEventCallback);
178 #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
179 }
180
181 if (Status == HAL_OK)
182 {
183 /* RTC variables */
184 RTC_AlarmTypeDef RTC_AlarmStructure;
185
186 /* RTC Alarm Generation */
187 RTC_AlarmStructure.Alarm = RTC_ALARM_A;
188 RTC_AlarmStructure.AlarmDateWeekDay = RTC_WEEKDAY_MONDAY;
189 RTC_AlarmStructure.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
190 /* Mask all and keep only subsecond, to have one match in each time base 1ms(uwTickFreq) */
191 RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_ALL;
192 RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
193 RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_HOURFORMAT_24;
194 RTC_AlarmStructure.AlarmTime.Hours = 0;
195 RTC_AlarmStructure.AlarmTime.Minutes = 0;
196 RTC_AlarmStructure.AlarmTime.Seconds = 0;
197 RTC_AlarmStructure.AlarmTime.SubSeconds = 0;
198
199 /* Set the specified RTC Alarm with Interrupt */
200 Status = HAL_RTC_SetAlarm_IT(&hRTC_Handle, &RTC_AlarmStructure, RTC_FORMAT_BCD);
201 }
202
203 if (TickPriority < (1UL << __NVIC_PRIO_BITS))
204 {
205 /* Enable the RTC global Interrupt */
206 HAL_NVIC_SetPriority(RTC_IRQn, TickPriority, 0);
207 uwTickPrio = TickPriority;
208 }
209 else
210 {
211 Status = HAL_ERROR;
212 }
213
214 HAL_NVIC_EnableIRQ(RTC_IRQn);
215
216 return Status;
217 }
218
219 /**
220 * @brief Suspend Tick increment.
221 * @note Disable the tick increment by disabling RTC ALARM interrupt.
222 * @retval None
223 */
HAL_SuspendTick(void)224 void HAL_SuspendTick(void)
225 {
226 /* Disable the write protection for RTC registers */
227 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
228 /* Disable RTC ALARM update Interrupt */
229 __HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
230 /* Enable the write protection for RTC registers */
231 __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
232 }
233
234 /**
235 * @brief Resume Tick increment.
236 * @note Enable the tick increment by Enabling RTC ALARM interrupt.
237 * @retval None
238 */
HAL_ResumeTick(void)239 void HAL_ResumeTick(void)
240 {
241 /* Disable the write protection for RTC registers */
242 __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
243 /* Enable RTC ALARM Update interrupt */
244 __HAL_RTC_ALARM_ENABLE_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 ALARM A Event Callback in non blocking mode
251 * @note This function is called when RTC_ALARM interrupt took place, inside
252 * RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
253 * a global variable "uwTick" used as application time base.
254 * @param hrtc RTC handle
255 * @retval None
256 */
257 #if (USE_HAL_RTC_REGISTER_CALLBACKS == 1U)
TimeBase_RTC_AlarmAEventCallback(RTC_HandleTypeDef * hrtc)258 void TimeBase_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
259 #else
260 void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
261 #endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
262 {
263 /* Prevent unused argument(s) compilation warning */
264 UNUSED(hrtc);
265
266 HAL_IncTick();
267 }
268
269 /**
270 * @brief This function handles RTC ALARM interrupt request.
271 * @retval None
272 */
RTC_IRQHandler(void)273 void RTC_IRQHandler(void)
274 {
275 HAL_RTC_AlarmIRQHandler(&hRTC_Handle);
276 }
277
278 /**
279 * @}
280 */
281
282 /**
283 * @}
284 */
285