1 /**
2   ******************************************************************************
3   * @file    stm32u0xx_hal_timebase_tim_template.c
4   * @author  GPM Application Team
5   * @brief   HAL time base based on the hardware TIM Template.
6   *
7   *          This file overrides the native HAL time base functions (defined as weak)
8   *          the TIM time base:
9   *           + Initializes the TIM peripheral to generate a Period elapsed Event each 1ms
10   *           + HAL_IncTick is called inside HAL_TIM_PeriodElapsedCallback ie each 1ms
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2023 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23  @verbatim
24   ==============================================================================
25                         ##### How to use this driver #####
26   ==============================================================================
27     [..]
28     This file must be copied to the application folder and modified as follows:
29     (#) Rename it to 'stm32u0xx_hal_timebase_tim.c'
30     (#) Add this file and the TIM HAL driver files to your project and make sure
31        HAL_TIM_MODULE_ENABLED is defined in stm32u0xx_hal_conf.h
32 
33     [..]
34     (@) The application needs to ensure that the time base is always set to 1 millisecond
35        to have correct HAL operation.
36 
37   @endverbatim
38   ******************************************************************************
39   */
40 
41 /* Includes ------------------------------------------------------------------*/
42 #include "stm32u0xx_hal.h"
43 
44 /** @addtogroup STM32U0xx_HAL_Driver
45   * @{
46   */
47 
48 /** @addtogroup HAL_TimeBase_TIM
49   * @{
50   */
51 
52 /* Private typedef -----------------------------------------------------------*/
53 /* Private define ------------------------------------------------------------*/
54 /* Private macro -------------------------------------------------------------*/
55 /* Private variables ---------------------------------------------------------*/
56 static TIM_HandleTypeDef        TimHandle;
57 
58 /* Private function prototypes -----------------------------------------------*/
59 void TIM16_IRQHandler(void);
60 /* Private functions ---------------------------------------------------------*/
61 
62 /**
63   * @brief  This function configures the TIM16 as a time base source.
64   *         The time source is configured to have 1ms time base with a dedicated
65   *         Tick interrupt priority.
66   * @note   This function is called  automatically at the beginning of program after
67   *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
68   * @param  TickPriority Tick interrupt priority.
69   * @retval HAL status
70   */
HAL_InitTick(uint32_t TickPriority)71 HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
72 {
73   RCC_ClkInitTypeDef    clkconfig;
74   uint32_t              uwTimclock;
75   uint32_t              uwAPB1Prescaler;
76   uint32_t              uwPrescalerValue;
77   uint32_t              pFLatency;
78   HAL_StatusTypeDef     status;
79 
80   /* Enable TIM16 clock */
81   __HAL_RCC_TIM16_CLK_ENABLE();
82 
83   /* Get clock configuration */
84   HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
85 
86   /* Get APB1 prescaler */
87   uwAPB1Prescaler = clkconfig.APB1CLKDivider;
88 
89   /* Compute TIM16 clock */
90   if (uwAPB1Prescaler == RCC_HCLK_DIV1)
91   {
92     uwTimclock = HAL_RCC_GetPCLK1Freq();
93   }
94   else
95   {
96     uwTimclock = 2U * HAL_RCC_GetPCLK1Freq();
97   }
98 
99   /* Compute the prescaler value to have TIM16 counter clock equal to 1MHz */
100   uwPrescalerValue = (uint32_t)((uwTimclock / 1000000U) - 1U);
101 
102   /* Initialize TIM16 */
103   TimHandle.Instance = TIM16;
104 
105   /* Initialize TIMx peripheral as follow:
106   + Period = [(TIM16CLK/1000) - 1]. to have a (1/1000) s time base.
107   + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
108   + ClockDivision = 0
109   + Counter direction = Up
110   */
111   TimHandle.Init.Period = (1000000U / 1000U) - 1U;
112   TimHandle.Init.Prescaler = uwPrescalerValue;
113   TimHandle.Init.ClockDivision = 0U;
114   TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
115 
116   status = HAL_TIM_Base_Init(&TimHandle);
117   if (status == HAL_OK)
118   {
119     /* Start the TIM time Base generation in interrupt mode */
120     status = HAL_TIM_Base_Start_IT(&TimHandle);
121     if (status == HAL_OK)
122     {
123       if (TickPriority < (1UL << __NVIC_PRIO_BITS))
124       {
125         /* Enable the TIM16 global Interrupt */
126         HAL_NVIC_SetPriority(TIM16_IRQn, TickPriority, 0U);
127         uwTickPrio = TickPriority;
128       }
129       else
130       {
131         status = HAL_ERROR;
132       }
133     }
134   }
135 
136   /* Enable the TIM16 global Interrupt */
137   HAL_NVIC_EnableIRQ(TIM16_IRQn);
138 
139  /* Return function status */
140   return status;
141 }
142 
143 /**
144   * @brief  Suspend Tick increment.
145   * @note   Disable the tick increment by disabling TIM16 update interrupt.
146   * @retval None
147   */
HAL_SuspendTick(void)148 void HAL_SuspendTick(void)
149 {
150   /* Disable TIM16 update interrupt */
151   __HAL_TIM_DISABLE_IT(&TimHandle, TIM_IT_UPDATE);
152 }
153 
154 /**
155   * @brief  Resume Tick increment.
156   * @note   Enable the tick increment by enabling TIM16 update interrupt.
157   * @retval None
158   */
HAL_ResumeTick(void)159 void HAL_ResumeTick(void)
160 {
161   /* Enable TIM16 update interrupt */
162   __HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
163 }
164 
165 /**
166   * @brief  Period elapsed callback in non blocking mode
167   * @note   This function is called  when TIM16 interrupt took place, inside
168   * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
169   * a global variable "uwTick" used as application time base.
170   * @param  htim TIM handle
171   * @retval None
172   */
HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim)173 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
174 {
175   HAL_IncTick();
176 }
177 
178 /**
179   * @brief  This function handles TIM interrupt request.
180   * @param  None
181   * @retval None
182   */
TIM16_IRQHandler(void)183 void TIM16_IRQHandler(void)
184 {
185   HAL_TIM_IRQHandler(&TimHandle);
186 }
187 
188 /**
189   * @}
190   */
191 
192 /**
193   * @}
194   */
195