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