1 /**
2 ******************************************************************************
3 * @file stm32f0xx_hal_rcc_ex.c
4 * @author MCD Application Team
5 * @brief Extended RCC HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities RCC extension peripheral:
8 * + Extended Peripheral Control functions
9 * + Extended Clock Recovery System Control functions
10 *
11 ******************************************************************************
12 * @attention
13 *
14 * Copyright (c) 2016 STMicroelectronics.
15 * All rights reserved.
16 *
17 * This software is licensed under terms that can be found in the LICENSE file in
18 * the root directory of this software component.
19 * If no LICENSE file comes with this software, it is provided AS-IS.
20 ******************************************************************************
21 */
22
23 /* Includes ------------------------------------------------------------------*/
24 #include "stm32f0xx_hal.h"
25
26 /** @addtogroup STM32F0xx_HAL_Driver
27 * @{
28 */
29
30 #ifdef HAL_RCC_MODULE_ENABLED
31
32 /** @defgroup RCCEx RCCEx
33 * @brief RCC Extension HAL module driver.
34 * @{
35 */
36
37 /* Private typedef -----------------------------------------------------------*/
38 /* Private define ------------------------------------------------------------*/
39 #if defined(CRS)
40 /** @defgroup RCCEx_Private_Constants RCCEx Private Constants
41 * @{
42 */
43 /* Bit position in register */
44 #define CRS_CFGR_FELIM_BITNUMBER 16
45 #define CRS_CR_TRIM_BITNUMBER 8
46 #define CRS_ISR_FECAP_BITNUMBER 16
47 /**
48 * @}
49 */
50 #endif /* CRS */
51
52 /* Private macro -------------------------------------------------------------*/
53 /** @defgroup RCCEx_Private_Macros RCCEx Private Macros
54 * @{
55 */
56 /**
57 * @}
58 */
59
60 /* Private variables ---------------------------------------------------------*/
61 /* Private function prototypes -----------------------------------------------*/
62 /* Private functions ---------------------------------------------------------*/
63
64 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
65 * @{
66 */
67
68 /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
69 * @brief Extended Peripheral Control functions
70 *
71 @verbatim
72 ===============================================================================
73 ##### Extended Peripheral Control functions #####
74 ===============================================================================
75 [..]
76 This subsection provides a set of functions allowing to control the RCC Clocks
77 frequencies.
78 [..]
79 (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
80 select the RTC clock source; in this case the Backup domain will be reset in
81 order to modify the RTC Clock source, as consequence RTC registers (including
82 the backup registers) are set to their reset values.
83
84 @endverbatim
85 * @{
86 */
87
88 /**
89 * @brief Initializes the RCC extended peripherals clocks according to the specified
90 * parameters in the RCC_PeriphCLKInitTypeDef.
91 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
92 * contains the configuration information for the Extended Peripherals clocks
93 * (USART, RTC, I2C, CEC and USB).
94 *
95 * @note Care must be taken when @ref HAL_RCCEx_PeriphCLKConfig() is used to select
96 * the RTC clock source; in this case the Backup domain will be reset in
97 * order to modify the RTC Clock source, as consequence RTC registers (including
98 * the backup registers) and RCC_BDCR register are set to their reset values.
99 *
100 * @retval HAL status
101 */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)102 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
103 {
104 uint32_t tickstart = 0U;
105 uint32_t temp_reg = 0U;
106
107 /* Check the parameters */
108 assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
109
110 /*---------------------------- RTC configuration -------------------------------*/
111 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
112 {
113 /* check for RTC Parameters used to output RTCCLK */
114 assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
115
116 FlagStatus pwrclkchanged = RESET;
117
118 /* As soon as function is called to change RTC clock source, activation of the
119 power domain is done. */
120 /* Requires to enable write access to Backup Domain of necessary */
121 if(__HAL_RCC_PWR_IS_CLK_DISABLED())
122 {
123 __HAL_RCC_PWR_CLK_ENABLE();
124 pwrclkchanged = SET;
125 }
126
127 if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
128 {
129 /* Enable write access to Backup domain */
130 SET_BIT(PWR->CR, PWR_CR_DBP);
131
132 /* Wait for Backup domain Write protection disable */
133 tickstart = HAL_GetTick();
134
135 while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
136 {
137 if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
138 {
139 return HAL_TIMEOUT;
140 }
141 }
142 }
143
144 /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
145 temp_reg = (RCC->BDCR & RCC_BDCR_RTCSEL);
146 if((temp_reg != 0x00000000U) && (temp_reg != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
147 {
148 /* Store the content of BDCR register before the reset of Backup Domain */
149 temp_reg = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
150 /* RTC Clock selection can be changed only if the Backup Domain is reset */
151 __HAL_RCC_BACKUPRESET_FORCE();
152 __HAL_RCC_BACKUPRESET_RELEASE();
153 /* Restore the Content of BDCR register */
154 RCC->BDCR = temp_reg;
155
156 /* Wait for LSERDY if LSE was enabled */
157 if (HAL_IS_BIT_SET(temp_reg, RCC_BDCR_LSEON))
158 {
159 /* Get Start Tick */
160 tickstart = HAL_GetTick();
161
162 /* Wait till LSE is ready */
163 while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
164 {
165 if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
166 {
167 return HAL_TIMEOUT;
168 }
169 }
170 }
171 }
172 __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
173
174 /* Require to disable power clock if necessary */
175 if(pwrclkchanged == SET)
176 {
177 __HAL_RCC_PWR_CLK_DISABLE();
178 }
179 }
180
181 /*------------------------------- USART1 Configuration ------------------------*/
182 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1)
183 {
184 /* Check the parameters */
185 assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection));
186
187 /* Configure the USART1 clock source */
188 __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection);
189 }
190
191 #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx)\
192 || defined(STM32F091xC) || defined(STM32F098xx)
193 /*----------------------------- USART2 Configuration --------------------------*/
194 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2)
195 {
196 /* Check the parameters */
197 assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection));
198
199 /* Configure the USART2 clock source */
200 __HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection);
201 }
202 #endif /* STM32F071xB || STM32F072xB || STM32F078xx || */
203 /* STM32F091xC || STM32F098xx */
204
205 #if defined(STM32F091xC) || defined(STM32F098xx)
206 /*----------------------------- USART3 Configuration --------------------------*/
207 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3)
208 {
209 /* Check the parameters */
210 assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection));
211
212 /* Configure the USART3 clock source */
213 __HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection);
214 }
215 #endif /* STM32F091xC || STM32F098xx */
216
217 /*------------------------------ I2C1 Configuration ------------------------*/
218 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1)
219 {
220 /* Check the parameters */
221 assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection));
222
223 /* Configure the I2C1 clock source */
224 __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection);
225 }
226
227 #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) || defined(STM32F070x6)
228 /*------------------------------ USB Configuration ------------------------*/
229 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB)
230 {
231 /* Check the parameters */
232 assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection));
233
234 /* Configure the USB clock source */
235 __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
236 }
237 #endif /* STM32F042x6 || STM32F048xx || STM32F072xB || STM32F078xx || STM32F070xB || STM32F070x6 */
238
239 #if defined(STM32F042x6) || defined(STM32F048xx)\
240 || defined(STM32F051x8) || defined(STM32F058xx)\
241 || defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx)\
242 || defined(STM32F091xC) || defined(STM32F098xx)
243 /*------------------------------ CEC clock Configuration -------------------*/
244 if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CEC) == RCC_PERIPHCLK_CEC)
245 {
246 /* Check the parameters */
247 assert_param(IS_RCC_CECCLKSOURCE(PeriphClkInit->CecClockSelection));
248
249 /* Configure the CEC clock source */
250 __HAL_RCC_CEC_CONFIG(PeriphClkInit->CecClockSelection);
251 }
252 #endif /* STM32F042x6 || STM32F048xx || */
253 /* STM32F051x8 || STM32F058xx || */
254 /* STM32F071xB || STM32F072xB || STM32F078xx || */
255 /* STM32F091xC || STM32F098xx */
256
257 return HAL_OK;
258 }
259
260 /**
261 * @brief Get the RCC_ClkInitStruct according to the internal
262 * RCC configuration registers.
263 * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
264 * returns the configuration information for the Extended Peripherals clocks
265 * (USART, RTC, I2C, CEC and USB).
266 * @retval None
267 */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)268 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
269 {
270 /* Set all possible values for the extended clock type parameter------------*/
271 /* Common part first */
272 PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_RTC;
273 /* Get the RTC configuration --------------------------------------------*/
274 PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
275 /* Get the USART1 clock configuration --------------------------------------------*/
276 PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
277 /* Get the I2C1 clock source -----------------------------------------------*/
278 PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
279
280 #if defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx)\
281 || defined(STM32F091xC) || defined(STM32F098xx)
282 PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USART2;
283 /* Get the USART2 clock source ---------------------------------------------*/
284 PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE();
285 #endif /* STM32F071xB || STM32F072xB || STM32F078xx || */
286 /* STM32F091xC || STM32F098xx */
287
288 #if defined(STM32F091xC) || defined(STM32F098xx)
289 PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USART3;
290 /* Get the USART3 clock source ---------------------------------------------*/
291 PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE();
292 #endif /* STM32F091xC || STM32F098xx */
293
294 #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) || defined(STM32F078xx) || defined(STM32F070xB) || defined(STM32F070x6)
295 PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USB;
296 /* Get the USB clock source ---------------------------------------------*/
297 PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
298 #endif /* STM32F042x6 || STM32F048xx || STM32F072xB || STM32F078xx || STM32F070xB || STM32F070x6 */
299
300 #if defined(STM32F042x6) || defined(STM32F048xx)\
301 || defined(STM32F051x8) || defined(STM32F058xx)\
302 || defined(STM32F071xB) || defined(STM32F072xB) || defined(STM32F078xx)\
303 || defined(STM32F091xC) || defined(STM32F098xx)
304 PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_CEC;
305 /* Get the CEC clock source ------------------------------------------------*/
306 PeriphClkInit->CecClockSelection = __HAL_RCC_GET_CEC_SOURCE();
307 #endif /* STM32F042x6 || STM32F048xx || */
308 /* STM32F051x8 || STM32F058xx || */
309 /* STM32F071xB || STM32F072xB || STM32F078xx || */
310 /* STM32F091xC || STM32F098xx */
311
312 }
313
314 /**
315 * @brief Returns the peripheral clock frequency
316 * @note Returns 0 if peripheral clock is unknown
317 * @param PeriphClk Peripheral clock identifier
318 * This parameter can be one of the following values:
319 * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
320 * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
321 * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
322 @if STM32F042x6
323 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
324 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
325 @endif
326 @if STM32F048xx
327 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
328 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
329 @endif
330 @if STM32F051x8
331 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
332 @endif
333 @if STM32F058xx
334 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
335 @endif
336 @if STM32F070x6
337 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
338 @endif
339 @if STM32F070xB
340 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
341 @endif
342 @if STM32F071xB
343 * @arg @ref RCC_PERIPHCLK_USART2 USART2 peripheral clock
344 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
345 @endif
346 @if STM32F072xB
347 * @arg @ref RCC_PERIPHCLK_USART2 USART2 peripheral clock
348 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
349 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
350 @endif
351 @if STM32F078xx
352 * @arg @ref RCC_PERIPHCLK_USART2 USART2 peripheral clock
353 * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
354 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
355 @endif
356 @if STM32F091xC
357 * @arg @ref RCC_PERIPHCLK_USART2 USART2 peripheral clock
358 * @arg @ref RCC_PERIPHCLK_USART3 USART2 peripheral clock
359 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
360 @endif
361 @if STM32F098xx
362 * @arg @ref RCC_PERIPHCLK_USART2 USART2 peripheral clock
363 * @arg @ref RCC_PERIPHCLK_USART3 USART2 peripheral clock
364 * @arg @ref RCC_PERIPHCLK_CEC CEC peripheral clock
365 @endif
366 * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
367 */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)368 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
369 {
370 /* frequency == 0 : means that no available frequency for the peripheral */
371 uint32_t frequency = 0U;
372
373 uint32_t srcclk = 0U;
374 #if defined(USB)
375 uint32_t pllmull = 0U, pllsource = 0U, predivfactor = 0U;
376 #endif /* USB */
377
378 /* Check the parameters */
379 assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
380
381 switch (PeriphClk)
382 {
383 case RCC_PERIPHCLK_RTC:
384 {
385 /* Get the current RTC source */
386 srcclk = __HAL_RCC_GET_RTC_SOURCE();
387
388 /* Check if LSE is ready and if RTC clock selection is LSE */
389 if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
390 {
391 frequency = LSE_VALUE;
392 }
393 /* Check if LSI is ready and if RTC clock selection is LSI */
394 else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
395 {
396 frequency = LSI_VALUE;
397 }
398 /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/
399 else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)))
400 {
401 frequency = HSE_VALUE / 32U;
402 }
403 break;
404 }
405 case RCC_PERIPHCLK_USART1:
406 {
407 /* Get the current USART1 source */
408 srcclk = __HAL_RCC_GET_USART1_SOURCE();
409
410 /* Check if USART1 clock selection is PCLK1 */
411 if (srcclk == RCC_USART1CLKSOURCE_PCLK1)
412 {
413 frequency = HAL_RCC_GetPCLK1Freq();
414 }
415 /* Check if HSI is ready and if USART1 clock selection is HSI */
416 else if ((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
417 {
418 frequency = HSI_VALUE;
419 }
420 /* Check if USART1 clock selection is SYSCLK */
421 else if (srcclk == RCC_USART1CLKSOURCE_SYSCLK)
422 {
423 frequency = HAL_RCC_GetSysClockFreq();
424 }
425 /* Check if LSE is ready and if USART1 clock selection is LSE */
426 else if ((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
427 {
428 frequency = LSE_VALUE;
429 }
430 break;
431 }
432 #if defined(RCC_CFGR3_USART2SW)
433 case RCC_PERIPHCLK_USART2:
434 {
435 /* Get the current USART2 source */
436 srcclk = __HAL_RCC_GET_USART2_SOURCE();
437
438 /* Check if USART2 clock selection is PCLK1 */
439 if (srcclk == RCC_USART2CLKSOURCE_PCLK1)
440 {
441 frequency = HAL_RCC_GetPCLK1Freq();
442 }
443 /* Check if HSI is ready and if USART2 clock selection is HSI */
444 else if ((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
445 {
446 frequency = HSI_VALUE;
447 }
448 /* Check if USART2 clock selection is SYSCLK */
449 else if (srcclk == RCC_USART2CLKSOURCE_SYSCLK)
450 {
451 frequency = HAL_RCC_GetSysClockFreq();
452 }
453 /* Check if LSE is ready and if USART2 clock selection is LSE */
454 else if ((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
455 {
456 frequency = LSE_VALUE;
457 }
458 break;
459 }
460 #endif /* RCC_CFGR3_USART2SW */
461 #if defined(RCC_CFGR3_USART3SW)
462 case RCC_PERIPHCLK_USART3:
463 {
464 /* Get the current USART3 source */
465 srcclk = __HAL_RCC_GET_USART3_SOURCE();
466
467 /* Check if USART3 clock selection is PCLK1 */
468 if (srcclk == RCC_USART3CLKSOURCE_PCLK1)
469 {
470 frequency = HAL_RCC_GetPCLK1Freq();
471 }
472 /* Check if HSI is ready and if USART3 clock selection is HSI */
473 else if ((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
474 {
475 frequency = HSI_VALUE;
476 }
477 /* Check if USART3 clock selection is SYSCLK */
478 else if (srcclk == RCC_USART3CLKSOURCE_SYSCLK)
479 {
480 frequency = HAL_RCC_GetSysClockFreq();
481 }
482 /* Check if LSE is ready and if USART3 clock selection is LSE */
483 else if ((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
484 {
485 frequency = LSE_VALUE;
486 }
487 break;
488 }
489 #endif /* RCC_CFGR3_USART3SW */
490 case RCC_PERIPHCLK_I2C1:
491 {
492 /* Get the current I2C1 source */
493 srcclk = __HAL_RCC_GET_I2C1_SOURCE();
494
495 /* Check if HSI is ready and if I2C1 clock selection is HSI */
496 if ((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
497 {
498 frequency = HSI_VALUE;
499 }
500 /* Check if I2C1 clock selection is SYSCLK */
501 else if (srcclk == RCC_I2C1CLKSOURCE_SYSCLK)
502 {
503 frequency = HAL_RCC_GetSysClockFreq();
504 }
505 break;
506 }
507 #if defined(USB)
508 case RCC_PERIPHCLK_USB:
509 {
510 /* Get the current USB source */
511 srcclk = __HAL_RCC_GET_USB_SOURCE();
512
513 /* Check if PLL is ready and if USB clock selection is PLL */
514 if ((srcclk == RCC_USBCLKSOURCE_PLL) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY)))
515 {
516 /* Get PLL clock source and multiplication factor ----------------------*/
517 pllmull = RCC->CFGR & RCC_CFGR_PLLMUL;
518 pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
519 pllmull = (pllmull >> RCC_CFGR_PLLMUL_BITNUMBER) + 2U;
520 predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1U;
521
522 if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV)
523 {
524 /* HSE used as PLL clock source : frequency = HSE/PREDIV * PLLMUL */
525 frequency = (HSE_VALUE/predivfactor) * pllmull;
526 }
527 #if defined(RCC_CR2_HSI48ON)
528 else if (pllsource == RCC_CFGR_PLLSRC_HSI48_PREDIV)
529 {
530 /* HSI48 used as PLL clock source : frequency = HSI48/PREDIV * PLLMUL */
531 frequency = (HSI48_VALUE / predivfactor) * pllmull;
532 }
533 #endif /* RCC_CR2_HSI48ON */
534 else
535 {
536 #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F078xx) || defined(STM32F072xB) || defined(STM32F070xB)
537 /* HSI used as PLL clock source : frequency = HSI/PREDIV * PLLMUL */
538 frequency = (HSI_VALUE / predivfactor) * pllmull;
539 #else
540 /* HSI used as PLL clock source : frequency = HSI/2U * PLLMUL */
541 frequency = (HSI_VALUE >> 1U) * pllmull;
542 #endif /* STM32F042x6 || STM32F048xx || STM32F072xB || STM32F078xx || STM32F070xB */
543 }
544 }
545 #if defined(RCC_CR2_HSI48ON)
546 /* Check if HSI48 is ready and if USB clock selection is HSI48 */
547 else if ((srcclk == RCC_USBCLKSOURCE_HSI48) && (HAL_IS_BIT_SET(RCC->CR2, RCC_CR2_HSI48RDY)))
548 {
549 frequency = HSI48_VALUE;
550 }
551 #endif /* RCC_CR2_HSI48ON */
552 break;
553 }
554 #endif /* USB */
555 #if defined(CEC)
556 case RCC_PERIPHCLK_CEC:
557 {
558 /* Get the current CEC source */
559 srcclk = __HAL_RCC_GET_CEC_SOURCE();
560
561 /* Check if HSI is ready and if CEC clock selection is HSI */
562 if ((srcclk == RCC_CECCLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
563 {
564 frequency = HSI_VALUE;
565 }
566 /* Check if LSE is ready and if CEC clock selection is LSE */
567 else if ((srcclk == RCC_CECCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
568 {
569 frequency = LSE_VALUE;
570 }
571 break;
572 }
573 #endif /* CEC */
574 default:
575 {
576 break;
577 }
578 }
579 return(frequency);
580 }
581
582 /**
583 * @}
584 */
585
586 #if defined(CRS)
587
588 /** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions
589 * @brief Extended Clock Recovery System Control functions
590 *
591 @verbatim
592 ===============================================================================
593 ##### Extended Clock Recovery System Control functions #####
594 ===============================================================================
595 [..]
596 For devices with Clock Recovery System feature (CRS), RCC Extension HAL driver can be used as follows:
597
598 (#) In System clock config, HSI48 needs to be enabled
599
600 (#) Enable CRS clock in IP MSP init which will use CRS functions
601
602 (#) Call CRS functions as follows:
603 (##) Prepare synchronization configuration necessary for HSI48 calibration
604 (+++) Default values can be set for frequency Error Measurement (reload and error limit)
605 and also HSI48 oscillator smooth trimming.
606 (+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate
607 directly reload value with target and synchronization frequencies values
608 (##) Call function HAL_RCCEx_CRSConfig which
609 (+++) Reset CRS registers to their default values.
610 (+++) Configure CRS registers with synchronization configuration
611 (+++) Enable automatic calibration and frequency error counter feature
612 Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the
613 periodic USB SOF will not be generated by the host. No SYNC signal will therefore be
614 provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock
615 precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs
616 should be used as SYNC signal.
617
618 (##) A polling function is provided to wait for complete synchronization
619 (+++) Call function HAL_RCCEx_CRSWaitSynchronization()
620 (+++) According to CRS status, user can decide to adjust again the calibration or continue
621 application if synchronization is OK
622
623 (#) User can retrieve information related to synchronization in calling function
624 HAL_RCCEx_CRSGetSynchronizationInfo()
625
626 (#) Regarding synchronization status and synchronization information, user can try a new calibration
627 in changing synchronization configuration and call again HAL_RCCEx_CRSConfig.
628 Note: When the SYNC event is detected during the downcounting phase (before reaching the zero value),
629 it means that the actual frequency is lower than the target (and so, that the TRIM value should be
630 incremented), while when it is detected during the upcounting phase it means that the actual frequency
631 is higher (and that the TRIM value should be decremented).
632
633 (#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go
634 through CRS Handler (RCC_IRQn/RCC_IRQHandler)
635 (++) Call function HAL_RCCEx_CRSConfig()
636 (++) Enable RCC_IRQn (thanks to NVIC functions)
637 (++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT)
638 (++) Implement CRS status management in the following user callbacks called from
639 HAL_RCCEx_CRS_IRQHandler():
640 (+++) HAL_RCCEx_CRS_SyncOkCallback()
641 (+++) HAL_RCCEx_CRS_SyncWarnCallback()
642 (+++) HAL_RCCEx_CRS_ExpectedSyncCallback()
643 (+++) HAL_RCCEx_CRS_ErrorCallback()
644
645 (#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate().
646 This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler)
647
648 @endverbatim
649 * @{
650 */
651
652 /**
653 * @brief Start automatic synchronization for polling mode
654 * @param pInit Pointer on RCC_CRSInitTypeDef structure
655 * @retval None
656 */
HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef * pInit)657 void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit)
658 {
659 uint32_t value = 0U;
660
661 /* Check the parameters */
662 assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler));
663 assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source));
664 assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity));
665 assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue));
666 assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue));
667 assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue));
668
669 /* CONFIGURATION */
670
671 /* Before configuration, reset CRS registers to their default values*/
672 __HAL_RCC_CRS_FORCE_RESET();
673 __HAL_RCC_CRS_RELEASE_RESET();
674
675 /* Set the SYNCDIV[2:0] bits according to Prescaler value */
676 /* Set the SYNCSRC[1:0] bits according to Source value */
677 /* Set the SYNCSPOL bit according to Polarity value */
678 value = (pInit->Prescaler | pInit->Source | pInit->Polarity);
679 /* Set the RELOAD[15:0] bits according to ReloadValue value */
680 value |= pInit->ReloadValue;
681 /* Set the FELIM[7:0] bits according to ErrorLimitValue value */
682 value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_BITNUMBER);
683 WRITE_REG(CRS->CFGR, value);
684
685 /* Adjust HSI48 oscillator smooth trimming */
686 /* Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value */
687 MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_BITNUMBER));
688
689 /* START AUTOMATIC SYNCHRONIZATION*/
690
691 /* Enable Automatic trimming & Frequency error counter */
692 SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN);
693 }
694
695 /**
696 * @brief Generate the software synchronization event
697 * @retval None
698 */
HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)699 void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)
700 {
701 SET_BIT(CRS->CR, CRS_CR_SWSYNC);
702 }
703
704 /**
705 * @brief Return synchronization info
706 * @param pSynchroInfo Pointer on RCC_CRSSynchroInfoTypeDef structure
707 * @retval None
708 */
HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef * pSynchroInfo)709 void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo)
710 {
711 /* Check the parameter */
712 assert_param(pSynchroInfo != NULL);
713
714 /* Get the reload value */
715 pSynchroInfo->ReloadValue = (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD));
716
717 /* Get HSI48 oscillator smooth trimming */
718 pSynchroInfo->HSI48CalibrationValue = (uint32_t)(READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_BITNUMBER);
719
720 /* Get Frequency error capture */
721 pSynchroInfo->FreqErrorCapture = (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_BITNUMBER);
722
723 /* Get Frequency error direction */
724 pSynchroInfo->FreqErrorDirection = (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FEDIR));
725 }
726
727 /**
728 * @brief Wait for CRS Synchronization status.
729 * @param Timeout Duration of the timeout
730 * @note Timeout is based on the maximum time to receive a SYNC event based on synchronization
731 * frequency.
732 * @note If Timeout set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned.
733 * @retval Combination of Synchronization status
734 * This parameter can be a combination of the following values:
735 * @arg @ref RCC_CRS_TIMEOUT
736 * @arg @ref RCC_CRS_SYNCOK
737 * @arg @ref RCC_CRS_SYNCWARN
738 * @arg @ref RCC_CRS_SYNCERR
739 * @arg @ref RCC_CRS_SYNCMISS
740 * @arg @ref RCC_CRS_TRIMOVF
741 */
HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)742 uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)
743 {
744 uint32_t crsstatus = RCC_CRS_NONE;
745 uint32_t tickstart = 0U;
746
747 /* Get timeout */
748 tickstart = HAL_GetTick();
749
750 /* Wait for CRS flag or timeout detection */
751 do
752 {
753 if(Timeout != HAL_MAX_DELAY)
754 {
755 if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
756 {
757 crsstatus = RCC_CRS_TIMEOUT;
758 }
759 }
760 /* Check CRS SYNCOK flag */
761 if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK))
762 {
763 /* CRS SYNC event OK */
764 crsstatus |= RCC_CRS_SYNCOK;
765
766 /* Clear CRS SYNC event OK bit */
767 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK);
768 }
769
770 /* Check CRS SYNCWARN flag */
771 if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN))
772 {
773 /* CRS SYNC warning */
774 crsstatus |= RCC_CRS_SYNCWARN;
775
776 /* Clear CRS SYNCWARN bit */
777 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN);
778 }
779
780 /* Check CRS TRIM overflow flag */
781 if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF))
782 {
783 /* CRS SYNC Error */
784 crsstatus |= RCC_CRS_TRIMOVF;
785
786 /* Clear CRS Error bit */
787 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF);
788 }
789
790 /* Check CRS Error flag */
791 if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR))
792 {
793 /* CRS SYNC Error */
794 crsstatus |= RCC_CRS_SYNCERR;
795
796 /* Clear CRS Error bit */
797 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR);
798 }
799
800 /* Check CRS SYNC Missed flag */
801 if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS))
802 {
803 /* CRS SYNC Missed */
804 crsstatus |= RCC_CRS_SYNCMISS;
805
806 /* Clear CRS SYNC Missed bit */
807 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS);
808 }
809
810 /* Check CRS Expected SYNC flag */
811 if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC))
812 {
813 /* frequency error counter reached a zero value */
814 __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC);
815 }
816 } while(RCC_CRS_NONE == crsstatus);
817
818 return crsstatus;
819 }
820
821 /**
822 * @brief Handle the Clock Recovery System interrupt request.
823 * @retval None
824 */
HAL_RCCEx_CRS_IRQHandler(void)825 void HAL_RCCEx_CRS_IRQHandler(void)
826 {
827 uint32_t crserror = RCC_CRS_NONE;
828 /* Get current IT flags and IT sources values */
829 uint32_t itflags = READ_REG(CRS->ISR);
830 uint32_t itsources = READ_REG(CRS->CR);
831
832 /* Check CRS SYNCOK flag */
833 if(((itflags & RCC_CRS_FLAG_SYNCOK) != RESET) && ((itsources & RCC_CRS_IT_SYNCOK) != RESET))
834 {
835 /* Clear CRS SYNC event OK flag */
836 WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC);
837
838 /* user callback */
839 HAL_RCCEx_CRS_SyncOkCallback();
840 }
841 /* Check CRS SYNCWARN flag */
842 else if(((itflags & RCC_CRS_FLAG_SYNCWARN) != RESET) && ((itsources & RCC_CRS_IT_SYNCWARN) != RESET))
843 {
844 /* Clear CRS SYNCWARN flag */
845 WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC);
846
847 /* user callback */
848 HAL_RCCEx_CRS_SyncWarnCallback();
849 }
850 /* Check CRS Expected SYNC flag */
851 else if(((itflags & RCC_CRS_FLAG_ESYNC) != RESET) && ((itsources & RCC_CRS_IT_ESYNC) != RESET))
852 {
853 /* frequency error counter reached a zero value */
854 WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC);
855
856 /* user callback */
857 HAL_RCCEx_CRS_ExpectedSyncCallback();
858 }
859 /* Check CRS Error flags */
860 else
861 {
862 if(((itflags & RCC_CRS_FLAG_ERR) != RESET) && ((itsources & RCC_CRS_IT_ERR) != RESET))
863 {
864 if((itflags & RCC_CRS_FLAG_SYNCERR) != RESET)
865 {
866 crserror |= RCC_CRS_SYNCERR;
867 }
868 if((itflags & RCC_CRS_FLAG_SYNCMISS) != RESET)
869 {
870 crserror |= RCC_CRS_SYNCMISS;
871 }
872 if((itflags & RCC_CRS_FLAG_TRIMOVF) != RESET)
873 {
874 crserror |= RCC_CRS_TRIMOVF;
875 }
876
877 /* Clear CRS Error flags */
878 WRITE_REG(CRS->ICR, CRS_ICR_ERRC);
879
880 /* user error callback */
881 HAL_RCCEx_CRS_ErrorCallback(crserror);
882 }
883 }
884 }
885
886 /**
887 * @brief RCCEx Clock Recovery System SYNCOK interrupt callback.
888 * @retval none
889 */
HAL_RCCEx_CRS_SyncOkCallback(void)890 __weak void HAL_RCCEx_CRS_SyncOkCallback(void)
891 {
892 /* NOTE : This function should not be modified, when the callback is needed,
893 the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file
894 */
895 }
896
897 /**
898 * @brief RCCEx Clock Recovery System SYNCWARN interrupt callback.
899 * @retval none
900 */
HAL_RCCEx_CRS_SyncWarnCallback(void)901 __weak void HAL_RCCEx_CRS_SyncWarnCallback(void)
902 {
903 /* NOTE : This function should not be modified, when the callback is needed,
904 the @ref HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file
905 */
906 }
907
908 /**
909 * @brief RCCEx Clock Recovery System Expected SYNC interrupt callback.
910 * @retval none
911 */
HAL_RCCEx_CRS_ExpectedSyncCallback(void)912 __weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void)
913 {
914 /* NOTE : This function should not be modified, when the callback is needed,
915 the @ref HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file
916 */
917 }
918
919 /**
920 * @brief RCCEx Clock Recovery System Error interrupt callback.
921 * @param Error Combination of Error status.
922 * This parameter can be a combination of the following values:
923 * @arg @ref RCC_CRS_SYNCERR
924 * @arg @ref RCC_CRS_SYNCMISS
925 * @arg @ref RCC_CRS_TRIMOVF
926 * @retval none
927 */
HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)928 __weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)
929 {
930 /* Prevent unused argument(s) compilation warning */
931 UNUSED(Error);
932
933 /* NOTE : This function should not be modified, when the callback is needed,
934 the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file
935 */
936 }
937
938 /**
939 * @}
940 */
941
942 #endif /* CRS */
943
944 /**
945 * @}
946 */
947
948 /**
949 * @}
950 */
951
952 /**
953 * @}
954 */
955
956 #endif /* HAL_RCC_MODULE_ENABLED */
957
958 /**
959 * @}
960 */
961
962