1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_hal_timebase_rtc_alarm_template.c
4   * @author  MCD Application Team
5   * @brief   HAL time base based on the hardware RTC_ALARM.
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 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  @verbatim
14   ==============================================================================
15                         ##### How to use this driver #####
16   ==============================================================================
17     [..]
18     This file must be copied to the application folder and modified as follows:
19     (#) Rename it to 'stm32f1xx_hal_timebase_rtc_alarm.c'
20     (#) Add this file and the RTC HAL drivers to your project and uncomment
21        HAL_RTC_MODULE_ENABLED define in stm32f1xx_hal_conf.h
22 
23     [..]
24     (@) HAL RTC alarm and HAL RTC wakeup drivers can�t be used with low power modes:
25         The wake up capability of the RTC may be intrusive in case of prior low power mode
26         configuration requiring different wake up sources.
27         Application/Example behavior is no more guaranteed
28     (@) The stm32f1xx_hal_timebase_tim use is recommended for the Applications/Examples
29           requiring low power modes
30 
31   @endverbatim
32   ******************************************************************************
33   * @attention
34   *
35   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
36   * All rights reserved.</center></h2>
37   *
38   * This software component is licensed by ST under BSD 3-Clause license,
39   * the "License"; You may not use this file except in compliance with the
40   * License. You may obtain a copy of the License at:
41   *                        opensource.org/licenses/BSD-3-Clause
42   *
43   ******************************************************************************
44   */
45 
46 /* Includes ------------------------------------------------------------------*/
47 #include "stm32f1xx_hal.h"
48 /** @addtogroup STM32F1xx_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 /* Private macro -------------------------------------------------------------*/
71 /* Private variables ---------------------------------------------------------*/
72 RTC_HandleTypeDef        hRTC_Handle;
73 /* Private function prototypes -----------------------------------------------*/
74 void RTC_Alarm_IRQHandler(void);
75 /* Private functions ---------------------------------------------------------*/
76 
77 /**
78   * @brief  This function configures the RTC_ALARMA as a time base source.
79   *         The time source is configured  to have 1ms time base with a dedicated
80   *         Tick interrupt priority.
81   * @note   This function is called  automatically at the beginning of program after
82   *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
83   * @param  TickPriority Tick interrupt priority.
84   * @retval HAL status
85   */
HAL_InitTick(uint32_t TickPriority)86 HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
87 {
88   __IO uint32_t counter = 0U;
89 
90   RCC_OscInitTypeDef        RCC_OscInitStruct;
91   RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
92 
93 #ifdef RTC_CLOCK_SOURCE_LSE
94   /* Configue LSE as RTC clock soucre */
95   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
96   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
97   RCC_OscInitStruct.LSEState = RCC_LSE_ON;
98   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
99 #elif defined (RTC_CLOCK_SOURCE_LSI)
100   /* Configue LSI as RTC clock soucre */
101   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
102   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
103   RCC_OscInitStruct.LSIState = RCC_LSI_ON;
104   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
105 #elif defined (RTC_CLOCK_SOURCE_HSE)
106   /* Configue HSE as RTC clock soucre */
107   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
108   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
109   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
110   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV128;
111 #else
112 #error Please select the RTC Clock source
113 #endif /* RTC_CLOCK_SOURCE_LSE */
114 
115   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK)
116   {
117     PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
118     if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) == HAL_OK)
119     {
120       /* Enable RTC Clock */
121       __HAL_RCC_RTC_ENABLE();
122 
123       hRTC_Handle.Instance = RTC;
124       /* Configure RTC time base to 10Khz */
125       hRTC_Handle.Init.AsynchPrediv = (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_RTC) / 10000) - 1;
126       hRTC_Handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
127       HAL_RTC_Init(&hRTC_Handle);
128 
129       /* Disable the write protection for RTC registers */
130       __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
131 
132       /* Clear flag alarm A */
133       __HAL_RTC_ALARM_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF);
134 
135       counter = 0U;
136       /* Wait till RTC ALRAF flag is set and if Time out is reached exit */
137       while (__HAL_RTC_ALARM_GET_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF) != RESET)
138       {
139         if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
140         {
141           return HAL_ERROR;
142         }
143       }
144 
145       /* Set RTC COUNTER MSB word */
146       hRTC_Handle.Instance->ALRH = 0x00U;
147       /* Set RTC COUNTER LSB word */
148       hRTC_Handle.Instance->ALRL = 0x09U;
149 
150       /* RTC Alarm Interrupt Configuration: EXTI configuration */
151       __HAL_RTC_ALARM_EXTI_ENABLE_IT();
152       __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
153 
154       /* Clear Second and overflow flags */
155       CLEAR_BIT(hRTC_Handle.Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
156 
157       /* Set RTC COUNTER MSB word */
158       hRTC_Handle.Instance->CNTH = 0x00U;
159       /* Set RTC COUNTER LSB word */
160       hRTC_Handle.Instance->CNTL = 0x00U;
161 
162       /* Configure the Alarm interrupt */
163       __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
164 
165       /* Enable the write protection for RTC registers */
166       __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
167 
168       /* Wait till RTC is in INIT state and if Time out is reached exit */
169       counter = 0U;
170       while ((hRTC_Handle.Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
171       {
172         if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
173         {
174           return HAL_ERROR;
175         }
176       }
177 
178       HAL_NVIC_SetPriority(RTC_Alarm_IRQn, TickPriority, 0U);
179       HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
180       return HAL_OK;
181     }
182   }
183   return HAL_ERROR;
184 }
185 
186 /**
187   * @brief  Suspend Tick increment.
188   * @note   Disable the tick increment by disabling RTC ALARM interrupt.
189   * @param  None
190   * @retval None
191   */
HAL_SuspendTick(void)192 void HAL_SuspendTick(void)
193 {
194   /* Disable RTC ALARM update Interrupt */
195   __HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
196 }
197 
198 /**
199   * @brief  Resume Tick increment.
200   * @note   Enable the tick increment by Enabling RTC ALARM interrupt.
201   * @param  None
202   * @retval None
203   */
HAL_ResumeTick(void)204 void HAL_ResumeTick(void)
205 {
206   __IO uint32_t counter = 0U;
207 
208   /* Disable the write protection for RTC registers */
209   __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
210 
211   /* Set RTC COUNTER MSB word */
212   hRTC_Handle.Instance->CNTH = 0x00U;
213   /* Set RTC COUNTER LSB word */
214   hRTC_Handle.Instance->CNTL = 0x00U;
215 
216   /* Clear Second and overflow flags */
217   CLEAR_BIT(hRTC_Handle.Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW | RTC_FLAG_ALRAF));
218 
219   /* Enable RTC ALARM Update interrupt */
220   __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
221 
222   /* Enable the write protection for RTC registers */
223   __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
224 
225   /* Wait till RTC is in INIT state and if Time out is reached exit */
226   while ((hRTC_Handle.Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
227   {
228     if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
229     {
230       break;
231     }
232   }
233 }
234 
235 /**
236   * @brief  ALARM A Event Callback in non blocking mode
237   * @note   This function is called  when RTC_ALARM interrupt took place, inside
238   * RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
239   * a global variable "uwTick" used as application time base.
240   * @param  hrtc RTC handle
241   * @retval None
242   */
HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef * hrtc)243 void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
244 {
245   __IO uint32_t counter = 0U;
246 
247   HAL_IncTick();
248 
249   __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
250 
251   /* Set RTC COUNTER MSB word */
252   WRITE_REG(hrtc->Instance->CNTH, 0x00U);
253   /* Set RTC COUNTER LSB word */
254   WRITE_REG(hrtc->Instance->CNTL, 0x00U);
255 
256   /* Clear Second and overflow flags */
257   CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
258 
259   /* Enable the write protection for RTC registers */
260   __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
261 
262   /* Wait till RTC is in INIT state and if Time out is reached exit */
263   while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
264   {
265     if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
266     {
267       break;
268     }
269   }
270 }
271 
272 /**
273   * @brief  This function handles RTC ALARM interrupt request.
274   * @retval None
275   */
RTC_Alarm_IRQHandler(void)276 void RTC_Alarm_IRQHandler(void)
277 {
278   HAL_RTC_AlarmIRQHandler(&hRTC_Handle);
279 }
280 
281 /**
282   * @}
283   */
284 
285 /**
286   * @}
287   */
288 
289 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
290