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