1 /** 2 ****************************************************************************** 3 * @file stm32g4xx_ll_lptim.c 4 * @author MCD Application Team 5 * @brief LPTIM LL module driver. 6 ****************************************************************************** 7 * @attention 8 * 9 * <h2><center>© 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 "stm32g4xx_ll_lptim.h" 23 #include "stm32g4xx_ll_bus.h" 24 #include "stm32g4xx_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 STM32G4xx_LL_Driver 34 * @{ 35 */ 36 37 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)96ErrorStatus 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)122void 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)141ErrorStatus 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)184void 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 293 294 /** 295 * @} 296 */ 297 298 #endif /* USE_FULL_LL_DRIVER */ 299 300 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 301