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