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