1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_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   *
10   ******************************************************************************
11   * @attention
12   *
13   * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
14   * All rights reserved.</center></h2>
15   *
16   * This software component is licensed by ST under BSD 3-Clause license,
17   * the "License"; You may not use this file except in compliance with the
18   * License. You may obtain a copy of the License at:
19   *                        opensource.org/licenses/BSD-3-Clause
20   *
21   ******************************************************************************
22   */
23 
24 /* Includes ------------------------------------------------------------------*/
25 #include "stm32f1xx_hal.h"
26 
27 /** @addtogroup STM32F1xx_HAL_Driver
28   * @{
29   */
30 
31 #ifdef HAL_RCC_MODULE_ENABLED
32 
33 /** @defgroup RCCEx RCCEx
34   * @brief RCC Extension HAL module driver.
35   * @{
36   */
37 
38 /* Private typedef -----------------------------------------------------------*/
39 /* Private define ------------------------------------------------------------*/
40 /** @defgroup RCCEx_Private_Constants RCCEx Private Constants
41   * @{
42   */
43 /**
44   * @}
45   */
46 
47 /* Private macro -------------------------------------------------------------*/
48 /** @defgroup RCCEx_Private_Macros RCCEx Private Macros
49   * @{
50   */
51 /**
52   * @}
53   */
54 
55 /* Private variables ---------------------------------------------------------*/
56 /* Private function prototypes -----------------------------------------------*/
57 /* Private functions ---------------------------------------------------------*/
58 
59 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
60   * @{
61   */
62 
63 /** @defgroup RCCEx_Exported_Functions_Group1 Peripheral Control functions
64   *  @brief  Extended Peripheral Control functions
65   *
66 @verbatim
67  ===============================================================================
68                 ##### Extended Peripheral Control functions  #####
69  ===============================================================================
70     [..]
71     This subsection provides a set of functions allowing to control the RCC Clocks
72     frequencies.
73     [..]
74     (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
75         select the RTC clock source; in this case the Backup domain will be reset in
76         order to modify the RTC Clock source, as consequence RTC registers (including
77         the backup registers) are set to their reset values.
78 
79 @endverbatim
80   * @{
81   */
82 
83 /**
84   * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
85   *         RCC_PeriphCLKInitTypeDef.
86   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
87   *         contains the configuration information for the Extended Peripherals clocks(RTC clock).
88   *
89   * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
90   *         the RTC clock source; in this case the Backup domain will be reset in
91   *         order to modify the RTC Clock source, as consequence RTC registers (including
92   *         the backup registers) are set to their reset values.
93   *
94   * @note   In case of STM32F105xC or STM32F107xC devices, PLLI2S will be enabled if requested on
95   *         one of 2 I2S interfaces. When PLLI2S is enabled, you need to call HAL_RCCEx_DisablePLLI2S to
96   *         manually disable it.
97   *
98   * @retval HAL status
99   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)100 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
101 {
102   uint32_t tickstart = 0U, temp_reg = 0U;
103 #if defined(STM32F105xC) || defined(STM32F107xC)
104   uint32_t  pllactive = 0U;
105 #endif /* STM32F105xC || STM32F107xC */
106 
107   /* Check the parameters */
108   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
109 
110   /*------------------------------- RTC/LCD Configuration ------------------------*/
111   if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
112   {
113     FlagStatus pwrclkchanged = RESET;
114 
115     /* check for RTC Parameters used to output RTCCLK */
116     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
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   /*------------------------------ ADC clock Configuration ------------------*/
182   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
183   {
184     /* Check the parameters */
185     assert_param(IS_RCC_ADCPLLCLK_DIV(PeriphClkInit->AdcClockSelection));
186 
187     /* Configure the ADC clock source */
188     __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
189   }
190 
191 #if defined(STM32F105xC) || defined(STM32F107xC)
192   /*------------------------------ I2S2 Configuration ------------------------*/
193   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S2) == RCC_PERIPHCLK_I2S2)
194   {
195     /* Check the parameters */
196     assert_param(IS_RCC_I2S2CLKSOURCE(PeriphClkInit->I2s2ClockSelection));
197 
198     /* Configure the I2S2 clock source */
199     __HAL_RCC_I2S2_CONFIG(PeriphClkInit->I2s2ClockSelection);
200   }
201 
202   /*------------------------------ I2S3 Configuration ------------------------*/
203   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S3) == RCC_PERIPHCLK_I2S3)
204   {
205     /* Check the parameters */
206     assert_param(IS_RCC_I2S3CLKSOURCE(PeriphClkInit->I2s3ClockSelection));
207 
208     /* Configure the I2S3 clock source */
209     __HAL_RCC_I2S3_CONFIG(PeriphClkInit->I2s3ClockSelection);
210   }
211 
212   /*------------------------------ PLL I2S Configuration ----------------------*/
213   /* Check that PLLI2S need to be enabled */
214   if (HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_I2S2SRC) || HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_I2S3SRC))
215   {
216     /* Update flag to indicate that PLL I2S should be active */
217     pllactive = 1;
218   }
219 
220   /* Check if PLL I2S need to be enabled */
221   if (pllactive == 1)
222   {
223     /* Enable PLL I2S only if not active */
224     if (HAL_IS_BIT_CLR(RCC->CR, RCC_CR_PLL3ON))
225     {
226       /* Check the parameters */
227       assert_param(IS_RCC_PLLI2S_MUL(PeriphClkInit->PLLI2S.PLLI2SMUL));
228       assert_param(IS_RCC_HSE_PREDIV2(PeriphClkInit->PLLI2S.HSEPrediv2Value));
229 
230       /* Prediv2 can be written only when the PLL2 is disabled. */
231       /* Return an error only if new value is different from the programmed value */
232       if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2ON) && \
233           (__HAL_RCC_HSE_GET_PREDIV2() != PeriphClkInit->PLLI2S.HSEPrediv2Value))
234       {
235         return HAL_ERROR;
236       }
237 
238       /* Configure the HSE prediv2 factor --------------------------------*/
239       __HAL_RCC_HSE_PREDIV2_CONFIG(PeriphClkInit->PLLI2S.HSEPrediv2Value);
240 
241       /* Configure the main PLLI2S multiplication factors. */
242       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SMUL);
243 
244       /* Enable the main PLLI2S. */
245       __HAL_RCC_PLLI2S_ENABLE();
246 
247       /* Get Start Tick*/
248       tickstart = HAL_GetTick();
249 
250       /* Wait till PLLI2S is ready */
251       while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
252       {
253         if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
254         {
255           return HAL_TIMEOUT;
256         }
257       }
258     }
259     else
260     {
261       /* Return an error only if user wants to change the PLLI2SMUL whereas PLLI2S is active */
262       if (READ_BIT(RCC->CFGR2, RCC_CFGR2_PLL3MUL) != PeriphClkInit->PLLI2S.PLLI2SMUL)
263       {
264         return HAL_ERROR;
265       }
266     }
267   }
268 #endif /* STM32F105xC || STM32F107xC */
269 
270 #if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6)\
271  || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)\
272  || defined(STM32F105xC) || defined(STM32F107xC)
273   /*------------------------------ USB clock Configuration ------------------*/
274   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB)
275   {
276     /* Check the parameters */
277     assert_param(IS_RCC_USBPLLCLK_DIV(PeriphClkInit->UsbClockSelection));
278 
279     /* Configure the USB clock source */
280     __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
281   }
282 #endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
283 
284   return HAL_OK;
285 }
286 
287 /**
288   * @brief  Get the PeriphClkInit according to the internal
289   * RCC configuration registers.
290   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
291   *         returns the configuration information for the Extended Peripherals clocks(RTC, I2S, ADC clocks).
292   * @retval None
293   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)294 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
295 {
296   uint32_t srcclk = 0U;
297 
298   /* Set all possible values for the extended clock type parameter------------*/
299   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_RTC;
300 
301   /* Get the RTC configuration -----------------------------------------------*/
302   srcclk = __HAL_RCC_GET_RTC_SOURCE();
303   /* Source clock is LSE or LSI*/
304   PeriphClkInit->RTCClockSelection = srcclk;
305 
306   /* Get the ADC clock configuration -----------------------------------------*/
307   PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_ADC;
308   PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
309 
310 #if defined(STM32F105xC) || defined(STM32F107xC)
311   /* Get the I2S2 clock configuration -----------------------------------------*/
312   PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S2;
313   PeriphClkInit->I2s2ClockSelection = __HAL_RCC_GET_I2S2_SOURCE();
314 
315   /* Get the I2S3 clock configuration -----------------------------------------*/
316   PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S3;
317   PeriphClkInit->I2s3ClockSelection = __HAL_RCC_GET_I2S3_SOURCE();
318 
319 #endif /* STM32F105xC || STM32F107xC */
320 
321 #if defined(STM32F103xE) || defined(STM32F103xG)
322   /* Get the I2S2 clock configuration -----------------------------------------*/
323   PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S2;
324   PeriphClkInit->I2s2ClockSelection = RCC_I2S2CLKSOURCE_SYSCLK;
325 
326   /* Get the I2S3 clock configuration -----------------------------------------*/
327   PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S3;
328   PeriphClkInit->I2s3ClockSelection = RCC_I2S3CLKSOURCE_SYSCLK;
329 
330 #endif /* STM32F103xE || STM32F103xG */
331 
332 #if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6)\
333  || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)\
334  || defined(STM32F105xC) || defined(STM32F107xC)
335   /* Get the USB clock configuration -----------------------------------------*/
336   PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USB;
337   PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
338 #endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
339 }
340 
341 /**
342   * @brief  Returns the peripheral clock frequency
343   * @note   Returns 0 if peripheral clock is unknown
344   * @param  PeriphClk Peripheral clock identifier
345   *         This parameter can be one of the following values:
346   *            @arg @ref RCC_PERIPHCLK_RTC  RTC peripheral clock
347   *            @arg @ref RCC_PERIPHCLK_ADC  ADC peripheral clock
348   @if STM32F103xE
349   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
350   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
351   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
352   @endif
353   @if STM32F103xG
354   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
355   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
356   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
357   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
358   @endif
359   @if STM32F105xC
360   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
361   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
362   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
363   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
364   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
365   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
366   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
367   *            @arg @ref RCC_PERIPHCLK_USB  USB peripheral clock
368   @endif
369   @if STM32F107xC
370   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
371   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
372   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
373   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
374   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
375   *            @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
376   *            @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
377   *            @arg @ref RCC_PERIPHCLK_USB  USB peripheral clock
378   @endif
379   @if STM32F102xx
380   *            @arg @ref RCC_PERIPHCLK_USB  USB peripheral clock
381   @endif
382   @if STM32F103xx
383   *            @arg @ref RCC_PERIPHCLK_USB  USB peripheral clock
384   @endif
385   * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
386   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)387 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
388 {
389 #if defined(STM32F105xC) || defined(STM32F107xC)
390   const uint8_t aPLLMULFactorTable[14] = {0, 0, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 13};
391   const uint8_t aPredivFactorTable[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
392 
393   uint32_t prediv1 = 0U, pllclk = 0U, pllmul = 0U;
394   uint32_t pll2mul = 0U, pll3mul = 0U, prediv2 = 0U;
395 #endif /* STM32F105xC || STM32F107xC */
396 #if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6) || \
397     defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)
398   const uint8_t aPLLMULFactorTable[16] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16};
399   const uint8_t aPredivFactorTable[2] = {1, 2};
400 
401   uint32_t prediv1 = 0U, pllclk = 0U, pllmul = 0U;
402 #endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG */
403   uint32_t temp_reg = 0U, frequency = 0U;
404 
405   /* Check the parameters */
406   assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
407 
408   switch (PeriphClk)
409   {
410 #if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6)\
411  || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)\
412  || defined(STM32F105xC) || defined(STM32F107xC)
413     case RCC_PERIPHCLK_USB:
414     {
415       /* Get RCC configuration ------------------------------------------------------*/
416       temp_reg = RCC->CFGR;
417 
418       /* Check if PLL is enabled */
419       if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLON))
420       {
421         pllmul = aPLLMULFactorTable[(uint32_t)(temp_reg & RCC_CFGR_PLLMULL) >> RCC_CFGR_PLLMULL_Pos];
422         if ((temp_reg & RCC_CFGR_PLLSRC) != RCC_PLLSOURCE_HSI_DIV2)
423         {
424 #if defined(STM32F105xC) || defined(STM32F107xC) || defined(STM32F100xB)\
425  || defined(STM32F100xE)
426           prediv1 = aPredivFactorTable[(uint32_t)(RCC->CFGR2 & RCC_CFGR2_PREDIV1) >> RCC_CFGR2_PREDIV1_Pos];
427 #else
428           prediv1 = aPredivFactorTable[(uint32_t)(RCC->CFGR & RCC_CFGR_PLLXTPRE) >> RCC_CFGR_PLLXTPRE_Pos];
429 #endif /* STM32F105xC || STM32F107xC || STM32F100xB || STM32F100xE */
430 
431 #if defined(STM32F105xC) || defined(STM32F107xC)
432           if (HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC))
433           {
434             /* PLL2 selected as Prediv1 source */
435             /* PLLCLK = PLL2CLK / PREDIV1 * PLLMUL with PLL2CLK = HSE/PREDIV2 * PLL2MUL */
436             prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
437             pll2mul = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> RCC_CFGR2_PLL2MUL_Pos) + 2;
438             pllclk = (uint32_t)((((HSE_VALUE / prediv2) * pll2mul) / prediv1) * pllmul);
439           }
440           else
441           {
442             /* HSE used as PLL clock source : PLLCLK = HSE/PREDIV1 * PLLMUL */
443             pllclk = (uint32_t)((HSE_VALUE / prediv1) * pllmul);
444           }
445 
446           /* If PLLMUL was set to 13 means that it was to cover the case PLLMUL 6.5 (avoid using float) */
447           /* In this case need to divide pllclk by 2 */
448           if (pllmul == aPLLMULFactorTable[(uint32_t)(RCC_CFGR_PLLMULL6_5) >> RCC_CFGR_PLLMULL_Pos])
449           {
450             pllclk = pllclk / 2;
451           }
452 #else
453           if ((temp_reg & RCC_CFGR_PLLSRC) != RCC_PLLSOURCE_HSI_DIV2)
454           {
455             /* HSE used as PLL clock source : PLLCLK = HSE/PREDIV1 * PLLMUL */
456             pllclk = (uint32_t)((HSE_VALUE / prediv1) * pllmul);
457           }
458 #endif /* STM32F105xC || STM32F107xC */
459         }
460         else
461         {
462           /* HSI used as PLL clock source : PLLCLK = HSI/2 * PLLMUL */
463           pllclk = (uint32_t)((HSI_VALUE >> 1) * pllmul);
464         }
465 
466         /* Calcul of the USB frequency*/
467 #if defined(STM32F105xC) || defined(STM32F107xC)
468         /* USBCLK = PLLVCO = (2 x PLLCLK) / USB prescaler */
469         if (__HAL_RCC_GET_USB_SOURCE() == RCC_USBCLKSOURCE_PLL_DIV2)
470         {
471           /* Prescaler of 2 selected for USB */
472           frequency = pllclk;
473         }
474         else
475         {
476           /* Prescaler of 3 selected for USB */
477           frequency = (2 * pllclk) / 3;
478         }
479 #else
480         /* USBCLK = PLLCLK / USB prescaler */
481         if (__HAL_RCC_GET_USB_SOURCE() == RCC_USBCLKSOURCE_PLL)
482         {
483           /* No prescaler selected for USB */
484           frequency = pllclk;
485         }
486         else
487         {
488           /* Prescaler of 1.5 selected for USB */
489           frequency = (pllclk * 2) / 3;
490         }
491 #endif
492       }
493       break;
494     }
495 #endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
496 #if defined(STM32F103xE) || defined(STM32F103xG) || defined(STM32F105xC) || defined(STM32F107xC)
497     case RCC_PERIPHCLK_I2S2:
498     {
499 #if defined(STM32F103xE) || defined(STM32F103xG)
500       /* SYSCLK used as source clock for I2S2 */
501       frequency = HAL_RCC_GetSysClockFreq();
502 #else
503       if (__HAL_RCC_GET_I2S2_SOURCE() == RCC_I2S2CLKSOURCE_SYSCLK)
504       {
505         /* SYSCLK used as source clock for I2S2 */
506         frequency = HAL_RCC_GetSysClockFreq();
507       }
508       else
509       {
510         /* Check if PLLI2S is enabled */
511         if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON))
512         {
513           /* PLLI2SVCO = 2 * PLLI2SCLK = 2 * (HSE/PREDIV2 * PLL3MUL) */
514           prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
515           pll3mul = ((RCC->CFGR2 & RCC_CFGR2_PLL3MUL) >> RCC_CFGR2_PLL3MUL_Pos) + 2;
516           frequency = (uint32_t)(2 * ((HSE_VALUE / prediv2) * pll3mul));
517         }
518       }
519 #endif /* STM32F103xE || STM32F103xG */
520       break;
521     }
522     case RCC_PERIPHCLK_I2S3:
523     {
524 #if defined(STM32F103xE) || defined(STM32F103xG)
525       /* SYSCLK used as source clock for I2S3 */
526       frequency = HAL_RCC_GetSysClockFreq();
527 #else
528       if (__HAL_RCC_GET_I2S3_SOURCE() == RCC_I2S3CLKSOURCE_SYSCLK)
529       {
530         /* SYSCLK used as source clock for I2S3 */
531         frequency = HAL_RCC_GetSysClockFreq();
532       }
533       else
534       {
535         /* Check if PLLI2S is enabled */
536         if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON))
537         {
538           /* PLLI2SVCO = 2 * PLLI2SCLK = 2 * (HSE/PREDIV2 * PLL3MUL) */
539           prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
540           pll3mul = ((RCC->CFGR2 & RCC_CFGR2_PLL3MUL) >> RCC_CFGR2_PLL3MUL_Pos) + 2;
541           frequency = (uint32_t)(2 * ((HSE_VALUE / prediv2) * pll3mul));
542         }
543       }
544 #endif /* STM32F103xE || STM32F103xG */
545       break;
546     }
547 #endif /* STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
548     case RCC_PERIPHCLK_RTC:
549     {
550       /* Get RCC BDCR configuration ------------------------------------------------------*/
551       temp_reg = RCC->BDCR;
552 
553       /* Check if LSE is ready if RTC clock selection is LSE */
554       if (((temp_reg & RCC_BDCR_RTCSEL) == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(temp_reg, RCC_BDCR_LSERDY)))
555       {
556         frequency = LSE_VALUE;
557       }
558       /* Check if LSI is ready if RTC clock selection is LSI */
559       else if (((temp_reg & RCC_BDCR_RTCSEL) == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
560       {
561         frequency = LSI_VALUE;
562       }
563       else if (((temp_reg & RCC_BDCR_RTCSEL) == RCC_RTCCLKSOURCE_HSE_DIV128) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)))
564       {
565         frequency = HSE_VALUE / 128U;
566       }
567       /* Clock not enabled for RTC*/
568       else
569       {
570         /* nothing to do: frequency already initialized to 0U */
571       }
572       break;
573     }
574     case RCC_PERIPHCLK_ADC:
575     {
576       frequency = HAL_RCC_GetPCLK2Freq() / (((__HAL_RCC_GET_ADC_SOURCE() >> RCC_CFGR_ADCPRE_Pos) + 1) * 2);
577       break;
578     }
579     default:
580     {
581       break;
582     }
583   }
584   return (frequency);
585 }
586 
587 /**
588   * @}
589   */
590 
591 #if defined(STM32F105xC) || defined(STM32F107xC)
592 /** @defgroup RCCEx_Exported_Functions_Group2 PLLI2S Management function
593   *  @brief  PLLI2S Management functions
594   *
595 @verbatim
596  ===============================================================================
597                 ##### Extended PLLI2S Management functions  #####
598  ===============================================================================
599     [..]
600     This subsection provides a set of functions allowing to control the PLLI2S
601     activation or deactivation
602 @endverbatim
603   * @{
604   */
605 
606 /**
607   * @brief  Enable PLLI2S
608   * @param  PLLI2SInit pointer to an RCC_PLLI2SInitTypeDef structure that
609   *         contains the configuration information for the PLLI2S
610   * @note   The PLLI2S configuration not modified if used by I2S2 or I2S3 Interface.
611   * @retval HAL status
612   */
HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef * PLLI2SInit)613 HAL_StatusTypeDef HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef  *PLLI2SInit)
614 {
615   uint32_t tickstart = 0U;
616 
617   /* Check that PLL I2S has not been already enabled by I2S2 or I2S3*/
618   if (HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S2SRC) && HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S3SRC))
619   {
620     /* Check the parameters */
621     assert_param(IS_RCC_PLLI2S_MUL(PLLI2SInit->PLLI2SMUL));
622     assert_param(IS_RCC_HSE_PREDIV2(PLLI2SInit->HSEPrediv2Value));
623 
624     /* Prediv2 can be written only when the PLL2 is disabled. */
625     /* Return an error only if new value is different from the programmed value */
626     if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2ON) && \
627         (__HAL_RCC_HSE_GET_PREDIV2() != PLLI2SInit->HSEPrediv2Value))
628     {
629       return HAL_ERROR;
630     }
631 
632     /* Disable the main PLLI2S. */
633     __HAL_RCC_PLLI2S_DISABLE();
634 
635     /* Get Start Tick*/
636     tickstart = HAL_GetTick();
637 
638     /* Wait till PLLI2S is ready */
639     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
640     {
641       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
642       {
643         return HAL_TIMEOUT;
644       }
645     }
646 
647     /* Configure the HSE prediv2 factor --------------------------------*/
648     __HAL_RCC_HSE_PREDIV2_CONFIG(PLLI2SInit->HSEPrediv2Value);
649 
650 
651     /* Configure the main PLLI2S multiplication factors. */
652     __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SMUL);
653 
654     /* Enable the main PLLI2S. */
655     __HAL_RCC_PLLI2S_ENABLE();
656 
657     /* Get Start Tick*/
658     tickstart = HAL_GetTick();
659 
660     /* Wait till PLLI2S is ready */
661     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
662     {
663       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
664       {
665         return HAL_TIMEOUT;
666       }
667     }
668   }
669   else
670   {
671     /* PLLI2S cannot be modified as already used by I2S2 or I2S3 */
672     return HAL_ERROR;
673   }
674 
675   return HAL_OK;
676 }
677 
678 /**
679   * @brief  Disable PLLI2S
680   * @note   PLLI2S is not disabled if used by I2S2 or I2S3 Interface.
681   * @retval HAL status
682   */
HAL_RCCEx_DisablePLLI2S(void)683 HAL_StatusTypeDef HAL_RCCEx_DisablePLLI2S(void)
684 {
685   uint32_t tickstart = 0U;
686 
687   /* Disable PLL I2S as not requested by I2S2 or I2S3*/
688   if (HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S2SRC) && HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S3SRC))
689   {
690     /* Disable the main PLLI2S. */
691     __HAL_RCC_PLLI2S_DISABLE();
692 
693     /* Get Start Tick*/
694     tickstart = HAL_GetTick();
695 
696     /* Wait till PLLI2S is ready */
697     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
698     {
699       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
700       {
701         return HAL_TIMEOUT;
702       }
703     }
704   }
705   else
706   {
707     /* PLLI2S is currently used by I2S2 or I2S3. Cannot be disabled.*/
708     return HAL_ERROR;
709   }
710 
711   return HAL_OK;
712 }
713 
714 /**
715   * @}
716   */
717 
718 /** @defgroup RCCEx_Exported_Functions_Group3 PLL2 Management function
719   *  @brief  PLL2 Management functions
720   *
721 @verbatim
722  ===============================================================================
723                 ##### Extended PLL2 Management functions  #####
724  ===============================================================================
725     [..]
726     This subsection provides a set of functions allowing to control the PLL2
727     activation or deactivation
728 @endverbatim
729   * @{
730   */
731 
732 /**
733   * @brief  Enable PLL2
734   * @param  PLL2Init pointer to an RCC_PLL2InitTypeDef structure that
735   *         contains the configuration information for the PLL2
736   * @note   The PLL2 configuration not modified if used indirectly as system clock.
737   * @retval HAL status
738   */
HAL_RCCEx_EnablePLL2(RCC_PLL2InitTypeDef * PLL2Init)739 HAL_StatusTypeDef HAL_RCCEx_EnablePLL2(RCC_PLL2InitTypeDef  *PLL2Init)
740 {
741   uint32_t tickstart = 0U;
742 
743   /* This bit can not be cleared if the PLL2 clock is used indirectly as system
744     clock (i.e. it is used as PLL clock entry that is used as system clock). */
745   if ((__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) && \
746       (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && \
747       ((READ_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC)) == RCC_CFGR2_PREDIV1SRC_PLL2))
748   {
749     return HAL_ERROR;
750   }
751   else
752   {
753     /* Check the parameters */
754     assert_param(IS_RCC_PLL2_MUL(PLL2Init->PLL2MUL));
755     assert_param(IS_RCC_HSE_PREDIV2(PLL2Init->HSEPrediv2Value));
756 
757     /* Prediv2 can be written only when the PLLI2S is disabled. */
758     /* Return an error only if new value is different from the programmed value */
759     if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON) && \
760         (__HAL_RCC_HSE_GET_PREDIV2() != PLL2Init->HSEPrediv2Value))
761     {
762       return HAL_ERROR;
763     }
764 
765     /* Disable the main PLL2. */
766     __HAL_RCC_PLL2_DISABLE();
767 
768     /* Get Start Tick*/
769     tickstart = HAL_GetTick();
770 
771     /* Wait till PLL2 is disabled */
772     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) != RESET)
773     {
774       if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
775       {
776         return HAL_TIMEOUT;
777       }
778     }
779 
780     /* Configure the HSE prediv2 factor --------------------------------*/
781     __HAL_RCC_HSE_PREDIV2_CONFIG(PLL2Init->HSEPrediv2Value);
782 
783     /* Configure the main PLL2 multiplication factors. */
784     __HAL_RCC_PLL2_CONFIG(PLL2Init->PLL2MUL);
785 
786     /* Enable the main PLL2. */
787     __HAL_RCC_PLL2_ENABLE();
788 
789     /* Get Start Tick*/
790     tickstart = HAL_GetTick();
791 
792     /* Wait till PLL2 is ready */
793     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY)  == RESET)
794     {
795       if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
796       {
797         return HAL_TIMEOUT;
798       }
799     }
800   }
801 
802   return HAL_OK;
803 }
804 
805 /**
806   * @brief  Disable PLL2
807   * @note   PLL2 is not disabled if used indirectly as system clock.
808   * @retval HAL status
809   */
HAL_RCCEx_DisablePLL2(void)810 HAL_StatusTypeDef HAL_RCCEx_DisablePLL2(void)
811 {
812   uint32_t tickstart = 0U;
813 
814   /* This bit can not be cleared if the PLL2 clock is used indirectly as system
815     clock (i.e. it is used as PLL clock entry that is used as system clock). */
816   if ((__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) && \
817       (__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && \
818       ((READ_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC)) == RCC_CFGR2_PREDIV1SRC_PLL2))
819   {
820     return HAL_ERROR;
821   }
822   else
823   {
824     /* Disable the main PLL2. */
825     __HAL_RCC_PLL2_DISABLE();
826 
827     /* Get Start Tick*/
828     tickstart = HAL_GetTick();
829 
830     /* Wait till PLL2 is disabled */
831     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY)  != RESET)
832     {
833       if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
834       {
835         return HAL_TIMEOUT;
836       }
837     }
838   }
839 
840   return HAL_OK;
841 }
842 
843 /**
844   * @}
845   */
846 #endif /* STM32F105xC || STM32F107xC */
847 
848 /**
849   * @}
850   */
851 
852 /**
853   * @}
854   */
855 
856 #endif /* HAL_RCC_MODULE_ENABLED */
857 
858 /**
859   * @}
860   */
861 
862 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
863 
864