1 /**
2   ******************************************************************************
3   * @file    stm32l5xx_ll_lptim.c
4   * @author  MCD Application Team
5   * @brief   LPTIM LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * <h2><center>&copy; Copyright (c) 2019 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 "stm32l5xx_ll_lptim.h"
23 #include "stm32l5xx_ll_bus.h"
24 #include "stm32l5xx_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 STM32L5xx_LL_Driver
34   * @{
35   */
36 
37 #if defined (LPTIM1) || defined (LPTIM2) || defined (LPTIM3)
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   else if (LPTIMx == LPTIM2)
109   {
110     LL_APB1_GRP2_ForceReset(LL_APB1_GRP2_PERIPH_LPTIM2);
111     LL_APB1_GRP2_ReleaseReset(LL_APB1_GRP2_PERIPH_LPTIM2);
112   }
113   else if (LPTIMx == LPTIM3)
114   {
115     LL_APB1_GRP2_ForceReset(LL_APB1_GRP2_PERIPH_LPTIM3);
116     LL_APB1_GRP2_ReleaseReset(LL_APB1_GRP2_PERIPH_LPTIM3);
117   }
118   else
119   {
120     result = ERROR;
121   }
122 
123   return result;
124 }
125 
126 /**
127   * @brief  Set each fields of the LPTIM_InitStruct structure to its default
128   *         value.
129   * @param  LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
130   * @retval None
131   */
LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef * LPTIM_InitStruct)132 void LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
133 {
134   /* Set the default configuration */
135   LPTIM_InitStruct->ClockSource = LL_LPTIM_CLK_SOURCE_INTERNAL;
136   LPTIM_InitStruct->Prescaler   = LL_LPTIM_PRESCALER_DIV1;
137   LPTIM_InitStruct->Waveform    = LL_LPTIM_OUTPUT_WAVEFORM_PWM;
138   LPTIM_InitStruct->Polarity    = LL_LPTIM_OUTPUT_POLARITY_REGULAR;
139 }
140 
141 /**
142   * @brief  Configure the LPTIMx peripheral according to the specified parameters.
143   * @note LL_LPTIM_Init can only be called when the LPTIM instance is disabled.
144   * @note LPTIMx can be disabled using unitary function @ref LL_LPTIM_Disable().
145   * @param  LPTIMx LP Timer Instance
146   * @param  LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
147   * @retval An ErrorStatus enumeration value:
148   *          - SUCCESS: LPTIMx instance has been initialized
149   *          - ERROR: LPTIMx instance hasn't been initialized
150   */
LL_LPTIM_Init(LPTIM_TypeDef * LPTIMx,LL_LPTIM_InitTypeDef * LPTIM_InitStruct)151 ErrorStatus LL_LPTIM_Init(LPTIM_TypeDef *LPTIMx, LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
152 {
153   ErrorStatus result = SUCCESS;
154   /* Check the parameters */
155   assert_param(IS_LPTIM_INSTANCE(LPTIMx));
156   assert_param(IS_LL_LPTIM_CLOCK_SOURCE(LPTIM_InitStruct->ClockSource));
157   assert_param(IS_LL_LPTIM_CLOCK_PRESCALER(LPTIM_InitStruct->Prescaler));
158   assert_param(IS_LL_LPTIM_WAVEFORM(LPTIM_InitStruct->Waveform));
159   assert_param(IS_LL_LPTIM_OUTPUT_POLARITY(LPTIM_InitStruct->Polarity));
160 
161   /* The LPTIMx_CFGR register must only be modified when the LPTIM is disabled
162      (ENABLE bit is reset to 0).
163   */
164   if (LL_LPTIM_IsEnabled(LPTIMx) == 1UL)
165   {
166     result = ERROR;
167   }
168   else
169   {
170     /* Set CKSEL bitfield according to ClockSource value */
171     /* Set PRESC bitfield according to Prescaler value */
172     /* Set WAVE bitfield according to Waveform value */
173     /* Set WAVEPOL bitfield according to Polarity value */
174     MODIFY_REG(LPTIMx->CFGR,
175                (LPTIM_CFGR_CKSEL | LPTIM_CFGR_PRESC | LPTIM_CFGR_WAVE | LPTIM_CFGR_WAVPOL),
176                LPTIM_InitStruct->ClockSource | \
177                LPTIM_InitStruct->Prescaler | \
178                LPTIM_InitStruct->Waveform | \
179                LPTIM_InitStruct->Polarity);
180   }
181 
182   return result;
183 }
184 
185 /**
186   * @brief  Disable the LPTIM instance
187   * @rmtoll CR           ENABLE        LL_LPTIM_Disable
188   * @param  LPTIMx Low-Power Timer instance
189   * @note   The following sequence is required to solve LPTIM disable HW limitation.
190   *         Please check Errata Sheet ES0335 for more details under "MCU may remain
191   *         stuck in LPTIM interrupt when entering Stop mode" section.
192   * @retval None
193   */
LL_LPTIM_Disable(LPTIM_TypeDef * LPTIMx)194 void LL_LPTIM_Disable(LPTIM_TypeDef *LPTIMx)
195 {
196   LL_RCC_ClocksTypeDef rcc_clock;
197   uint32_t tmpclksource = 0;
198   uint32_t tmpIER;
199   uint32_t tmpCFGR;
200   uint32_t tmpCMP;
201   uint32_t tmpARR;
202   uint32_t tmpOR;
203   uint32_t tmpRCR;
204 
205   /* Check the parameters */
206   assert_param(IS_LPTIM_INSTANCE(LPTIMx));
207 
208   __disable_irq();
209 
210   /********** Save LPTIM Config *********/
211   /* Save LPTIM source clock */
212   switch ((uint32_t)LPTIMx)
213   {
214     case LPTIM1_BASE:
215       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE);
216       break;
217     case LPTIM2_BASE:
218       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE);
219       break;
220     case LPTIM3_BASE:
221       tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE);
222       break;
223     default:
224       break;
225   }
226 
227   /* Save LPTIM configuration registers */
228   tmpIER = LPTIMx->IER;
229   tmpCFGR = LPTIMx->CFGR;
230   tmpCMP = LPTIMx->CMP;
231   tmpARR = LPTIMx->ARR;
232   tmpOR = LPTIMx->OR;
233   tmpRCR = LPTIMx->RCR;
234 
235   /************* Reset LPTIM ************/
236   (void)LL_LPTIM_DeInit(LPTIMx);
237 
238   /********* Restore LPTIM Config *******/
239   LL_RCC_GetSystemClocksFreq(&rcc_clock);
240 
241   if ((tmpCMP != 0UL) || (tmpARR != 0UL) || (tmpRCR != 0UL))
242   {
243     /* Force LPTIM source kernel clock from APB */
244     switch ((uint32_t)LPTIMx)
245     {
246       case LPTIM1_BASE:
247         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1);
248         break;
249       case LPTIM2_BASE:
250         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK1);
251         break;
252       case LPTIM3_BASE:
253         LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE_PCLK1);
254         break;
255       default:
256         break;
257     }
258 
259     if (tmpCMP != 0UL)
260     {
261       /* Restore CMP and ARR registers (LPTIM should be enabled first) */
262       LPTIMx->CR |= LPTIM_CR_ENABLE;
263       LPTIMx->CMP = tmpCMP;
264 
265       /* Polling on CMP write ok status after above restore operation */
266       do
267       {
268         rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
269       } while (((LL_LPTIM_IsActiveFlag_CMPOK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
270 
271       LL_LPTIM_ClearFlag_CMPOK(LPTIMx);
272     }
273 
274     if (tmpARR != 0UL)
275     {
276       LPTIMx->CR |= LPTIM_CR_ENABLE;
277       LPTIMx->ARR = tmpARR;
278 
279       LL_RCC_GetSystemClocksFreq(&rcc_clock);
280       /* Polling on ARR write ok status after above restore operation */
281       do
282       {
283         rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
284       }
285       while (((LL_LPTIM_IsActiveFlag_ARROK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
286 
287       LL_LPTIM_ClearFlag_ARROK(LPTIMx);
288     }
289 
290     if (tmpRCR != 0UL)
291     {
292       LPTIMx->CR |= LPTIM_CR_ENABLE;
293       LPTIMx->RCR = tmpRCR;
294 
295       LL_RCC_GetSystemClocksFreq(&rcc_clock);
296       /* Polling on RCR write ok status after above restore operation */
297       do
298       {
299         rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
300       } while (((LL_LPTIM_IsActiveFlag_REPOK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));
301 
302       LL_LPTIM_ClearFlag_REPOK(LPTIMx);
303     }
304 
305     /* Restore LPTIM source kernel clock */
306     LL_RCC_SetLPTIMClockSource(tmpclksource);
307   }
308 
309   /* Restore configuration registers (LPTIM should be disabled first) */
310   LPTIMx->CR &= ~(LPTIM_CR_ENABLE);
311   LPTIMx->IER = tmpIER;
312   LPTIMx->CFGR = tmpCFGR;
313   LPTIMx->OR = tmpOR;
314 
315   __enable_irq();
316 }
317 
318 /**
319   * @}
320   */
321 
322 /**
323   * @}
324   */
325 
326 /**
327   * @}
328   */
329 
330 #endif /* LPTIM1 || LPTIM2 || LPTIM3 */
331 
332 /**
333   * @}
334   */
335 
336 #endif /* USE_FULL_LL_DRIVER */
337 
338 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
339