1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_ll_lptim.c
4   * @author  MCD Application Team
5   * @brief   LPTIM LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * Copyright (c) 2017 STMicroelectronics.
10   * All rights reserved.
11   *
12   * This software is licensed under terms that can be found in the LICENSE file
13   * in the root directory of this software component.
14   * If no LICENSE file comes with this software, it is provided AS-IS.
15   *
16   ******************************************************************************
17   */
18 #if defined(USE_FULL_LL_DRIVER)
19 
20 /* Includes ------------------------------------------------------------------*/
21 #include "stm32h7xx_ll_lptim.h"
22 #include "stm32h7xx_ll_bus.h"
23 #include "stm32h7xx_ll_rcc.h"
24 
25 
26 #ifdef  USE_FULL_ASSERT
27 #include "stm32_assert.h"
28 #else
29 #define assert_param(expr) ((void)0U)
30 #endif /* USE_FULL_ASSERT */
31 
32 /** @addtogroup STM32H7xx_LL_Driver
33   * @{
34   */
35 
36 #if defined (LPTIM1) || defined (LPTIM2) || defined (LPTIM3) || defined (LPTIM4) || defined (LPTIM5)
37 
38 /** @addtogroup LPTIM_LL
39   * @{
40   */
41 
42 /* Private types -------------------------------------------------------------*/
43 /* Private variables ---------------------------------------------------------*/
44 /* Private constants ---------------------------------------------------------*/
45 /* Private macros ------------------------------------------------------------*/
46 /** @addtogroup LPTIM_LL_Private_Macros
47   * @{
48   */
49 #define IS_LL_LPTIM_CLOCK_SOURCE(__VALUE__) (((__VALUE__) == LL_LPTIM_CLK_SOURCE_INTERNAL) \
50                                              || ((__VALUE__) == LL_LPTIM_CLK_SOURCE_EXTERNAL))
51 
52 #define IS_LL_LPTIM_CLOCK_PRESCALER(__VALUE__) (((__VALUE__) == LL_LPTIM_PRESCALER_DIV1)   \
53                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV2)   \
54                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV4)   \
55                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV8)   \
56                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV16)  \
57                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV32)  \
58                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV64)  \
59                                                 || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV128))
60 
61 #define IS_LL_LPTIM_WAVEFORM(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_PWM) \
62                                          || ((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_SETONCE))
63 
64 #define IS_LL_LPTIM_OUTPUT_POLARITY(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_REGULAR) \
65                                                 || ((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_INVERSE))
66 /**
67   * @}
68   */
69 
70 
71 /* Private function prototypes -----------------------------------------------*/
72 /* Private functions ---------------------------------------------------------*/
73 /** @defgroup LPTIM_Private_Functions LPTIM Private Functions
74   * @{
75   */
76 /**
77   * @}
78   */
79 /* Exported functions --------------------------------------------------------*/
80 /** @addtogroup LPTIM_LL_Exported_Functions
81   * @{
82   */
83 
84 /** @addtogroup LPTIM_LL_EF_Init
85   * @{
86   */
87 
88 /**
89   * @brief  Set LPTIMx registers to their reset values.
90   * @param  LPTIMx LP Timer instance
91   * @retval An ErrorStatus enumeration value:
92   *          - SUCCESS: LPTIMx registers are de-initialized
93   *          - ERROR: invalid LPTIMx instance
94   */
LL_LPTIM_DeInit(LPTIM_TypeDef * LPTIMx)95 ErrorStatus LL_LPTIM_DeInit(LPTIM_TypeDef *LPTIMx)
96 {
97   ErrorStatus result = SUCCESS;
98 
99   /* Check the parameters */
100   assert_param(IS_LPTIM_INSTANCE(LPTIMx));
101 
102   if (LPTIMx == LPTIM1)
103   {
104     LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_LPTIM1);
105     LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1);
106   }
107   else if (LPTIMx == LPTIM2)
108   {
109     LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM2);
110     LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM2);
111   }
112 #if defined(LPTIM3)
113   else if (LPTIMx == LPTIM3)
114   {
115     LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM3);
116     LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM3);
117   }
118 #endif /* LPTIM3 */
119 #if defined(LPTIM4)
120   else if (LPTIMx == LPTIM4)
121   {
122     LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM4);
123     LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM4);
124   }
125 #endif /* LPTIM4 */
126 #if defined(LPTIM5)
127   else if (LPTIMx == LPTIM5)
128   {
129     LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM5);
130     LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM5);
131   }
132 #endif /* LPTIM5 */
133   else
134   {
135     result = ERROR;
136   }
137 
138   return result;
139 }
140 
141 /**
142   * @brief  Set each fields of the LPTIM_InitStruct structure to its default
143   *         value.
144   * @param  LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
145   * @retval None
146   */
LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef * LPTIM_InitStruct)147 void LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
148 {
149   /* Set the default configuration */
150   LPTIM_InitStruct->ClockSource = LL_LPTIM_CLK_SOURCE_INTERNAL;
151   LPTIM_InitStruct->Prescaler   = LL_LPTIM_PRESCALER_DIV1;
152   LPTIM_InitStruct->Waveform    = LL_LPTIM_OUTPUT_WAVEFORM_PWM;
153   LPTIM_InitStruct->Polarity    = LL_LPTIM_OUTPUT_POLARITY_REGULAR;
154 }
155 
156 /**
157   * @brief  Configure the LPTIMx peripheral according to the specified parameters.
158   * @note LL_LPTIM_Init can only be called when the LPTIM instance is disabled.
159   * @note LPTIMx can be disabled using unitary function @ref LL_LPTIM_Disable().
160   * @param  LPTIMx LP Timer Instance
161   * @param  LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
162   * @retval An ErrorStatus enumeration value:
163   *          - SUCCESS: LPTIMx instance has been initialized
164   *          - ERROR: LPTIMx instance hasn't been initialized
165   */
LL_LPTIM_Init(LPTIM_TypeDef * LPTIMx,const LL_LPTIM_InitTypeDef * LPTIM_InitStruct)166 ErrorStatus LL_LPTIM_Init(LPTIM_TypeDef *LPTIMx, const LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
167 {
168   ErrorStatus result = SUCCESS;
169   /* Check the parameters */
170   assert_param(IS_LPTIM_INSTANCE(LPTIMx));
171   assert_param(IS_LL_LPTIM_CLOCK_SOURCE(LPTIM_InitStruct->ClockSource));
172   assert_param(IS_LL_LPTIM_CLOCK_PRESCALER(LPTIM_InitStruct->Prescaler));
173   assert_param(IS_LL_LPTIM_WAVEFORM(LPTIM_InitStruct->Waveform));
174   assert_param(IS_LL_LPTIM_OUTPUT_POLARITY(LPTIM_InitStruct->Polarity));
175 
176   /* The LPTIMx_CFGR register must only be modified when the LPTIM is disabled
177      (ENABLE bit is reset to 0).
178   */
179   if (LL_LPTIM_IsEnabled(LPTIMx) == 1UL)
180   {
181     result = ERROR;
182   }
183   else
184   {
185     /* Set CKSEL bitfield according to ClockSource value */
186     /* Set PRESC bitfield according to Prescaler value */
187     /* Set WAVE bitfield according to Waveform value */
188     /* Set WAVEPOL bitfield according to Polarity value */
189     MODIFY_REG(LPTIMx->CFGR,
190                (LPTIM_CFGR_CKSEL | LPTIM_CFGR_PRESC | LPTIM_CFGR_WAVE | LPTIM_CFGR_WAVPOL),
191                LPTIM_InitStruct->ClockSource | \
192                LPTIM_InitStruct->Prescaler | \
193                LPTIM_InitStruct->Waveform | \
194                LPTIM_InitStruct->Polarity);
195   }
196 
197   return result;
198 }
199 
200 /**
201   * @brief  Disable the LPTIM instance
202   * @rmtoll CR           ENABLE        LL_LPTIM_Disable
203   * @param  LPTIMx Low-Power Timer instance
204   * @note   The following sequence is required to solve LPTIM disable HW limitation.
205   *         Please check Errata Sheet ES0335 for more details under "MCU may remain
206   *         stuck in LPTIM interrupt when entering Stop mode" section.
207   * @retval None
208   */
LL_LPTIM_Disable(LPTIM_TypeDef * LPTIMx)209 void LL_LPTIM_Disable(LPTIM_TypeDef *LPTIMx)
210 {
211   LL_RCC_ClocksTypeDef rcc_clock;
212   uint32_t tmpclksource = 0;
213   uint32_t tmpIER;
214   uint32_t tmpCFGR;
215   uint32_t tmpCMP;
216   uint32_t tmpARR;
217   uint32_t primask_bit;
218   uint32_t tmpCFGR2;
219 
220   /* Check the parameters */
221   assert_param(IS_LPTIM_INSTANCE(LPTIMx));
222 
223   /* Enter critical section */
224   primask_bit = __get_PRIMASK();
225   __set_PRIMASK(1) ;
226 
227   /********** Save LPTIM Config *********/
228   /* Save LPTIM source clock */
229   switch ((uint32_t)LPTIMx)
230   {
231     case LPTIM1_BASE:
232       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE);
233       break;
234     case LPTIM2_BASE:
235       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE);
236       break;
237 #if defined(LPTIM3)&&defined(LPTIM4)&&defined(LPTIM5)
238     case LPTIM3_BASE:
239     case LPTIM4_BASE:
240     case LPTIM5_BASE:
241       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM345_CLKSOURCE);
242       break;
243 #elif defined(LPTIM3)
244     case LPTIM3_BASE:
245       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE);
246       break;
247 #endif /* LPTIM3 && LPTIM4 && LPTIM5 */
248     default:
249       break;
250   }
251 
252   /* Save LPTIM configuration registers */
253   tmpIER = LPTIMx->IER;
254   tmpCFGR = LPTIMx->CFGR;
255   tmpCMP = LPTIMx->CMP;
256   tmpARR = LPTIMx->ARR;
257   tmpCFGR2 = LPTIMx->CFGR2;
258 
259   /************* Reset LPTIM ************/
260   (void)LL_LPTIM_DeInit(LPTIMx);
261 
262   /********* Restore LPTIM Config *******/
263   LL_RCC_GetSystemClocksFreq(&rcc_clock);
264 
265   if ((tmpCMP != 0UL) || (tmpARR != 0UL))
266   {
267     /* Force LPTIM source kernel clock from APB */
268     switch ((uint32_t)LPTIMx)
269     {
270       case LPTIM1_BASE:
271         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1);
272         break;
273       case LPTIM2_BASE:
274         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK4);
275         break;
276 #if defined(LPTIM3)&&defined(LPTIM4)&&defined(LPTIM5)
277       case LPTIM3_BASE:
278       case LPTIM4_BASE:
279       case LPTIM5_BASE:
280         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM345_CLKSOURCE_PCLK4);
281         break;
282 #elif defined(LPTIM3)
283       case LPTIM3_BASE:
284         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE_PCLK4);
285         break;
286 #endif /* LPTIM3 && LPTIM4 && LPTIM5*/
287       default:
288         break;
289     }
290 
291     if (tmpCMP != 0UL)
292     {
293       /* Restore CMP and ARR registers (LPTIM should be enabled first) */
294       LPTIMx->CR |= LPTIM_CR_ENABLE;
295       LPTIMx->CMP = tmpCMP;
296 
297       /* Polling on CMP write ok status after above restore operation */
298       do
299       {
300         rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
301       } while (((LL_LPTIM_IsActiveFlag_CMPOK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
302 
303       LL_LPTIM_ClearFlag_CMPOK(LPTIMx);
304     }
305 
306     if (tmpARR != 0UL)
307     {
308       LPTIMx->CR |= LPTIM_CR_ENABLE;
309       LPTIMx->ARR = tmpARR;
310 
311       LL_RCC_GetSystemClocksFreq(&rcc_clock);
312       /* Polling on ARR write ok status after above restore operation */
313       do
314       {
315         rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
316       } while (((LL_LPTIM_IsActiveFlag_ARROK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
317 
318       LL_LPTIM_ClearFlag_ARROK(LPTIMx);
319     }
320 
321 
322     /* Restore LPTIM source kernel clock */
323     LL_RCC_SetLPTIMClockSource(tmpclksource);
324   }
325 
326   /* Restore configuration registers (LPTIM should be disabled first) */
327   LPTIMx->CR &= ~(LPTIM_CR_ENABLE);
328   LPTIMx->IER = tmpIER;
329   LPTIMx->CFGR = tmpCFGR;
330   LPTIMx->CFGR2 = tmpCFGR2;
331 
332   /* Exit critical section: restore previous priority mask */
333   __set_PRIMASK(primask_bit);
334 }
335 
336 /**
337   * @}
338   */
339 
340 /**
341   * @}
342   */
343 
344 /**
345   * @}
346   */
347 
348 #endif /* LPTIM1 || LPTIM2 ||  LPTIM3 || LPTIM4 || LPTIM5 */
349 
350 /**
351   * @}
352   */
353 
354 #endif /* USE_FULL_LL_DRIVER */
355