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