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)95ErrorStatus 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)147void 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)166ErrorStatus 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)209void 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