1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_hal_rcc_ex.c
4   * @author  MCD Application Team
5   * @brief   Extension 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) 2017 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 "stm32f4xx_hal.h"
24 
25 /** @addtogroup STM32F4xx_HAL_Driver
26   * @{
27   */
28 
29 /** @defgroup RCCEx RCCEx
30   * @brief RCCEx HAL module driver
31   * @{
32   */
33 
34 #ifdef HAL_RCC_MODULE_ENABLED
35 
36 /* Private typedef -----------------------------------------------------------*/
37 /* Private define ------------------------------------------------------------*/
38 /** @addtogroup RCCEx_Private_Constants
39   * @{
40   */
41 /**
42   * @}
43   */
44 /* Private macro -------------------------------------------------------------*/
45 /* Private variables ---------------------------------------------------------*/
46 /* Private function prototypes -----------------------------------------------*/
47 /* Private functions ---------------------------------------------------------*/
48 /** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
49   *  @{
50   */
51 
52 /** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
53   *  @brief  Extended Peripheral Control functions
54   *
55 @verbatim
56  ===============================================================================
57                 ##### Extended Peripheral Control functions  #####
58  ===============================================================================
59     [..]
60     This subsection provides a set of functions allowing to control the RCC Clocks
61     frequencies.
62     [..]
63     (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
64         select the RTC clock source; in this case the Backup domain will be reset in
65         order to modify the RTC Clock source, as consequence RTC registers (including
66         the backup registers) and RCC_BDCR register are set to their reset values.
67 
68 @endverbatim
69   * @{
70   */
71 
72 #if defined(STM32F446xx)
73 /**
74   * @brief  Initializes the RCC extended peripherals clocks according to the specified
75   *         parameters in the RCC_PeriphCLKInitTypeDef.
76   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
77   *         contains the configuration information for the Extended Peripherals
78   *         clocks(I2S, SAI, LTDC RTC and TIM).
79   *
80   * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
81   *         the RTC clock source; in this case the Backup domain will be reset in
82   *         order to modify the RTC Clock source, as consequence RTC registers (including
83   *         the backup registers) and RCC_BDCR register are set to their reset values.
84   *
85   * @retval HAL status
86   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)87 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
88 {
89   uint32_t tickstart = 0U;
90   uint32_t tmpreg1 = 0U;
91   uint32_t plli2sp = 0U;
92   uint32_t plli2sq = 0U;
93   uint32_t plli2sr = 0U;
94   uint32_t pllsaip = 0U;
95   uint32_t pllsaiq = 0U;
96   uint32_t plli2sused = 0U;
97   uint32_t pllsaiused = 0U;
98 
99   /* Check the peripheral clock selection parameters */
100   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
101 
102   /*------------------------ I2S APB1 configuration --------------------------*/
103   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == (RCC_PERIPHCLK_I2S_APB1))
104   {
105     /* Check the parameters */
106     assert_param(IS_RCC_I2SAPB1CLKSOURCE(PeriphClkInit->I2sApb1ClockSelection));
107 
108     /* Configure I2S Clock source */
109     __HAL_RCC_I2S_APB1_CONFIG(PeriphClkInit->I2sApb1ClockSelection);
110     /* Enable the PLLI2S when it's used as clock source for I2S */
111     if (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)
112     {
113       plli2sused = 1U;
114     }
115   }
116   /*--------------------------------------------------------------------------*/
117 
118   /*---------------------------- I2S APB2 configuration ----------------------*/
119   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == (RCC_PERIPHCLK_I2S_APB2))
120   {
121     /* Check the parameters */
122     assert_param(IS_RCC_I2SAPB2CLKSOURCE(PeriphClkInit->I2sApb2ClockSelection));
123 
124     /* Configure I2S Clock source */
125     __HAL_RCC_I2S_APB2_CONFIG(PeriphClkInit->I2sApb2ClockSelection);
126     /* Enable the PLLI2S when it's used as clock source for I2S */
127     if (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)
128     {
129       plli2sused = 1U;
130     }
131   }
132   /*--------------------------------------------------------------------------*/
133 
134   /*--------------------------- SAI1 configuration ---------------------------*/
135   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == (RCC_PERIPHCLK_SAI1))
136   {
137     /* Check the parameters */
138     assert_param(IS_RCC_SAI1CLKSOURCE(PeriphClkInit->Sai1ClockSelection));
139 
140     /* Configure SAI1 Clock source */
141     __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
142     /* Enable the PLLI2S when it's used as clock source for SAI */
143     if (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)
144     {
145       plli2sused = 1U;
146     }
147     /* Enable the PLLSAI when it's used as clock source for SAI */
148     if (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)
149     {
150       pllsaiused = 1U;
151     }
152   }
153   /*--------------------------------------------------------------------------*/
154 
155   /*-------------------------- SAI2 configuration ----------------------------*/
156   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == (RCC_PERIPHCLK_SAI2))
157   {
158     /* Check the parameters */
159     assert_param(IS_RCC_SAI2CLKSOURCE(PeriphClkInit->Sai2ClockSelection));
160 
161     /* Configure SAI2 Clock source */
162     __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection);
163 
164     /* Enable the PLLI2S when it's used as clock source for SAI */
165     if (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S)
166     {
167       plli2sused = 1U;
168     }
169     /* Enable the PLLSAI when it's used as clock source for SAI */
170     if (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI)
171     {
172       pllsaiused = 1U;
173     }
174   }
175   /*--------------------------------------------------------------------------*/
176 
177   /*----------------------------- RTC configuration --------------------------*/
178   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
179   {
180     /* Check for RTC Parameters used to output RTCCLK */
181     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
182 
183     /* Enable Power Clock*/
184     __HAL_RCC_PWR_CLK_ENABLE();
185 
186     /* Enable write access to Backup domain */
187     PWR->CR |= PWR_CR_DBP;
188 
189     /* Get tick */
190     tickstart = HAL_GetTick();
191 
192     while ((PWR->CR & PWR_CR_DBP) == RESET)
193     {
194       if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
195       {
196         return HAL_TIMEOUT;
197       }
198     }
199     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
200     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
201     if ((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
202     {
203       /* Store the content of BDCR register before the reset of Backup Domain */
204       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
205       /* RTC Clock selection can be changed only if the Backup Domain is reset */
206       __HAL_RCC_BACKUPRESET_FORCE();
207       __HAL_RCC_BACKUPRESET_RELEASE();
208       /* Restore the Content of BDCR register */
209       RCC->BDCR = tmpreg1;
210 
211       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
212       if (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
213       {
214         /* Get tick */
215         tickstart = HAL_GetTick();
216 
217         /* Wait till LSE is ready */
218         while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
219         {
220           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
221           {
222             return HAL_TIMEOUT;
223           }
224         }
225       }
226     }
227     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
228   }
229   /*--------------------------------------------------------------------------*/
230 
231   /*---------------------------- TIM configuration ---------------------------*/
232   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
233   {
234     /* Configure Timer Prescaler */
235     __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
236   }
237   /*--------------------------------------------------------------------------*/
238 
239   /*---------------------------- FMPI2C1 Configuration -----------------------*/
240   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1)
241   {
242     /* Check the parameters */
243     assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection));
244 
245     /* Configure the FMPI2C1 clock source */
246     __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection);
247   }
248   /*--------------------------------------------------------------------------*/
249 
250   /*------------------------------ CEC Configuration -------------------------*/
251   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CEC) == RCC_PERIPHCLK_CEC)
252   {
253     /* Check the parameters */
254     assert_param(IS_RCC_CECCLKSOURCE(PeriphClkInit->CecClockSelection));
255 
256     /* Configure the CEC clock source */
257     __HAL_RCC_CEC_CONFIG(PeriphClkInit->CecClockSelection);
258   }
259   /*--------------------------------------------------------------------------*/
260 
261   /*----------------------------- CLK48 Configuration ------------------------*/
262   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
263   {
264     /* Check the parameters */
265     assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection));
266 
267     /* Configure the CLK48 clock source */
268     __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);
269 
270     /* Enable the PLLSAI when it's used as clock source for CLK48 */
271     if (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP)
272     {
273       pllsaiused = 1U;
274     }
275   }
276   /*--------------------------------------------------------------------------*/
277 
278   /*----------------------------- SDIO Configuration -------------------------*/
279   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO)
280   {
281     /* Check the parameters */
282     assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection));
283 
284     /* Configure the SDIO clock source */
285     __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection);
286   }
287   /*--------------------------------------------------------------------------*/
288 
289   /*------------------------------ SPDIFRX Configuration ---------------------*/
290   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX)
291   {
292     /* Check the parameters */
293     assert_param(IS_RCC_SPDIFRXCLKSOURCE(PeriphClkInit->SpdifClockSelection));
294 
295     /* Configure the SPDIFRX clock source */
296     __HAL_RCC_SPDIFRX_CONFIG(PeriphClkInit->SpdifClockSelection);
297     /* Enable the PLLI2S when it's used as clock source for SPDIFRX */
298     if (PeriphClkInit->SpdifClockSelection == RCC_SPDIFRXCLKSOURCE_PLLI2SP)
299     {
300       plli2sused = 1U;
301     }
302   }
303   /*--------------------------------------------------------------------------*/
304 
305   /*---------------------------- PLLI2S Configuration ------------------------*/
306   /* PLLI2S is configured when a peripheral will use it as source clock : SAI1, SAI2, I2S on APB1,
307      I2S on APB2 or SPDIFRX */
308   if ((plli2sused == 1U) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
309   {
310     /* Disable the PLLI2S */
311     __HAL_RCC_PLLI2S_DISABLE();
312     /* Get tick */
313     tickstart = HAL_GetTick();
314     /* Wait till PLLI2S is disabled */
315     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
316     {
317       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
318       {
319         /* return in case of Timeout detected */
320         return HAL_TIMEOUT;
321       }
322     }
323 
324     /* check for common PLLI2S Parameters */
325     assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM));
326     assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
327 
328     /*------ In Case of PLLI2S is selected as source clock for I2S -----------*/
329     if (((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == RCC_PERIPHCLK_I2S_APB1)
330          && (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)) ||
331         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == RCC_PERIPHCLK_I2S_APB2) && (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)))
332     {
333       /* check for Parameters */
334       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
335 
336       /* Read PLLI2SP/PLLI2SQ value from PLLI2SCFGR register (this value is not needed for I2S configuration) */
337       plli2sp = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
338       plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
339       /* Configure the PLLI2S division factors */
340       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
341       /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
342       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sp, plli2sq,
343                               PeriphClkInit->PLLI2S.PLLI2SR);
344     }
345 
346     /*------- In Case of PLLI2S is selected as source clock for SAI ----------*/
347     if (((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)
348          && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLI2S)) ||
349         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLI2S)))
350     {
351       /* Check for PLLI2S Parameters */
352       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
353       /* Check for PLLI2S/DIVQ parameters */
354       assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));
355 
356       /* Read PLLI2SP/PLLI2SR value from PLLI2SCFGR register (this value is not needed for SAI configuration) */
357       plli2sp = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
358       plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
359       /* Configure the PLLI2S division factors */
360       /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
361       /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
362       /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
363       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sp,
364                               PeriphClkInit->PLLI2S.PLLI2SQ, plli2sr);
365 
366       /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
367       __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
368     }
369 
370     /*------ In Case of PLLI2S is selected as source clock for SPDIFRX -------*/
371     if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX)
372         && (PeriphClkInit->SpdifClockSelection == RCC_SPDIFRXCLKSOURCE_PLLI2SP))
373     {
374       /* check for Parameters */
375       assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP));
376       /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */
377       plli2sq = ((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
378       plli2sr = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
379       /* Configure the PLLI2S division factors */
380       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
381       /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */
382       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SP,
383                               plli2sq, plli2sr);
384     }
385 
386     /*----------------- In Case of PLLI2S is just selected  -----------------*/
387     if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
388     {
389       /* Check for Parameters */
390       assert_param(IS_RCC_PLLI2SP_VALUE(PeriphClkInit->PLLI2S.PLLI2SP));
391       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
392       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
393 
394       /* Configure the PLLI2S division factors */
395       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
396       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SP,
397                               PeriphClkInit->PLLI2S.PLLI2SQ, PeriphClkInit->PLLI2S.PLLI2SR);
398     }
399 
400     /* Enable the PLLI2S */
401     __HAL_RCC_PLLI2S_ENABLE();
402     /* Get tick */
403     tickstart = HAL_GetTick();
404     /* Wait till PLLI2S is ready */
405     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
406     {
407       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
408       {
409         /* return in case of Timeout detected */
410         return HAL_TIMEOUT;
411       }
412     }
413   }
414   /*--------------------------------------------------------------------------*/
415 
416   /*----------------------------- PLLSAI Configuration -----------------------*/
417   /* PLLSAI is configured when a peripheral will use it as source clock : SAI1, SAI2, CLK48 or SDIO */
418   if (pllsaiused == 1U)
419   {
420     /* Disable PLLSAI Clock */
421     __HAL_RCC_PLLSAI_DISABLE();
422     /* Get tick */
423     tickstart = HAL_GetTick();
424     /* Wait till PLLSAI is disabled */
425     while (__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
426     {
427       if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
428       {
429         /* return in case of Timeout detected */
430         return HAL_TIMEOUT;
431       }
432     }
433 
434     /* Check the PLLSAI division factors */
435     assert_param(IS_RCC_PLLSAIM_VALUE(PeriphClkInit->PLLSAI.PLLSAIM));
436     assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));
437 
438     /*------ In Case of PLLSAI is selected as source clock for SAI -----------*/
439     if (((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)
440          && (PeriphClkInit->Sai1ClockSelection == RCC_SAI1CLKSOURCE_PLLSAI)) ||
441         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) && (PeriphClkInit->Sai2ClockSelection == RCC_SAI2CLKSOURCE_PLLSAI)))
442     {
443       /* check for PLLSAIQ Parameter */
444       assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
445       /* check for PLLSAI/DIVQ Parameter */
446       assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));
447 
448       /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
449       pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
450       /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
451       /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
452       /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
453       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIM, PeriphClkInit->PLLSAI.PLLSAIN, pllsaip,
454                               PeriphClkInit->PLLSAI.PLLSAIQ, 0U);
455 
456       /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
457       __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
458     }
459 
460     /*------ In Case of PLLSAI is selected as source clock for CLK48 ---------*/
461     /* In Case of PLLI2S is selected as source clock for CLK48 */
462     if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
463         && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP))
464     {
465       /* check for Parameters */
466       assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP));
467       /* Read PLLSAIQ value from PLLI2SCFGR register (this value is not need for SAI configuration) */
468       pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
469       /* Configure the PLLSAI division factors */
470       /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * (PLLI2SN/PLLSAIM) */
471       /* 48CLK = f(PLLSAI clock output) = f(VCO clock) / PLLSAIP */
472       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIM, PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIP,
473                               pllsaiq, 0U);
474     }
475 
476     /* Enable PLLSAI Clock */
477     __HAL_RCC_PLLSAI_ENABLE();
478     /* Get tick */
479     tickstart = HAL_GetTick();
480     /* Wait till PLLSAI is ready */
481     while (__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
482     {
483       if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
484       {
485         /* return in case of Timeout detected */
486         return HAL_TIMEOUT;
487       }
488     }
489   }
490   return HAL_OK;
491 }
492 
493 /**
494   * @brief  Get the RCC_PeriphCLKInitTypeDef according to the internal
495   *         RCC configuration registers.
496   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
497   *         will be configured.
498   * @retval None
499   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)500 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
501 {
502   uint32_t tempreg;
503 
504   /* Set all possible values for the extended clock type parameter------------*/
505   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 | \
506                                         RCC_PERIPHCLK_SAI1     | RCC_PERIPHCLK_SAI2     | \
507                                         RCC_PERIPHCLK_TIM      | RCC_PERIPHCLK_RTC      | \
508                                         RCC_PERIPHCLK_CEC      | RCC_PERIPHCLK_FMPI2C1  | \
509                                         RCC_PERIPHCLK_CLK48     | RCC_PERIPHCLK_SDIO     | \
510                                         RCC_PERIPHCLK_SPDIFRX;
511 
512   /* Get the PLLI2S Clock configuration --------------------------------------*/
513   PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM) >> RCC_PLLI2SCFGR_PLLI2SM_Pos);
514   PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
515   PeriphClkInit->PLLI2S.PLLI2SP = (uint32_t)((((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SP) >> RCC_PLLI2SCFGR_PLLI2SP_Pos) + 1U) << 1U);
516   PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
517   PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
518   /* Get the PLLSAI Clock configuration --------------------------------------*/
519   PeriphClkInit->PLLSAI.PLLSAIM = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM) >> RCC_PLLSAICFGR_PLLSAIM_Pos);
520   PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos);
521   PeriphClkInit->PLLSAI.PLLSAIP = (uint32_t)((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
522   PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
523   /* Get the PLLSAI/PLLI2S division factors ----------------------------------*/
524   PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos);
525   PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos);
526 
527   /* Get the SAI1 clock configuration ----------------------------------------*/
528   PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();
529 
530   /* Get the SAI2 clock configuration ----------------------------------------*/
531   PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE();
532 
533   /* Get the I2S APB1 clock configuration ------------------------------------*/
534   PeriphClkInit->I2sApb1ClockSelection = __HAL_RCC_GET_I2S_APB1_SOURCE();
535 
536   /* Get the I2S APB2 clock configuration ------------------------------------*/
537   PeriphClkInit->I2sApb2ClockSelection = __HAL_RCC_GET_I2S_APB2_SOURCE();
538 
539   /* Get the RTC Clock configuration -----------------------------------------*/
540   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
541   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
542 
543   /* Get the CEC clock configuration -----------------------------------------*/
544   PeriphClkInit->CecClockSelection = __HAL_RCC_GET_CEC_SOURCE();
545 
546   /* Get the FMPI2C1 clock configuration -------------------------------------*/
547   PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE();
548 
549   /* Get the CLK48 clock configuration ----------------------------------------*/
550   PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();
551 
552   /* Get the SDIO clock configuration ----------------------------------------*/
553   PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE();
554 
555   /* Get the SPDIFRX clock configuration -------------------------------------*/
556   PeriphClkInit->SpdifClockSelection = __HAL_RCC_GET_SPDIFRX_SOURCE();
557 
558   /* Get the TIM Prescaler configuration -------------------------------------*/
559   if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
560   {
561     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
562   }
563   else
564   {
565     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
566   }
567 }
568 
569 /**
570   * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
571   * @note   Return 0 if peripheral clock identifier not managed by this API
572   * @param  PeriphClk Peripheral clock identifier
573   *         This parameter can be one of the following values:
574   *            @arg RCC_PERIPHCLK_SAI1: SAI1 peripheral clock
575   *            @arg RCC_PERIPHCLK_SAI2: SAI2 peripheral clock
576   *            @arg RCC_PERIPHCLK_I2S_APB1: I2S APB1 peripheral clock
577   *            @arg RCC_PERIPHCLK_I2S_APB2: I2S APB2 peripheral clock
578   * @retval Frequency in KHz
579   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)580 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
581 {
582   uint32_t tmpreg1 = 0U;
583   /* This variable used to store the SAI clock frequency (value in Hz) */
584   uint32_t frequency = 0U;
585   /* This variable used to store the VCO Input (value in Hz) */
586   uint32_t vcoinput = 0U;
587   /* This variable used to store the SAI clock source */
588   uint32_t saiclocksource = 0U;
589   uint32_t srcclk = 0U;
590   /* This variable used to store the VCO Output (value in Hz) */
591   uint32_t vcooutput = 0U;
592   switch (PeriphClk)
593   {
594     case RCC_PERIPHCLK_SAI1:
595     case RCC_PERIPHCLK_SAI2:
596     {
597       saiclocksource = RCC->DCKCFGR;
598       saiclocksource &= (RCC_DCKCFGR_SAI1SRC | RCC_DCKCFGR_SAI2SRC);
599       switch (saiclocksource)
600       {
601         case 0U: /* PLLSAI is the clock source for SAI*/
602         {
603           /* Configure the PLLSAI division factor */
604           /* PLLSAI_VCO Input  = PLL_SOURCE/PLLSAIM */
605           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
606           {
607             /* In Case the PLL Source is HSI (Internal Clock) */
608             vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM));
609           }
610           else
611           {
612             /* In Case the PLL Source is HSE (External Clock) */
613             vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIM)));
614           }
615           /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
616           /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
617           tmpreg1 = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24U;
618           frequency = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6U)) / (tmpreg1);
619 
620           /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
621           tmpreg1 = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> 8U) + 1U);
622           frequency = frequency / (tmpreg1);
623           break;
624         }
625         case RCC_DCKCFGR_SAI1SRC_0: /* PLLI2S is the clock source for SAI*/
626         case RCC_DCKCFGR_SAI2SRC_0: /* PLLI2S is the clock source for SAI*/
627         {
628           /* Configure the PLLI2S division factor */
629           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
630           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
631           {
632             /* In Case the PLL Source is HSI (Internal Clock) */
633             vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
634           }
635           else
636           {
637             /* In Case the PLL Source is HSE (External Clock) */
638             vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM)));
639           }
640 
641           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
642           /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
643           tmpreg1 = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24U;
644           frequency = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U)) / (tmpreg1);
645 
646           /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
647           tmpreg1 = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) + 1U);
648           frequency = frequency / (tmpreg1);
649           break;
650         }
651         case RCC_DCKCFGR_SAI1SRC_1: /* PLLR is the clock source for SAI*/
652         case RCC_DCKCFGR_SAI2SRC_1: /* PLLR is the clock source for SAI*/
653         {
654           /* Configure the PLLI2S division factor */
655           /* PLL_VCO Input  = PLL_SOURCE/PLLM */
656           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
657           {
658             /* In Case the PLL Source is HSI (Internal Clock) */
659             vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
660           }
661           else
662           {
663             /* In Case the PLL Source is HSE (External Clock) */
664             vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)));
665           }
666 
667           /* PLL_VCO Output = PLL_VCO Input * PLLN */
668           /* SAI_CLK_x = PLL_VCO Output/PLLR */
669           tmpreg1 = (RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U;
670           frequency = (vcoinput * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U)) / (tmpreg1);
671           break;
672         }
673         case RCC_DCKCFGR_SAI1SRC: /* External clock is the clock source for SAI*/
674         {
675           frequency = EXTERNAL_CLOCK_VALUE;
676           break;
677         }
678         case RCC_DCKCFGR_SAI2SRC: /* PLLSRC(HSE or HSI) is the clock source for SAI*/
679         {
680           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI)
681           {
682             /* In Case the PLL Source is HSI (Internal Clock) */
683             frequency = (uint32_t)(HSI_VALUE);
684           }
685           else
686           {
687             /* In Case the PLL Source is HSE (External Clock) */
688             frequency = (uint32_t)(HSE_VALUE);
689           }
690           break;
691         }
692         default :
693         {
694           break;
695         }
696       }
697       break;
698     }
699     case RCC_PERIPHCLK_I2S_APB1:
700     {
701       /* Get the current I2S source */
702       srcclk = __HAL_RCC_GET_I2S_APB1_SOURCE();
703       switch (srcclk)
704       {
705         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
706         case RCC_I2SAPB1CLKSOURCE_EXT:
707         {
708           /* Set the I2S clock to the external clock  value */
709           frequency = EXTERNAL_CLOCK_VALUE;
710           break;
711         }
712         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
713         case RCC_I2SAPB1CLKSOURCE_PLLI2S:
714         {
715           /* Configure the PLLI2S division factor */
716           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
717           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
718           {
719             /* Get the I2S source clock value */
720             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
721           }
722           else
723           {
724             /* Get the I2S source clock value */
725             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
726           }
727 
728           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
729           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
730           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
731           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
732           break;
733         }
734         /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
735         case RCC_I2SAPB1CLKSOURCE_PLLR:
736         {
737           /* Configure the PLL division factor R */
738           /* PLL_VCO Input  = PLL_SOURCE/PLLM */
739           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
740           {
741             /* Get the I2S source clock value */
742             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
743           }
744           else
745           {
746             /* Get the I2S source clock value */
747             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
748           }
749 
750           /* PLL_VCO Output = PLL_VCO Input * PLLN */
751           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
752           /* I2S_CLK = PLL_VCO Output/PLLR */
753           frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
754           break;
755         }
756         /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
757         case RCC_I2SAPB1CLKSOURCE_PLLSRC:
758         {
759           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
760           {
761             frequency = HSE_VALUE;
762           }
763           else
764           {
765             frequency = HSI_VALUE;
766           }
767           break;
768         }
769         /* Clock not enabled for I2S*/
770         default:
771         {
772           frequency = 0U;
773           break;
774         }
775       }
776       break;
777     }
778     case RCC_PERIPHCLK_I2S_APB2:
779     {
780       /* Get the current I2S source */
781       srcclk = __HAL_RCC_GET_I2S_APB2_SOURCE();
782       switch (srcclk)
783       {
784         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
785         case RCC_I2SAPB2CLKSOURCE_EXT:
786         {
787           /* Set the I2S clock to the external clock  value */
788           frequency = EXTERNAL_CLOCK_VALUE;
789           break;
790         }
791         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
792         case RCC_I2SAPB2CLKSOURCE_PLLI2S:
793         {
794           /* Configure the PLLI2S division factor */
795           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
796           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
797           {
798             /* Get the I2S source clock value */
799             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
800           }
801           else
802           {
803             /* Get the I2S source clock value */
804             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
805           }
806 
807           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
808           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
809           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
810           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
811           break;
812         }
813         /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
814         case RCC_I2SAPB2CLKSOURCE_PLLR:
815         {
816           /* Configure the PLL division factor R */
817           /* PLL_VCO Input  = PLL_SOURCE/PLLM */
818           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
819           {
820             /* Get the I2S source clock value */
821             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
822           }
823           else
824           {
825             /* Get the I2S source clock value */
826             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
827           }
828 
829           /* PLL_VCO Output = PLL_VCO Input * PLLN */
830           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
831           /* I2S_CLK = PLL_VCO Output/PLLR */
832           frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
833           break;
834         }
835         /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
836         case RCC_I2SAPB2CLKSOURCE_PLLSRC:
837         {
838           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
839           {
840             frequency = HSE_VALUE;
841           }
842           else
843           {
844             frequency = HSI_VALUE;
845           }
846           break;
847         }
848         /* Clock not enabled for I2S*/
849         default:
850         {
851           frequency = 0U;
852           break;
853         }
854       }
855       break;
856     }
857     default:
858     {
859       break;
860     }
861   }
862   return frequency;
863 }
864 #endif /* STM32F446xx */
865 
866 #if defined(STM32F469xx) || defined(STM32F479xx)
867 /**
868   * @brief  Initializes the RCC extended peripherals clocks according to the specified
869   *         parameters in the RCC_PeriphCLKInitTypeDef.
870   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
871   *         contains the configuration information for the Extended Peripherals
872   *         clocks(I2S, SAI, LTDC, RTC and TIM).
873   *
874   * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
875   *         the RTC clock source; in this case the Backup domain will be reset in
876   *         order to modify the RTC Clock source, as consequence RTC registers (including
877   *         the backup registers) and RCC_BDCR register are set to their reset values.
878   *
879   * @retval HAL status
880   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)881 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
882 {
883   uint32_t tickstart = 0U;
884   uint32_t tmpreg1 = 0U;
885   uint32_t pllsaip = 0U;
886   uint32_t pllsaiq = 0U;
887   uint32_t pllsair = 0U;
888 
889   /* Check the parameters */
890   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
891 
892   /*--------------------------- CLK48 Configuration --------------------------*/
893   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
894   {
895     /* Check the parameters */
896     assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection));
897 
898     /* Configure the CLK48 clock source */
899     __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);
900   }
901   /*--------------------------------------------------------------------------*/
902 
903   /*------------------------------ SDIO Configuration ------------------------*/
904   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO)
905   {
906     /* Check the parameters */
907     assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection));
908 
909     /* Configure the SDIO clock source */
910     __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection);
911   }
912   /*--------------------------------------------------------------------------*/
913 
914   /*----------------------- SAI/I2S Configuration (PLLI2S) -------------------*/
915   /*------------------- Common configuration SAI/I2S -------------------------*/
916   /* In Case of SAI or I2S Clock Configuration through PLLI2S, PLLI2SN division
917      factor is common parameters for both peripherals */
918   if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) ||
919       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == RCC_PERIPHCLK_SAI_PLLI2S) ||
920       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S))
921   {
922     /* check for Parameters */
923     assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
924 
925     /* Disable the PLLI2S */
926     __HAL_RCC_PLLI2S_DISABLE();
927     /* Get tick */
928     tickstart = HAL_GetTick();
929     /* Wait till PLLI2S is disabled */
930     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
931     {
932       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
933       {
934         /* return in case of Timeout detected */
935         return HAL_TIMEOUT;
936       }
937     }
938 
939     /*---------------------- I2S configuration -------------------------------*/
940     /* In Case of I2S Clock Configuration through PLLI2S, PLLI2SR must be added
941       only for I2S configuration */
942     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))
943     {
944       /* check for Parameters */
945       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
946       /* Configure the PLLI2S division factors */
947       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x (PLLI2SN/PLLM) */
948       /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
949       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
950     }
951 
952     /*---------------------------- SAI configuration -------------------------*/
953     /* In Case of SAI Clock Configuration through PLLI2S, PLLI2SQ and PLLI2S_DIVQ must
954        be added only for SAI configuration */
955     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == (RCC_PERIPHCLK_SAI_PLLI2S))
956     {
957       /* Check the PLLI2S division factors */
958       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
959       assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));
960 
961       /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */
962       tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
963       /* Configure the PLLI2S division factors */
964       /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
965       /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
966       /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
967       __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, tmpreg1);
968       /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
969       __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
970     }
971 
972     /*----------------- In Case of PLLI2S is just selected  -----------------*/
973     if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
974     {
975       /* Check for Parameters */
976       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
977       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
978 
979       /* Configure the PLLI2S multiplication and division factors */
980       __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ,
981                                      PeriphClkInit->PLLI2S.PLLI2SR);
982     }
983 
984     /* Enable the PLLI2S */
985     __HAL_RCC_PLLI2S_ENABLE();
986     /* Get tick */
987     tickstart = HAL_GetTick();
988     /* Wait till PLLI2S is ready */
989     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
990     {
991       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
992       {
993         /* return in case of Timeout detected */
994         return HAL_TIMEOUT;
995       }
996     }
997   }
998   /*--------------------------------------------------------------------------*/
999 
1000   /*----------------------- SAI/LTDC Configuration (PLLSAI) ------------------*/
1001   /*----------------------- Common configuration SAI/LTDC --------------------*/
1002   /* In Case of SAI, LTDC or CLK48 Clock Configuration through PLLSAI, PLLSAIN division
1003      factor is common parameters for these peripherals */
1004   if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == RCC_PERIPHCLK_SAI_PLLSAI) ||
1005       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)             ||
1006       ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)          &&
1007        (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP)))
1008   {
1009     /* Check the PLLSAI division factors */
1010     assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));
1011 
1012     /* Disable PLLSAI Clock */
1013     __HAL_RCC_PLLSAI_DISABLE();
1014     /* Get tick */
1015     tickstart = HAL_GetTick();
1016     /* Wait till PLLSAI is disabled */
1017     while (__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
1018     {
1019       if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
1020       {
1021         /* return in case of Timeout detected */
1022         return HAL_TIMEOUT;
1023       }
1024     }
1025 
1026     /*---------------------------- SAI configuration -------------------------*/
1027     /* In Case of SAI Clock Configuration through PLLSAI, PLLSAIQ and PLLSAI_DIVQ must
1028        be added only for SAI configuration */
1029     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == (RCC_PERIPHCLK_SAI_PLLSAI))
1030     {
1031       assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
1032       assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));
1033 
1034       /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
1035       pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
1036       /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
1037       pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
1038       /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
1039       /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
1040       /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
1041       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, PeriphClkInit->PLLSAI.PLLSAIQ, pllsair);
1042       /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
1043       __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
1044     }
1045 
1046     /*---------------------------- LTDC configuration ------------------------*/
1047     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC))
1048     {
1049       assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR));
1050       assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR));
1051 
1052       /* Read PLLSAIP value from PLLSAICFGR register (this value is not needed for SAI configuration) */
1053       pllsaip = ((((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIP) >> RCC_PLLSAICFGR_PLLSAIP_Pos) + 1U) << 1U);
1054       /* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */
1055       pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
1056       /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
1057       /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
1058       /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */
1059       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, pllsaip, pllsaiq, PeriphClkInit->PLLSAI.PLLSAIR);
1060       /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */
1061       __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR);
1062     }
1063 
1064     /*---------------------------- CLK48 configuration ------------------------*/
1065     /* Configure the PLLSAI when it is used as clock source for CLK48 */
1066     if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == (RCC_PERIPHCLK_CLK48)) &&
1067         (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLSAIP))
1068     {
1069       assert_param(IS_RCC_PLLSAIP_VALUE(PeriphClkInit->PLLSAI.PLLSAIP));
1070 
1071       /* Read PLLSAIQ value from PLLSAICFGR register (this value is not need for SAI configuration) */
1072       pllsaiq = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
1073       /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
1074       pllsair = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
1075       /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
1076       /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
1077       /* CLK48_CLK(first level) = PLLSAI_VCO Output/PLLSAIP */
1078       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIP, pllsaiq, pllsair);
1079     }
1080 
1081     /* Enable PLLSAI Clock */
1082     __HAL_RCC_PLLSAI_ENABLE();
1083     /* Get tick */
1084     tickstart = HAL_GetTick();
1085     /* Wait till PLLSAI is ready */
1086     while (__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
1087     {
1088       if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
1089       {
1090         /* return in case of Timeout detected */
1091         return HAL_TIMEOUT;
1092       }
1093     }
1094   }
1095 
1096   /*--------------------------------------------------------------------------*/
1097 
1098   /*---------------------------- RTC configuration ---------------------------*/
1099   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
1100   {
1101     /* Check for RTC Parameters used to output RTCCLK */
1102     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
1103 
1104     /* Enable Power Clock*/
1105     __HAL_RCC_PWR_CLK_ENABLE();
1106 
1107     /* Enable write access to Backup domain */
1108     PWR->CR |= PWR_CR_DBP;
1109 
1110     /* Get tick */
1111     tickstart = HAL_GetTick();
1112 
1113     while ((PWR->CR & PWR_CR_DBP) == RESET)
1114     {
1115       if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
1116       {
1117         return HAL_TIMEOUT;
1118       }
1119     }
1120     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
1121     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
1122     if ((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
1123     {
1124       /* Store the content of BDCR register before the reset of Backup Domain */
1125       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
1126       /* RTC Clock selection can be changed only if the Backup Domain is reset */
1127       __HAL_RCC_BACKUPRESET_FORCE();
1128       __HAL_RCC_BACKUPRESET_RELEASE();
1129       /* Restore the Content of BDCR register */
1130       RCC->BDCR = tmpreg1;
1131 
1132       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
1133       if (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
1134       {
1135         /* Get tick */
1136         tickstart = HAL_GetTick();
1137 
1138         /* Wait till LSE is ready */
1139         while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
1140         {
1141           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
1142           {
1143             return HAL_TIMEOUT;
1144           }
1145         }
1146       }
1147     }
1148     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
1149   }
1150   /*--------------------------------------------------------------------------*/
1151 
1152   /*---------------------------- TIM configuration ---------------------------*/
1153   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
1154   {
1155     __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
1156   }
1157   return HAL_OK;
1158 }
1159 
1160 /**
1161   * @brief  Configures the RCC_PeriphCLKInitTypeDef according to the internal
1162   * RCC configuration registers.
1163   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
1164   *         will be configured.
1165   * @retval None
1166   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)1167 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
1168 {
1169   uint32_t tempreg;
1170 
1171   /* Set all possible values for the extended clock type parameter------------*/
1172   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S        | RCC_PERIPHCLK_SAI_PLLSAI | \
1173                                         RCC_PERIPHCLK_SAI_PLLI2S | RCC_PERIPHCLK_LTDC       | \
1174                                         RCC_PERIPHCLK_TIM        | RCC_PERIPHCLK_RTC        | \
1175                                         RCC_PERIPHCLK_CLK48       | RCC_PERIPHCLK_SDIO;
1176 
1177   /* Get the PLLI2S Clock configuration --------------------------------------*/
1178   PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
1179   PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
1180   PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
1181   /* Get the PLLSAI Clock configuration --------------------------------------*/
1182   PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos);
1183   PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
1184   PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
1185   /* Get the PLLSAI/PLLI2S division factors ----------------------------------*/
1186   PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos);
1187   PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos);
1188   PeriphClkInit->PLLSAIDivR = (uint32_t)(RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVR);
1189   /* Get the RTC Clock configuration -----------------------------------------*/
1190   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
1191   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
1192 
1193   /* Get the CLK48 clock configuration -------------------------------------*/
1194   PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();
1195 
1196   /* Get the SDIO clock configuration ----------------------------------------*/
1197   PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE();
1198 
1199   if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
1200   {
1201     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
1202   }
1203   else
1204   {
1205     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
1206   }
1207 }
1208 
1209 /**
1210   * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
1211   * @note   Return 0 if peripheral clock identifier not managed by this API
1212   * @param  PeriphClk Peripheral clock identifier
1213   *         This parameter can be one of the following values:
1214   *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
1215   * @retval Frequency in KHz
1216   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)1217 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
1218 {
1219   /* This variable used to store the I2S clock frequency (value in Hz) */
1220   uint32_t frequency = 0U;
1221   /* This variable used to store the VCO Input (value in Hz) */
1222   uint32_t vcoinput = 0U;
1223   uint32_t srcclk = 0U;
1224   /* This variable used to store the VCO Output (value in Hz) */
1225   uint32_t vcooutput = 0U;
1226   switch (PeriphClk)
1227   {
1228     case RCC_PERIPHCLK_I2S:
1229     {
1230       /* Get the current I2S source */
1231       srcclk = __HAL_RCC_GET_I2S_SOURCE();
1232       switch (srcclk)
1233       {
1234         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
1235         case RCC_I2SCLKSOURCE_EXT:
1236         {
1237           /* Set the I2S clock to the external clock  value */
1238           frequency = EXTERNAL_CLOCK_VALUE;
1239           break;
1240         }
1241         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
1242         case RCC_I2SCLKSOURCE_PLLI2S:
1243         {
1244           /* Configure the PLLI2S division factor */
1245           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
1246           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1247           {
1248             /* Get the I2S source clock value */
1249             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
1250           }
1251           else
1252           {
1253             /* Get the I2S source clock value */
1254             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
1255           }
1256 
1257           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
1258           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
1259           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
1260           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
1261           break;
1262         }
1263         /* Clock not enabled for I2S*/
1264         default:
1265         {
1266           frequency = 0U;
1267           break;
1268         }
1269       }
1270       break;
1271     }
1272     default:
1273     {
1274       break;
1275     }
1276   }
1277   return frequency;
1278 }
1279 #endif /* STM32F469xx || STM32F479xx */
1280 
1281 #if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
1282 /**
1283   * @brief  Initializes the RCC extended peripherals clocks according to the specified
1284   *         parameters in the RCC_PeriphCLKInitTypeDef.
1285   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
1286   *         contains the configuration information for the Extended Peripherals
1287   *         clocks(I2S, LTDC RTC and TIM).
1288   *
1289   * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
1290   *         the RTC clock source; in this case the Backup domain will be reset in
1291   *         order to modify the RTC Clock source, as consequence RTC registers (including
1292   *         the backup registers) and RCC_BDCR register are set to their reset values.
1293   *
1294   * @retval HAL status
1295   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)1296 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
1297 {
1298   uint32_t tickstart = 0U;
1299   uint32_t tmpreg1 = 0U;
1300 #if defined(STM32F413xx) || defined(STM32F423xx)
1301   uint32_t plli2sq = 0U;
1302 #endif /* STM32F413xx || STM32F423xx */
1303   uint32_t plli2sused = 0U;
1304 
1305   /* Check the peripheral clock selection parameters */
1306   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
1307 
1308   /*----------------------------------- I2S APB1 configuration ---------------*/
1309   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == (RCC_PERIPHCLK_I2S_APB1))
1310   {
1311     /* Check the parameters */
1312     assert_param(IS_RCC_I2SAPB1CLKSOURCE(PeriphClkInit->I2sApb1ClockSelection));
1313 
1314     /* Configure I2S Clock source */
1315     __HAL_RCC_I2S_APB1_CONFIG(PeriphClkInit->I2sApb1ClockSelection);
1316     /* Enable the PLLI2S when it's used as clock source for I2S */
1317     if (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)
1318     {
1319       plli2sused = 1U;
1320     }
1321   }
1322   /*--------------------------------------------------------------------------*/
1323 
1324   /*----------------------------------- I2S APB2 configuration ---------------*/
1325   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == (RCC_PERIPHCLK_I2S_APB2))
1326   {
1327     /* Check the parameters */
1328     assert_param(IS_RCC_I2SAPB2CLKSOURCE(PeriphClkInit->I2sApb2ClockSelection));
1329 
1330     /* Configure I2S Clock source */
1331     __HAL_RCC_I2S_APB2_CONFIG(PeriphClkInit->I2sApb2ClockSelection);
1332     /* Enable the PLLI2S when it's used as clock source for I2S */
1333     if (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)
1334     {
1335       plli2sused = 1U;
1336     }
1337   }
1338   /*--------------------------------------------------------------------------*/
1339 
1340 #if defined(STM32F413xx) || defined(STM32F423xx)
1341   /*----------------------- SAI1 Block A configuration -----------------------*/
1342   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIA) == (RCC_PERIPHCLK_SAIA))
1343   {
1344     /* Check the parameters */
1345     assert_param(IS_RCC_SAIACLKSOURCE(PeriphClkInit->SaiAClockSelection));
1346 
1347     /* Configure SAI1 Clock source */
1348     __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(PeriphClkInit->SaiAClockSelection);
1349     /* Enable the PLLI2S when it's used as clock source for SAI */
1350     if (PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLI2SR)
1351     {
1352       plli2sused = 1U;
1353     }
1354     /* Enable the PLLSAI when it's used as clock source for SAI */
1355     if (PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLR)
1356     {
1357       /* Check for PLL/DIVR parameters */
1358       assert_param(IS_RCC_PLL_DIVR_VALUE(PeriphClkInit->PLLDivR));
1359 
1360       /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */
1361       __HAL_RCC_PLL_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLDivR);
1362     }
1363   }
1364   /*--------------------------------------------------------------------------*/
1365 
1366   /*---------------------- SAI1 Block B configuration ------------------------*/
1367   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIB) == (RCC_PERIPHCLK_SAIB))
1368   {
1369     /* Check the parameters */
1370     assert_param(IS_RCC_SAIBCLKSOURCE(PeriphClkInit->SaiBClockSelection));
1371 
1372     /* Configure SAI1 Clock source */
1373     __HAL_RCC_SAI_BLOCKBCLKSOURCE_CONFIG(PeriphClkInit->SaiBClockSelection);
1374     /* Enable the PLLI2S when it's used as clock source for SAI */
1375     if (PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLI2SR)
1376     {
1377       plli2sused = 1U;
1378     }
1379     /* Enable the PLLSAI when it's used as clock source for SAI */
1380     if (PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLR)
1381     {
1382       /* Check for PLL/DIVR parameters */
1383       assert_param(IS_RCC_PLL_DIVR_VALUE(PeriphClkInit->PLLDivR));
1384 
1385       /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */
1386       __HAL_RCC_PLL_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLDivR);
1387     }
1388   }
1389   /*--------------------------------------------------------------------------*/
1390 #endif /* STM32F413xx || STM32F423xx */
1391 
1392   /*------------------------------------ RTC configuration -------------------*/
1393   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
1394   {
1395     /* Check for RTC Parameters used to output RTCCLK */
1396     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
1397 
1398     /* Enable Power Clock*/
1399     __HAL_RCC_PWR_CLK_ENABLE();
1400 
1401     /* Enable write access to Backup domain */
1402     PWR->CR |= PWR_CR_DBP;
1403 
1404     /* Get tick */
1405     tickstart = HAL_GetTick();
1406 
1407     while ((PWR->CR & PWR_CR_DBP) == RESET)
1408     {
1409       if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
1410       {
1411         return HAL_TIMEOUT;
1412       }
1413     }
1414     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
1415     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
1416     if ((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
1417     {
1418       /* Store the content of BDCR register before the reset of Backup Domain */
1419       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
1420       /* RTC Clock selection can be changed only if the Backup Domain is reset */
1421       __HAL_RCC_BACKUPRESET_FORCE();
1422       __HAL_RCC_BACKUPRESET_RELEASE();
1423       /* Restore the Content of BDCR register */
1424       RCC->BDCR = tmpreg1;
1425 
1426       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
1427       if (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
1428       {
1429         /* Get tick */
1430         tickstart = HAL_GetTick();
1431 
1432         /* Wait till LSE is ready */
1433         while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
1434         {
1435           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
1436           {
1437             return HAL_TIMEOUT;
1438           }
1439         }
1440       }
1441     }
1442     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
1443   }
1444   /*--------------------------------------------------------------------------*/
1445 
1446   /*------------------------------------ TIM configuration -------------------*/
1447   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
1448   {
1449     /* Configure Timer Prescaler */
1450     __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
1451   }
1452   /*--------------------------------------------------------------------------*/
1453 
1454   /*------------------------------------- FMPI2C1 Configuration --------------*/
1455   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1)
1456   {
1457     /* Check the parameters */
1458     assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection));
1459 
1460     /* Configure the FMPI2C1 clock source */
1461     __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection);
1462   }
1463   /*--------------------------------------------------------------------------*/
1464 
1465   /*------------------------------------- CLK48 Configuration ----------------*/
1466   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48)
1467   {
1468     /* Check the parameters */
1469     assert_param(IS_RCC_CLK48CLKSOURCE(PeriphClkInit->Clk48ClockSelection));
1470 
1471     /* Configure the SDIO clock source */
1472     __HAL_RCC_CLK48_CONFIG(PeriphClkInit->Clk48ClockSelection);
1473 
1474     /* Enable the PLLI2S when it's used as clock source for CLK48 */
1475     if (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)
1476     {
1477       plli2sused = 1U;
1478     }
1479   }
1480   /*--------------------------------------------------------------------------*/
1481 
1482   /*------------------------------------- SDIO Configuration -----------------*/
1483   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO)
1484   {
1485     /* Check the parameters */
1486     assert_param(IS_RCC_SDIOCLKSOURCE(PeriphClkInit->SdioClockSelection));
1487 
1488     /* Configure the SDIO clock source */
1489     __HAL_RCC_SDIO_CONFIG(PeriphClkInit->SdioClockSelection);
1490   }
1491   /*--------------------------------------------------------------------------*/
1492 
1493   /*-------------------------------------- PLLI2S Configuration --------------*/
1494   /* PLLI2S is configured when a peripheral will use it as source clock : I2S on APB1 or
1495      I2S on APB2*/
1496   if ((plli2sused == 1U) || (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
1497   {
1498     /* Disable the PLLI2S */
1499     __HAL_RCC_PLLI2S_DISABLE();
1500     /* Get tick */
1501     tickstart = HAL_GetTick();
1502     /* Wait till PLLI2S is disabled */
1503     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
1504     {
1505       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
1506       {
1507         /* return in case of Timeout detected */
1508         return HAL_TIMEOUT;
1509       }
1510     }
1511 
1512     /* check for common PLLI2S Parameters */
1513     assert_param(IS_RCC_PLLI2SCLKSOURCE(PeriphClkInit->PLLI2SSelection));
1514     assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM));
1515     assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
1516     /*-------------------- Set the PLL I2S clock -----------------------------*/
1517     __HAL_RCC_PLL_I2S_CONFIG(PeriphClkInit->PLLI2SSelection);
1518 
1519     /*------- In Case of PLLI2S is selected as source clock for I2S ----------*/
1520     if (((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB1) == RCC_PERIPHCLK_I2S_APB1)
1521          && (PeriphClkInit->I2sApb1ClockSelection == RCC_I2SAPB1CLKSOURCE_PLLI2S)) ||
1522         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S_APB2) == RCC_PERIPHCLK_I2S_APB2) && (PeriphClkInit->I2sApb2ClockSelection == RCC_I2SAPB2CLKSOURCE_PLLI2S)) ||
1523         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CLK48) == RCC_PERIPHCLK_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)) ||
1524         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDIO) == RCC_PERIPHCLK_SDIO) && (PeriphClkInit->SdioClockSelection == RCC_SDIOCLKSOURCE_CLK48) && (PeriphClkInit->Clk48ClockSelection == RCC_CLK48CLKSOURCE_PLLI2SQ)))
1525     {
1526       /* check for Parameters */
1527       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
1528       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
1529 
1530       /* Configure the PLLI2S division factors */
1531       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/
1532       /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
1533       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ,
1534                               PeriphClkInit->PLLI2S.PLLI2SR);
1535     }
1536 
1537 #if defined(STM32F413xx) || defined(STM32F423xx)
1538     /*------- In Case of PLLI2S is selected as source clock for SAI ----------*/
1539     if (((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIA) == RCC_PERIPHCLK_SAIA)
1540          && (PeriphClkInit->SaiAClockSelection == RCC_SAIACLKSOURCE_PLLI2SR)) ||
1541         ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAIB) == RCC_PERIPHCLK_SAIB) && (PeriphClkInit->SaiBClockSelection == RCC_SAIBCLKSOURCE_PLLI2SR)))
1542     {
1543       /* Check for PLLI2S Parameters */
1544       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
1545       /* Check for PLLI2S/DIVR parameters */
1546       assert_param(IS_RCC_PLLI2S_DIVR_VALUE(PeriphClkInit->PLLI2SDivR));
1547 
1548       /* Read PLLI2SQ value from PLLI2SCFGR register (this value is not needed for SAI configuration) */
1549       plli2sq = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
1550       /* Configure the PLLI2S division factors */
1551       /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
1552       /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
1553       /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
1554       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, plli2sq,
1555                               PeriphClkInit->PLLI2S.PLLI2SR);
1556 
1557       /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVR */
1558       __HAL_RCC_PLLI2S_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLI2SDivR);
1559     }
1560 #endif /* STM32F413xx || STM32F423xx */
1561 
1562     /*----------------- In Case of PLLI2S is just selected  ------------------*/
1563     if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
1564     {
1565       /* Check for Parameters */
1566       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
1567       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
1568 
1569       /* Configure the PLLI2S division factors */
1570       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/
1571       /* SPDIFRXCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SP */
1572       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ,
1573                               PeriphClkInit->PLLI2S.PLLI2SR);
1574     }
1575 
1576     /* Enable the PLLI2S */
1577     __HAL_RCC_PLLI2S_ENABLE();
1578     /* Get tick */
1579     tickstart = HAL_GetTick();
1580     /* Wait till PLLI2S is ready */
1581     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
1582     {
1583       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
1584       {
1585         /* return in case of Timeout detected */
1586         return HAL_TIMEOUT;
1587       }
1588     }
1589   }
1590   /*--------------------------------------------------------------------------*/
1591 
1592   /*-------------------- DFSDM1 clock source configuration -------------------*/
1593   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1)
1594   {
1595     /* Check the parameters */
1596     assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection));
1597 
1598     /* Configure the DFSDM1 interface clock source */
1599     __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection);
1600   }
1601   /*--------------------------------------------------------------------------*/
1602 
1603   /*-------------------- DFSDM1 Audio clock source configuration -------------*/
1604   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1_AUDIO) == RCC_PERIPHCLK_DFSDM1_AUDIO)
1605   {
1606     /* Check the parameters */
1607     assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection));
1608 
1609     /* Configure the DFSDM1 Audio interface clock source */
1610     __HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection);
1611   }
1612   /*--------------------------------------------------------------------------*/
1613 
1614 #if defined(STM32F413xx) || defined(STM32F423xx)
1615   /*-------------------- DFSDM2 clock source configuration -------------------*/
1616   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2) == RCC_PERIPHCLK_DFSDM2)
1617   {
1618     /* Check the parameters */
1619     assert_param(IS_RCC_DFSDM2CLKSOURCE(PeriphClkInit->Dfsdm2ClockSelection));
1620 
1621     /* Configure the DFSDM1 interface clock source */
1622     __HAL_RCC_DFSDM2_CONFIG(PeriphClkInit->Dfsdm2ClockSelection);
1623   }
1624   /*--------------------------------------------------------------------------*/
1625 
1626   /*-------------------- DFSDM2 Audio clock source configuration -------------*/
1627   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2_AUDIO) == RCC_PERIPHCLK_DFSDM2_AUDIO)
1628   {
1629     /* Check the parameters */
1630     assert_param(IS_RCC_DFSDM2AUDIOCLKSOURCE(PeriphClkInit->Dfsdm2AudioClockSelection));
1631 
1632     /* Configure the DFSDM1 Audio interface clock source */
1633     __HAL_RCC_DFSDM2AUDIO_CONFIG(PeriphClkInit->Dfsdm2AudioClockSelection);
1634   }
1635   /*--------------------------------------------------------------------------*/
1636 
1637   /*---------------------------- LPTIM1 Configuration ------------------------*/
1638   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1)
1639   {
1640     /* Check the parameters */
1641     assert_param(IS_RCC_LPTIM1CLKSOURCE(PeriphClkInit->Lptim1ClockSelection));
1642 
1643     /* Configure the LPTIM1 clock source */
1644     __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
1645   }
1646   /*--------------------------------------------------------------------------*/
1647 #endif /* STM32F413xx || STM32F423xx */
1648 
1649   return HAL_OK;
1650 }
1651 
1652 /**
1653   * @brief  Get the RCC_PeriphCLKInitTypeDef according to the internal
1654   *         RCC configuration registers.
1655   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
1656   *         will be configured.
1657   * @retval None
1658   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)1659 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
1660 {
1661   uint32_t tempreg;
1662 
1663   /* Set all possible values for the extended clock type parameter------------*/
1664 #if defined(STM32F413xx) || defined(STM32F423xx)
1665   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1     | RCC_PERIPHCLK_I2S_APB2 | \
1666                                         RCC_PERIPHCLK_TIM          | RCC_PERIPHCLK_RTC      | \
1667                                         RCC_PERIPHCLK_FMPI2C1      | RCC_PERIPHCLK_CLK48    | \
1668                                         RCC_PERIPHCLK_SDIO         | RCC_PERIPHCLK_DFSDM1   | \
1669                                         RCC_PERIPHCLK_DFSDM1_AUDIO | RCC_PERIPHCLK_DFSDM2   | \
1670                                         RCC_PERIPHCLK_DFSDM2_AUDIO | RCC_PERIPHCLK_LPTIM1   | \
1671                                         RCC_PERIPHCLK_SAIA         | RCC_PERIPHCLK_SAIB;
1672 #else /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */
1673   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S_APB1 | RCC_PERIPHCLK_I2S_APB2 | \
1674                                         RCC_PERIPHCLK_TIM      | RCC_PERIPHCLK_RTC      | \
1675                                         RCC_PERIPHCLK_FMPI2C1  | RCC_PERIPHCLK_CLK48    | \
1676                                         RCC_PERIPHCLK_SDIO     | RCC_PERIPHCLK_DFSDM1   | \
1677                                         RCC_PERIPHCLK_DFSDM1_AUDIO;
1678 #endif /* STM32F413xx || STM32F423xx */
1679 
1680 
1681 
1682   /* Get the PLLI2S Clock configuration --------------------------------------*/
1683   PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM) >> RCC_PLLI2SCFGR_PLLI2SM_Pos);
1684   PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
1685   PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
1686   PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
1687 #if defined(STM32F413xx) || defined(STM32F423xx)
1688   /* Get the PLL/PLLI2S division factors -------------------------------------*/
1689   PeriphClkInit->PLLI2SDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVR) >> RCC_DCKCFGR_PLLI2SDIVR_Pos);
1690   PeriphClkInit->PLLDivR = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLDIVR) >> RCC_DCKCFGR_PLLDIVR_Pos);
1691 #endif /* STM32F413xx || STM32F423xx */
1692 
1693   /* Get the I2S APB1 clock configuration ------------------------------------*/
1694   PeriphClkInit->I2sApb1ClockSelection = __HAL_RCC_GET_I2S_APB1_SOURCE();
1695 
1696   /* Get the I2S APB2 clock configuration ------------------------------------*/
1697   PeriphClkInit->I2sApb2ClockSelection = __HAL_RCC_GET_I2S_APB2_SOURCE();
1698 
1699   /* Get the RTC Clock configuration -----------------------------------------*/
1700   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
1701   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
1702 
1703   /* Get the FMPI2C1 clock configuration -------------------------------------*/
1704   PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE();
1705 
1706   /* Get the CLK48 clock configuration ---------------------------------------*/
1707   PeriphClkInit->Clk48ClockSelection = __HAL_RCC_GET_CLK48_SOURCE();
1708 
1709   /* Get the SDIO clock configuration ----------------------------------------*/
1710   PeriphClkInit->SdioClockSelection = __HAL_RCC_GET_SDIO_SOURCE();
1711 
1712   /* Get the DFSDM1 clock configuration --------------------------------------*/
1713   PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE();
1714 
1715   /* Get the DFSDM1 Audio clock configuration --------------------------------*/
1716   PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE();
1717 
1718 #if defined(STM32F413xx) || defined(STM32F423xx)
1719   /* Get the DFSDM2 clock configuration --------------------------------------*/
1720   PeriphClkInit->Dfsdm2ClockSelection = __HAL_RCC_GET_DFSDM2_SOURCE();
1721 
1722   /* Get the DFSDM2 Audio clock configuration --------------------------------*/
1723   PeriphClkInit->Dfsdm2AudioClockSelection = __HAL_RCC_GET_DFSDM2AUDIO_SOURCE();
1724 
1725   /* Get the LPTIM1 clock configuration --------------------------------------*/
1726   PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
1727 
1728   /* Get the SAI1 Block Aclock configuration ---------------------------------*/
1729   PeriphClkInit->SaiAClockSelection = __HAL_RCC_GET_SAI_BLOCKA_SOURCE();
1730 
1731   /* Get the SAI1 Block B clock configuration --------------------------------*/
1732   PeriphClkInit->SaiBClockSelection = __HAL_RCC_GET_SAI_BLOCKB_SOURCE();
1733 #endif /* STM32F413xx || STM32F423xx */
1734 
1735   /* Get the TIM Prescaler configuration -------------------------------------*/
1736   if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
1737   {
1738     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
1739   }
1740   else
1741   {
1742     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
1743   }
1744 }
1745 
1746 /**
1747   * @brief  Return the peripheral clock frequency for a given peripheral(I2S..)
1748   * @note   Return 0 if peripheral clock identifier not managed by this API
1749   * @param  PeriphClk Peripheral clock identifier
1750   *         This parameter can be one of the following values:
1751   *            @arg RCC_PERIPHCLK_I2S_APB1: I2S APB1 peripheral clock
1752   *            @arg RCC_PERIPHCLK_I2S_APB2: I2S APB2 peripheral clock
1753   * @retval Frequency in KHz
1754   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)1755 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
1756 {
1757   /* This variable used to store the I2S clock frequency (value in Hz) */
1758   uint32_t frequency = 0U;
1759   /* This variable used to store the VCO Input (value in Hz) */
1760   uint32_t vcoinput = 0U;
1761   uint32_t srcclk = 0U;
1762   /* This variable used to store the VCO Output (value in Hz) */
1763   uint32_t vcooutput = 0U;
1764   switch (PeriphClk)
1765   {
1766     case RCC_PERIPHCLK_I2S_APB1:
1767     {
1768       /* Get the current I2S source */
1769       srcclk = __HAL_RCC_GET_I2S_APB1_SOURCE();
1770       switch (srcclk)
1771       {
1772         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
1773         case RCC_I2SAPB1CLKSOURCE_EXT:
1774         {
1775           /* Set the I2S clock to the external clock  value */
1776           frequency = EXTERNAL_CLOCK_VALUE;
1777           break;
1778         }
1779         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
1780         case RCC_I2SAPB1CLKSOURCE_PLLI2S:
1781         {
1782           if ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SSRC) == RCC_PLLI2SCFGR_PLLI2SSRC)
1783           {
1784             /* Get the I2S source clock value */
1785             vcoinput = (uint32_t)(EXTERNAL_CLOCK_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
1786           }
1787           else
1788           {
1789             /* Configure the PLLI2S division factor */
1790             /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
1791             if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1792             {
1793               /* Get the I2S source clock value */
1794               vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
1795             }
1796             else
1797             {
1798               /* Get the I2S source clock value */
1799               vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
1800             }
1801           }
1802           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
1803           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
1804           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
1805           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
1806           break;
1807         }
1808         /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
1809         case RCC_I2SAPB1CLKSOURCE_PLLR:
1810         {
1811           /* Configure the PLL division factor R */
1812           /* PLL_VCO Input  = PLL_SOURCE/PLLM */
1813           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1814           {
1815             /* Get the I2S source clock value */
1816             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
1817           }
1818           else
1819           {
1820             /* Get the I2S source clock value */
1821             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
1822           }
1823 
1824           /* PLL_VCO Output = PLL_VCO Input * PLLN */
1825           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
1826           /* I2S_CLK = PLL_VCO Output/PLLR */
1827           frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
1828           break;
1829         }
1830         /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
1831         case RCC_I2SAPB1CLKSOURCE_PLLSRC:
1832         {
1833           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1834           {
1835             frequency = HSE_VALUE;
1836           }
1837           else
1838           {
1839             frequency = HSI_VALUE;
1840           }
1841           break;
1842         }
1843         /* Clock not enabled for I2S*/
1844         default:
1845         {
1846           frequency = 0U;
1847           break;
1848         }
1849       }
1850       break;
1851     }
1852     case RCC_PERIPHCLK_I2S_APB2:
1853     {
1854       /* Get the current I2S source */
1855       srcclk = __HAL_RCC_GET_I2S_APB2_SOURCE();
1856       switch (srcclk)
1857       {
1858         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
1859         case RCC_I2SAPB2CLKSOURCE_EXT:
1860         {
1861           /* Set the I2S clock to the external clock  value */
1862           frequency = EXTERNAL_CLOCK_VALUE;
1863           break;
1864         }
1865         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
1866         case RCC_I2SAPB2CLKSOURCE_PLLI2S:
1867         {
1868           if ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SSRC) == RCC_PLLI2SCFGR_PLLI2SSRC)
1869           {
1870             /* Get the I2S source clock value */
1871             vcoinput = (uint32_t)(EXTERNAL_CLOCK_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
1872           }
1873           else
1874           {
1875             /* Configure the PLLI2S division factor */
1876             /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
1877             if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1878             {
1879               /* Get the I2S source clock value */
1880               vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
1881             }
1882             else
1883             {
1884               /* Get the I2S source clock value */
1885               vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
1886             }
1887           }
1888           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
1889           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
1890           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
1891           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
1892           break;
1893         }
1894         /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
1895         case RCC_I2SAPB2CLKSOURCE_PLLR:
1896         {
1897           /* Configure the PLL division factor R */
1898           /* PLL_VCO Input  = PLL_SOURCE/PLLM */
1899           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1900           {
1901             /* Get the I2S source clock value */
1902             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
1903           }
1904           else
1905           {
1906             /* Get the I2S source clock value */
1907             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
1908           }
1909 
1910           /* PLL_VCO Output = PLL_VCO Input * PLLN */
1911           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
1912           /* I2S_CLK = PLL_VCO Output/PLLR */
1913           frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
1914           break;
1915         }
1916         /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
1917         case RCC_I2SAPB2CLKSOURCE_PLLSRC:
1918         {
1919           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
1920           {
1921             frequency = HSE_VALUE;
1922           }
1923           else
1924           {
1925             frequency = HSI_VALUE;
1926           }
1927           break;
1928         }
1929         /* Clock not enabled for I2S*/
1930         default:
1931         {
1932           frequency = 0U;
1933           break;
1934         }
1935       }
1936       break;
1937     }
1938     default:
1939     {
1940       break;
1941     }
1942   }
1943   return frequency;
1944 }
1945 #endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */
1946 
1947 #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx)
1948 /**
1949   * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
1950   *         RCC_PeriphCLKInitTypeDef.
1951   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
1952   *         contains the configuration information for the Extended Peripherals clocks(I2S and RTC clocks).
1953   *
1954   * @note   A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case
1955   *         the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup
1956   *        domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset
1957   *
1958   * @retval HAL status
1959   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)1960 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
1961 {
1962   uint32_t tickstart = 0U;
1963   uint32_t tmpreg1 = 0U;
1964 
1965   /* Check the parameters */
1966   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
1967 
1968   /*---------------------------- RTC configuration ---------------------------*/
1969   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
1970   {
1971     /* Check for RTC Parameters used to output RTCCLK */
1972     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
1973 
1974     /* Enable Power Clock*/
1975     __HAL_RCC_PWR_CLK_ENABLE();
1976 
1977     /* Enable write access to Backup domain */
1978     PWR->CR |= PWR_CR_DBP;
1979 
1980     /* Get tick */
1981     tickstart = HAL_GetTick();
1982 
1983     while ((PWR->CR & PWR_CR_DBP) == RESET)
1984     {
1985       if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
1986       {
1987         return HAL_TIMEOUT;
1988       }
1989     }
1990     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
1991     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
1992     if ((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
1993     {
1994       /* Store the content of BDCR register before the reset of Backup Domain */
1995       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
1996       /* RTC Clock selection can be changed only if the Backup Domain is reset */
1997       __HAL_RCC_BACKUPRESET_FORCE();
1998       __HAL_RCC_BACKUPRESET_RELEASE();
1999       /* Restore the Content of BDCR register */
2000       RCC->BDCR = tmpreg1;
2001 
2002       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
2003       if (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
2004       {
2005         /* Get tick */
2006         tickstart = HAL_GetTick();
2007 
2008         /* Wait till LSE is ready */
2009         while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
2010         {
2011           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
2012           {
2013             return HAL_TIMEOUT;
2014           }
2015         }
2016       }
2017     }
2018     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
2019   }
2020   /*--------------------------------------------------------------------------*/
2021 
2022   /*---------------------------- TIM configuration ---------------------------*/
2023   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
2024   {
2025     __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
2026   }
2027   /*--------------------------------------------------------------------------*/
2028 
2029   /*---------------------------- FMPI2C1 Configuration -----------------------*/
2030   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMPI2C1) == RCC_PERIPHCLK_FMPI2C1)
2031   {
2032     /* Check the parameters */
2033     assert_param(IS_RCC_FMPI2C1CLKSOURCE(PeriphClkInit->Fmpi2c1ClockSelection));
2034 
2035     /* Configure the FMPI2C1 clock source */
2036     __HAL_RCC_FMPI2C1_CONFIG(PeriphClkInit->Fmpi2c1ClockSelection);
2037   }
2038   /*--------------------------------------------------------------------------*/
2039 
2040   /*---------------------------- LPTIM1 Configuration ------------------------*/
2041   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1)
2042   {
2043     /* Check the parameters */
2044     assert_param(IS_RCC_LPTIM1CLKSOURCE(PeriphClkInit->Lptim1ClockSelection));
2045 
2046     /* Configure the LPTIM1 clock source */
2047     __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
2048   }
2049 
2050   /*---------------------------- I2S Configuration ---------------------------*/
2051   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S)
2052   {
2053     /* Check the parameters */
2054     assert_param(IS_RCC_I2SAPBCLKSOURCE(PeriphClkInit->I2SClockSelection));
2055 
2056     /* Configure the I2S clock source */
2057     __HAL_RCC_I2S_CONFIG(PeriphClkInit->I2SClockSelection);
2058   }
2059 
2060   return HAL_OK;
2061 }
2062 
2063 /**
2064   * @brief  Configures the RCC_OscInitStruct according to the internal
2065   * RCC configuration registers.
2066   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
2067   * will be configured.
2068   * @retval None
2069   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)2070 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
2071 {
2072   uint32_t tempreg;
2073 
2074   /* Set all possible values for the extended clock type parameter------------*/
2075   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_FMPI2C1 | RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC;
2076 
2077   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
2078   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
2079 
2080   if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
2081   {
2082     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
2083   }
2084   else
2085   {
2086     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
2087   }
2088   /* Get the FMPI2C1 clock configuration -------------------------------------*/
2089   PeriphClkInit->Fmpi2c1ClockSelection = __HAL_RCC_GET_FMPI2C1_SOURCE();
2090 
2091   /* Get the I2S clock configuration -----------------------------------------*/
2092   PeriphClkInit->I2SClockSelection = __HAL_RCC_GET_I2S_SOURCE();
2093 
2094 
2095 }
2096 /**
2097   * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
2098   * @note   Return 0 if peripheral clock identifier not managed by this API
2099   * @param  PeriphClk Peripheral clock identifier
2100   *         This parameter can be one of the following values:
2101   *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
2102   * @retval Frequency in KHz
2103   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)2104 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
2105 {
2106   /* This variable used to store the I2S clock frequency (value in Hz) */
2107   uint32_t frequency = 0U;
2108   /* This variable used to store the VCO Input (value in Hz) */
2109   uint32_t vcoinput = 0U;
2110   uint32_t srcclk = 0U;
2111   /* This variable used to store the VCO Output (value in Hz) */
2112   uint32_t vcooutput = 0U;
2113   switch (PeriphClk)
2114   {
2115     case RCC_PERIPHCLK_I2S:
2116     {
2117       /* Get the current I2S source */
2118       srcclk = __HAL_RCC_GET_I2S_SOURCE();
2119       switch (srcclk)
2120       {
2121         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
2122         case RCC_I2SAPBCLKSOURCE_EXT:
2123         {
2124           /* Set the I2S clock to the external clock  value */
2125           frequency = EXTERNAL_CLOCK_VALUE;
2126           break;
2127         }
2128         /* Check if I2S clock selection is PLL VCO Output divided by PLLR used as I2S clock */
2129         case RCC_I2SAPBCLKSOURCE_PLLR:
2130         {
2131           /* Configure the PLL division factor R */
2132           /* PLL_VCO Input  = PLL_SOURCE/PLLM */
2133           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
2134           {
2135             /* Get the I2S source clock value */
2136             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
2137           }
2138           else
2139           {
2140             /* Get the I2S source clock value */
2141             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
2142           }
2143 
2144           /* PLL_VCO Output = PLL_VCO Input * PLLN */
2145           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U) & (RCC_PLLCFGR_PLLN >> 6U)));
2146           /* I2S_CLK = PLL_VCO Output/PLLR */
2147           frequency = (uint32_t)(vcooutput / (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U) & (RCC_PLLCFGR_PLLR >> 28U)));
2148           break;
2149         }
2150         /* Check if I2S clock selection is HSI or HSE depending from PLL source Clock */
2151         case RCC_I2SAPBCLKSOURCE_PLLSRC:
2152         {
2153           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
2154           {
2155             frequency = HSE_VALUE;
2156           }
2157           else
2158           {
2159             frequency = HSI_VALUE;
2160           }
2161           break;
2162         }
2163         /* Clock not enabled for I2S*/
2164         default:
2165         {
2166           frequency = 0U;
2167           break;
2168         }
2169       }
2170       break;
2171     }
2172     default:
2173     {
2174       break;
2175     }
2176   }
2177   return frequency;
2178 }
2179 #endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */
2180 
2181 #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
2182 /**
2183   * @brief  Initializes the RCC extended peripherals clocks according to the specified
2184   *         parameters in the RCC_PeriphCLKInitTypeDef.
2185   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
2186   *         contains the configuration information for the Extended Peripherals
2187   *         clocks(I2S, SAI, LTDC RTC and TIM).
2188   *
2189   * @note   Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
2190   *         the RTC clock source; in this case the Backup domain will be reset in
2191   *         order to modify the RTC Clock source, as consequence RTC registers (including
2192   *         the backup registers) and RCC_BDCR register are set to their reset values.
2193   *
2194   * @retval HAL status
2195   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)2196 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
2197 {
2198   uint32_t tickstart = 0U;
2199   uint32_t tmpreg1 = 0U;
2200 
2201   /* Check the parameters */
2202   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
2203 
2204   /*----------------------- SAI/I2S Configuration (PLLI2S) -------------------*/
2205   /*----------------------- Common configuration SAI/I2S ---------------------*/
2206   /* In Case of SAI or I2S Clock Configuration through PLLI2S, PLLI2SN division
2207      factor is common parameters for both peripherals */
2208   if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) ||
2209       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == RCC_PERIPHCLK_SAI_PLLI2S) ||
2210       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S))
2211   {
2212     /* check for Parameters */
2213     assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
2214 
2215     /* Disable the PLLI2S */
2216     __HAL_RCC_PLLI2S_DISABLE();
2217     /* Get tick */
2218     tickstart = HAL_GetTick();
2219     /* Wait till PLLI2S is disabled */
2220     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
2221     {
2222       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2223       {
2224         /* return in case of Timeout detected */
2225         return HAL_TIMEOUT;
2226       }
2227     }
2228 
2229     /*---------------------------- I2S configuration -------------------------*/
2230     /* In Case of I2S Clock Configuration through PLLI2S, PLLI2SR must be added
2231       only for I2S configuration */
2232     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))
2233     {
2234       /* check for Parameters */
2235       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
2236       /* Configure the PLLI2S division factors */
2237       /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */
2238       /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
2239       __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
2240     }
2241 
2242     /*---------------------------- SAI configuration -------------------------*/
2243     /* In Case of SAI Clock Configuration through PLLI2S, PLLI2SQ and PLLI2S_DIVQ must
2244        be added only for SAI configuration */
2245     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLI2S) == (RCC_PERIPHCLK_SAI_PLLI2S))
2246     {
2247       /* Check the PLLI2S division factors */
2248       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
2249       assert_param(IS_RCC_PLLI2S_DIVQ_VALUE(PeriphClkInit->PLLI2SDivQ));
2250 
2251       /* Read PLLI2SR value from PLLI2SCFGR register (this value is not need for SAI configuration) */
2252       tmpreg1 = ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
2253       /* Configure the PLLI2S division factors */
2254       /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
2255       /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
2256       /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */
2257       __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ, tmpreg1);
2258       /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */
2259       __HAL_RCC_PLLI2S_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLI2SDivQ);
2260     }
2261 
2262     /*----------------- In Case of PLLI2S is just selected  -----------------*/
2263     if ((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S)
2264     {
2265       /* Check for Parameters */
2266       assert_param(IS_RCC_PLLI2SQ_VALUE(PeriphClkInit->PLLI2S.PLLI2SQ));
2267       assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
2268 
2269       /* Configure the PLLI2S multiplication and division factors */
2270       __HAL_RCC_PLLI2S_SAICLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SQ,
2271                                      PeriphClkInit->PLLI2S.PLLI2SR);
2272     }
2273 
2274     /* Enable the PLLI2S */
2275     __HAL_RCC_PLLI2S_ENABLE();
2276     /* Get tick */
2277     tickstart = HAL_GetTick();
2278     /* Wait till PLLI2S is ready */
2279     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
2280     {
2281       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2282       {
2283         /* return in case of Timeout detected */
2284         return HAL_TIMEOUT;
2285       }
2286     }
2287   }
2288   /*--------------------------------------------------------------------------*/
2289 
2290   /*----------------------- SAI/LTDC Configuration (PLLSAI) ------------------*/
2291   /*----------------------- Common configuration SAI/LTDC --------------------*/
2292   /* In Case of SAI or LTDC Clock Configuration through PLLSAI, PLLSAIN division
2293      factor is common parameters for both peripherals */
2294   if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == RCC_PERIPHCLK_SAI_PLLSAI) ||
2295       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC))
2296   {
2297     /* Check the PLLSAI division factors */
2298     assert_param(IS_RCC_PLLSAIN_VALUE(PeriphClkInit->PLLSAI.PLLSAIN));
2299 
2300     /* Disable PLLSAI Clock */
2301     __HAL_RCC_PLLSAI_DISABLE();
2302     /* Get tick */
2303     tickstart = HAL_GetTick();
2304     /* Wait till PLLSAI is disabled */
2305     while (__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
2306     {
2307       if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
2308       {
2309         /* return in case of Timeout detected */
2310         return HAL_TIMEOUT;
2311       }
2312     }
2313 
2314     /*---------------------------- SAI configuration -------------------------*/
2315     /* In Case of SAI Clock Configuration through PLLSAI, PLLSAIQ and PLLSAI_DIVQ must
2316        be added only for SAI configuration */
2317     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI_PLLSAI) == (RCC_PERIPHCLK_SAI_PLLSAI))
2318     {
2319       assert_param(IS_RCC_PLLSAIQ_VALUE(PeriphClkInit->PLLSAI.PLLSAIQ));
2320       assert_param(IS_RCC_PLLSAI_DIVQ_VALUE(PeriphClkInit->PLLSAIDivQ));
2321 
2322       /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
2323       tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
2324       /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
2325       /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
2326       /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */
2327       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, PeriphClkInit->PLLSAI.PLLSAIQ, tmpreg1);
2328       /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */
2329       __HAL_RCC_PLLSAI_PLLSAICLKDIVQ_CONFIG(PeriphClkInit->PLLSAIDivQ);
2330     }
2331 
2332     /*---------------------------- LTDC configuration ------------------------*/
2333     if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == (RCC_PERIPHCLK_LTDC))
2334     {
2335       assert_param(IS_RCC_PLLSAIR_VALUE(PeriphClkInit->PLLSAI.PLLSAIR));
2336       assert_param(IS_RCC_PLLSAI_DIVR_VALUE(PeriphClkInit->PLLSAIDivR));
2337 
2338       /* Read PLLSAIR value from PLLSAICFGR register (this value is not need for SAI configuration) */
2339       tmpreg1 = ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
2340       /* PLLSAI_VCO Input  = PLL_SOURCE/PLLM */
2341       /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */
2342       /* LTDC_CLK(first level) = PLLSAI_VCO Output/PLLSAIR */
2343       __HAL_RCC_PLLSAI_CONFIG(PeriphClkInit->PLLSAI.PLLSAIN, tmpreg1, PeriphClkInit->PLLSAI.PLLSAIR);
2344       /* LTDC_CLK = LTDC_CLK(first level)/PLLSAIDIVR */
2345       __HAL_RCC_PLLSAI_PLLSAICLKDIVR_CONFIG(PeriphClkInit->PLLSAIDivR);
2346     }
2347     /* Enable PLLSAI Clock */
2348     __HAL_RCC_PLLSAI_ENABLE();
2349     /* Get tick */
2350     tickstart = HAL_GetTick();
2351     /* Wait till PLLSAI is ready */
2352     while (__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
2353     {
2354       if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
2355       {
2356         /* return in case of Timeout detected */
2357         return HAL_TIMEOUT;
2358       }
2359     }
2360   }
2361   /*--------------------------------------------------------------------------*/
2362 
2363   /*---------------------------- RTC configuration ---------------------------*/
2364   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
2365   {
2366     /* Check for RTC Parameters used to output RTCCLK */
2367     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
2368 
2369     /* Enable Power Clock*/
2370     __HAL_RCC_PWR_CLK_ENABLE();
2371 
2372     /* Enable write access to Backup domain */
2373     PWR->CR |= PWR_CR_DBP;
2374 
2375     /* Get tick */
2376     tickstart = HAL_GetTick();
2377 
2378     while ((PWR->CR & PWR_CR_DBP) == RESET)
2379     {
2380       if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
2381       {
2382         return HAL_TIMEOUT;
2383       }
2384     }
2385     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
2386     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
2387     if ((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
2388     {
2389       /* Store the content of BDCR register before the reset of Backup Domain */
2390       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
2391       /* RTC Clock selection can be changed only if the Backup Domain is reset */
2392       __HAL_RCC_BACKUPRESET_FORCE();
2393       __HAL_RCC_BACKUPRESET_RELEASE();
2394       /* Restore the Content of BDCR register */
2395       RCC->BDCR = tmpreg1;
2396 
2397       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
2398       if (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
2399       {
2400         /* Get tick */
2401         tickstart = HAL_GetTick();
2402 
2403         /* Wait till LSE is ready */
2404         while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
2405         {
2406           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
2407           {
2408             return HAL_TIMEOUT;
2409           }
2410         }
2411       }
2412     }
2413     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
2414   }
2415   /*--------------------------------------------------------------------------*/
2416 
2417   /*---------------------------- TIM configuration ---------------------------*/
2418   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
2419   {
2420     __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
2421   }
2422   return HAL_OK;
2423 }
2424 
2425 /**
2426   * @brief  Configures the PeriphClkInit according to the internal
2427   * RCC configuration registers.
2428   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
2429   *         will be configured.
2430   * @retval None
2431   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)2432 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
2433 {
2434   uint32_t tempreg;
2435 
2436   /* Set all possible values for the extended clock type parameter------------*/
2437   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_SAI_PLLSAI | RCC_PERIPHCLK_SAI_PLLI2S | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_TIM | RCC_PERIPHCLK_RTC;
2438 
2439   /* Get the PLLI2S Clock configuration -----------------------------------------------*/
2440   PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
2441   PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
2442   PeriphClkInit->PLLI2S.PLLI2SQ = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> RCC_PLLI2SCFGR_PLLI2SQ_Pos);
2443   /* Get the PLLSAI Clock configuration -----------------------------------------------*/
2444   PeriphClkInit->PLLSAI.PLLSAIN = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> RCC_PLLSAICFGR_PLLSAIN_Pos);
2445   PeriphClkInit->PLLSAI.PLLSAIR = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIR) >> RCC_PLLSAICFGR_PLLSAIR_Pos);
2446   PeriphClkInit->PLLSAI.PLLSAIQ = (uint32_t)((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> RCC_PLLSAICFGR_PLLSAIQ_Pos);
2447   /* Get the PLLSAI/PLLI2S division factors -----------------------------------------------*/
2448   PeriphClkInit->PLLI2SDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) >> RCC_DCKCFGR_PLLI2SDIVQ_Pos);
2449   PeriphClkInit->PLLSAIDivQ = (uint32_t)((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> RCC_DCKCFGR_PLLSAIDIVQ_Pos);
2450   PeriphClkInit->PLLSAIDivR = (uint32_t)(RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVR);
2451   /* Get the RTC Clock configuration -----------------------------------------------*/
2452   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
2453   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
2454 
2455   if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
2456   {
2457     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
2458   }
2459   else
2460   {
2461     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
2462   }
2463 }
2464 
2465 /**
2466   * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
2467   * @note   Return 0 if peripheral clock identifier not managed by this API
2468   * @param  PeriphClk Peripheral clock identifier
2469   *         This parameter can be one of the following values:
2470   *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
2471   * @retval Frequency in KHz
2472   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)2473 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
2474 {
2475   /* This variable used to store the I2S clock frequency (value in Hz) */
2476   uint32_t frequency = 0U;
2477   /* This variable used to store the VCO Input (value in Hz) */
2478   uint32_t vcoinput = 0U;
2479   uint32_t srcclk = 0U;
2480   /* This variable used to store the VCO Output (value in Hz) */
2481   uint32_t vcooutput = 0U;
2482   switch (PeriphClk)
2483   {
2484     case RCC_PERIPHCLK_I2S:
2485     {
2486       /* Get the current I2S source */
2487       srcclk = __HAL_RCC_GET_I2S_SOURCE();
2488       switch (srcclk)
2489       {
2490         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
2491         case RCC_I2SCLKSOURCE_EXT:
2492         {
2493           /* Set the I2S clock to the external clock  value */
2494           frequency = EXTERNAL_CLOCK_VALUE;
2495           break;
2496         }
2497         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
2498         case RCC_I2SCLKSOURCE_PLLI2S:
2499         {
2500           /* Configure the PLLI2S division factor */
2501           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
2502           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
2503           {
2504             /* Get the I2S source clock value */
2505             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
2506           }
2507           else
2508           {
2509             /* Get the I2S source clock value */
2510             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
2511           }
2512 
2513           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
2514           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
2515           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
2516           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
2517           break;
2518         }
2519         /* Clock not enabled for I2S*/
2520         default:
2521         {
2522           frequency = 0U;
2523           break;
2524         }
2525       }
2526       break;
2527     }
2528     default:
2529     {
2530       break;
2531     }
2532   }
2533   return frequency;
2534 }
2535 #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
2536 
2537 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx) ||\
2538     defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE)
2539 /**
2540   * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
2541   *         RCC_PeriphCLKInitTypeDef.
2542   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
2543   *         contains the configuration information for the Extended Peripherals clocks(I2S and RTC clocks).
2544   *
2545   * @note   A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case
2546   *         the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup
2547   *        domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset
2548   *
2549   * @retval HAL status
2550   */
HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)2551 HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
2552 {
2553   uint32_t tickstart = 0U;
2554   uint32_t tmpreg1 = 0U;
2555 
2556   /* Check the parameters */
2557   assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
2558 
2559   /*---------------------------- I2S configuration ---------------------------*/
2560   if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S) == RCC_PERIPHCLK_I2S) ||
2561       (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLLI2S) == RCC_PERIPHCLK_PLLI2S))
2562   {
2563     /* check for Parameters */
2564     assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
2565     assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
2566 #if defined(STM32F411xE)
2567     assert_param(IS_RCC_PLLI2SM_VALUE(PeriphClkInit->PLLI2S.PLLI2SM));
2568 #endif /* STM32F411xE */
2569     /* Disable the PLLI2S */
2570     __HAL_RCC_PLLI2S_DISABLE();
2571     /* Get tick */
2572     tickstart = HAL_GetTick();
2573     /* Wait till PLLI2S is disabled */
2574     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
2575     {
2576       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2577       {
2578         /* return in case of Timeout detected */
2579         return HAL_TIMEOUT;
2580       }
2581     }
2582 
2583 #if defined(STM32F411xE)
2584     /* Configure the PLLI2S division factors */
2585     /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
2586     /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
2587     __HAL_RCC_PLLI2S_I2SCLK_CONFIG(PeriphClkInit->PLLI2S.PLLI2SM, PeriphClkInit->PLLI2S.PLLI2SN,
2588                                    PeriphClkInit->PLLI2S.PLLI2SR);
2589 #else
2590     /* Configure the PLLI2S division factors */
2591     /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */
2592     /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
2593     __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN, PeriphClkInit->PLLI2S.PLLI2SR);
2594 #endif /* STM32F411xE */
2595 
2596     /* Enable the PLLI2S */
2597     __HAL_RCC_PLLI2S_ENABLE();
2598     /* Get tick */
2599     tickstart = HAL_GetTick();
2600     /* Wait till PLLI2S is ready */
2601     while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
2602     {
2603       if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2604       {
2605         /* return in case of Timeout detected */
2606         return HAL_TIMEOUT;
2607       }
2608     }
2609   }
2610 
2611   /*---------------------------- RTC configuration ---------------------------*/
2612   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
2613   {
2614     /* Check for RTC Parameters used to output RTCCLK */
2615     assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
2616 
2617     /* Enable Power Clock*/
2618     __HAL_RCC_PWR_CLK_ENABLE();
2619 
2620     /* Enable write access to Backup domain */
2621     PWR->CR |= PWR_CR_DBP;
2622 
2623     /* Get tick */
2624     tickstart = HAL_GetTick();
2625 
2626     while ((PWR->CR & PWR_CR_DBP) == RESET)
2627     {
2628       if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
2629       {
2630         return HAL_TIMEOUT;
2631       }
2632     }
2633     /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
2634     tmpreg1 = (RCC->BDCR & RCC_BDCR_RTCSEL);
2635     if ((tmpreg1 != 0x00000000U) && ((tmpreg1) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
2636     {
2637       /* Store the content of BDCR register before the reset of Backup Domain */
2638       tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
2639       /* RTC Clock selection can be changed only if the Backup Domain is reset */
2640       __HAL_RCC_BACKUPRESET_FORCE();
2641       __HAL_RCC_BACKUPRESET_RELEASE();
2642       /* Restore the Content of BDCR register */
2643       RCC->BDCR = tmpreg1;
2644 
2645       /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
2646       if (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSEON))
2647       {
2648         /* Get tick */
2649         tickstart = HAL_GetTick();
2650 
2651         /* Wait till LSE is ready */
2652         while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
2653         {
2654           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
2655           {
2656             return HAL_TIMEOUT;
2657           }
2658         }
2659       }
2660     }
2661     __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
2662   }
2663 #if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE)
2664   /*---------------------------- TIM configuration ---------------------------*/
2665   if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_TIM) == (RCC_PERIPHCLK_TIM))
2666   {
2667     __HAL_RCC_TIMCLKPRESCALER(PeriphClkInit->TIMPresSelection);
2668   }
2669 #endif /* STM32F401xC || STM32F401xE || STM32F411xE */
2670   return HAL_OK;
2671 }
2672 
2673 /**
2674   * @brief  Configures the RCC_OscInitStruct according to the internal
2675   * RCC configuration registers.
2676   * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
2677   * will be configured.
2678   * @retval None
2679   */
HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef * PeriphClkInit)2680 void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
2681 {
2682   uint32_t tempreg;
2683 
2684   /* Set all possible values for the extended clock type parameter------------*/
2685   PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_I2S | RCC_PERIPHCLK_RTC;
2686 
2687   /* Get the PLLI2S Clock configuration --------------------------------------*/
2688   PeriphClkInit->PLLI2S.PLLI2SN = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> RCC_PLLI2SCFGR_PLLI2SN_Pos);
2689   PeriphClkInit->PLLI2S.PLLI2SR = (uint32_t)((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> RCC_PLLI2SCFGR_PLLI2SR_Pos);
2690 #if defined(STM32F411xE)
2691   PeriphClkInit->PLLI2S.PLLI2SM = (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM);
2692 #endif /* STM32F411xE */
2693   /* Get the RTC Clock configuration -----------------------------------------*/
2694   tempreg = (RCC->CFGR & RCC_CFGR_RTCPRE);
2695   PeriphClkInit->RTCClockSelection = (uint32_t)((tempreg) | (RCC->BDCR & RCC_BDCR_RTCSEL));
2696 
2697 #if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE)
2698   /* Get the TIM Prescaler configuration -------------------------------------*/
2699   if ((RCC->DCKCFGR & RCC_DCKCFGR_TIMPRE) == RESET)
2700   {
2701     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_DESACTIVATED;
2702   }
2703   else
2704   {
2705     PeriphClkInit->TIMPresSelection = RCC_TIMPRES_ACTIVATED;
2706   }
2707 #endif /* STM32F401xC || STM32F401xE || STM32F411xE */
2708 }
2709 
2710 /**
2711   * @brief  Return the peripheral clock frequency for a given peripheral(SAI..)
2712   * @note   Return 0 if peripheral clock identifier not managed by this API
2713   * @param  PeriphClk Peripheral clock identifier
2714   *         This parameter can be one of the following values:
2715   *            @arg RCC_PERIPHCLK_I2S: I2S peripheral clock
2716   * @retval Frequency in KHz
2717   */
HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)2718 uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
2719 {
2720   /* This variable used to store the I2S clock frequency (value in Hz) */
2721   uint32_t frequency = 0U;
2722   /* This variable used to store the VCO Input (value in Hz) */
2723   uint32_t vcoinput = 0U;
2724   uint32_t srcclk = 0U;
2725   /* This variable used to store the VCO Output (value in Hz) */
2726   uint32_t vcooutput = 0U;
2727   switch (PeriphClk)
2728   {
2729     case RCC_PERIPHCLK_I2S:
2730     {
2731       /* Get the current I2S source */
2732       srcclk = __HAL_RCC_GET_I2S_SOURCE();
2733       switch (srcclk)
2734       {
2735         /* Check if I2S clock selection is External clock mapped on the I2S_CKIN pin used as I2S clock */
2736         case RCC_I2SCLKSOURCE_EXT:
2737         {
2738           /* Set the I2S clock to the external clock  value */
2739           frequency = EXTERNAL_CLOCK_VALUE;
2740           break;
2741         }
2742         /* Check if I2S clock selection is PLLI2S VCO output clock divided by PLLI2SR used as I2S clock */
2743         case RCC_I2SCLKSOURCE_PLLI2S:
2744         {
2745 #if defined(STM32F411xE)
2746           /* Configure the PLLI2S division factor */
2747           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLI2SM */
2748           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
2749           {
2750             /* Get the I2S source clock value */
2751             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
2752           }
2753           else
2754           {
2755             /* Get the I2S source clock value */
2756             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SM));
2757           }
2758 #else
2759           /* Configure the PLLI2S division factor */
2760           /* PLLI2S_VCO Input  = PLL_SOURCE/PLLM */
2761           if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE)
2762           {
2763             /* Get the I2S source clock value */
2764             vcoinput = (uint32_t)(HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
2765           }
2766           else
2767           {
2768             /* Get the I2S source clock value */
2769             vcoinput = (uint32_t)(HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM));
2770           }
2771 #endif /* STM32F411xE */
2772           /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */
2773           vcooutput = (uint32_t)(vcoinput * (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U) & (RCC_PLLI2SCFGR_PLLI2SN >> 6U)));
2774           /* I2S_CLK = PLLI2S_VCO Output/PLLI2SR */
2775           frequency = (uint32_t)(vcooutput / (((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U) & (RCC_PLLI2SCFGR_PLLI2SR >> 28U)));
2776           break;
2777         }
2778         /* Clock not enabled for I2S*/
2779         default:
2780         {
2781           frequency = 0U;
2782           break;
2783         }
2784       }
2785       break;
2786     }
2787     default:
2788     {
2789       break;
2790     }
2791   }
2792   return frequency;
2793 }
2794 #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE  || STM32F411xE */
2795 
2796 #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\
2797     defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
2798 /**
2799   * @brief  Select LSE mode
2800   *
2801   * @note   This mode is only available for STM32F410xx/STM32F411xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx  devices.
2802   *
2803   * @param  Mode specifies the LSE mode.
2804   *          This parameter can be one of the following values:
2805   *            @arg RCC_LSE_LOWPOWER_MODE:  LSE oscillator in low power mode selection
2806   *            @arg RCC_LSE_HIGHDRIVE_MODE: LSE oscillator in High Drive mode selection
2807   * @retval None
2808   */
HAL_RCCEx_SelectLSEMode(uint8_t Mode)2809 void HAL_RCCEx_SelectLSEMode(uint8_t Mode)
2810 {
2811   /* Check the parameters */
2812   assert_param(IS_RCC_LSE_MODE(Mode));
2813   if (Mode == RCC_LSE_HIGHDRIVE_MODE)
2814   {
2815     SET_BIT(RCC->BDCR, RCC_BDCR_LSEMOD);
2816   }
2817   else
2818   {
2819     CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEMOD);
2820   }
2821 }
2822 
2823 #endif /* STM32F410xx || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */
2824 
2825 /** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
2826   *  @brief  Extended Clock management functions
2827   *
2828 @verbatim
2829  ===============================================================================
2830                 ##### Extended clock management functions  #####
2831  ===============================================================================
2832     [..]
2833     This subsection provides a set of functions allowing to control the
2834     activation or deactivation of PLLI2S, PLLSAI.
2835 @endverbatim
2836   * @{
2837   */
2838 
2839 #if defined(RCC_PLLI2S_SUPPORT)
2840 /**
2841   * @brief  Enable PLLI2S.
2842   * @param  PLLI2SInit  pointer to an RCC_PLLI2SInitTypeDef structure that
2843   *         contains the configuration information for the PLLI2S
2844   * @retval HAL status
2845   */
HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef * PLLI2SInit)2846 HAL_StatusTypeDef HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef  *PLLI2SInit)
2847 {
2848   uint32_t tickstart;
2849 
2850   /* Check for parameters */
2851   assert_param(IS_RCC_PLLI2SN_VALUE(PLLI2SInit->PLLI2SN));
2852   assert_param(IS_RCC_PLLI2SR_VALUE(PLLI2SInit->PLLI2SR));
2853 #if defined(RCC_PLLI2SCFGR_PLLI2SM)
2854   assert_param(IS_RCC_PLLI2SM_VALUE(PLLI2SInit->PLLI2SM));
2855 #endif /* RCC_PLLI2SCFGR_PLLI2SM */
2856 #if defined(RCC_PLLI2SCFGR_PLLI2SP)
2857   assert_param(IS_RCC_PLLI2SP_VALUE(PLLI2SInit->PLLI2SP));
2858 #endif /* RCC_PLLI2SCFGR_PLLI2SP */
2859 #if defined(RCC_PLLI2SCFGR_PLLI2SQ)
2860   assert_param(IS_RCC_PLLI2SQ_VALUE(PLLI2SInit->PLLI2SQ));
2861 #endif /* RCC_PLLI2SCFGR_PLLI2SQ */
2862 
2863   /* Disable the PLLI2S */
2864   __HAL_RCC_PLLI2S_DISABLE();
2865 
2866   /* Wait till PLLI2S is disabled */
2867   tickstart = HAL_GetTick();
2868   while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET)
2869   {
2870     if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2871     {
2872       /* return in case of Timeout detected */
2873       return HAL_TIMEOUT;
2874     }
2875   }
2876 
2877   /* Configure the PLLI2S division factors */
2878 #if defined(STM32F446xx)
2879   /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
2880   /* I2SPCLK = PLLI2S_VCO / PLLI2SP */
2881   /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */
2882   /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
2883   __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, \
2884                           PLLI2SInit->PLLI2SP, PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR);
2885 #elif defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) ||\
2886       defined(STM32F413xx) || defined(STM32F423xx)
2887   /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM)*/
2888   /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */
2889   /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
2890   __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, \
2891                           PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR);
2892 #elif defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
2893       defined(STM32F469xx) || defined(STM32F479xx)
2894   /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * PLLI2SN */
2895   /* I2SQCLK = PLLI2S_VCO / PLLI2SQ */
2896   /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
2897   __HAL_RCC_PLLI2S_SAICLK_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SQ, PLLI2SInit->PLLI2SR);
2898 #elif defined(STM32F411xE)
2899   /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLI2SM) */
2900   /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
2901   __HAL_RCC_PLLI2S_I2SCLK_CONFIG(PLLI2SInit->PLLI2SM, PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR);
2902 #else
2903   /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) x PLLI2SN */
2904   /* I2SRCLK = PLLI2S_VCO / PLLI2SR */
2905   __HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SN, PLLI2SInit->PLLI2SR);
2906 #endif /* STM32F446xx */
2907 
2908   /* Enable the PLLI2S */
2909   __HAL_RCC_PLLI2S_ENABLE();
2910 
2911   /* Wait till PLLI2S is ready */
2912   tickstart = HAL_GetTick();
2913   while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET)
2914   {
2915     if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2916     {
2917       /* return in case of Timeout detected */
2918       return HAL_TIMEOUT;
2919     }
2920   }
2921 
2922   return HAL_OK;
2923 }
2924 
2925 /**
2926   * @brief  Disable PLLI2S.
2927   * @retval HAL status
2928   */
HAL_RCCEx_DisablePLLI2S(void)2929 HAL_StatusTypeDef HAL_RCCEx_DisablePLLI2S(void)
2930 {
2931   uint32_t tickstart;
2932 
2933   /* Disable the PLLI2S */
2934   __HAL_RCC_PLLI2S_DISABLE();
2935 
2936   /* Wait till PLLI2S is disabled */
2937   tickstart = HAL_GetTick();
2938   while (READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET)
2939   {
2940     if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
2941     {
2942       /* return in case of Timeout detected */
2943       return HAL_TIMEOUT;
2944     }
2945   }
2946 
2947   return HAL_OK;
2948 }
2949 
2950 #endif /* RCC_PLLI2S_SUPPORT */
2951 
2952 #if defined(RCC_PLLSAI_SUPPORT)
2953 /**
2954   * @brief  Enable PLLSAI.
2955   * @param  PLLSAIInit  pointer to an RCC_PLLSAIInitTypeDef structure that
2956   *         contains the configuration information for the PLLSAI
2957   * @retval HAL status
2958   */
HAL_RCCEx_EnablePLLSAI(RCC_PLLSAIInitTypeDef * PLLSAIInit)2959 HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI(RCC_PLLSAIInitTypeDef  *PLLSAIInit)
2960 {
2961   uint32_t tickstart;
2962 
2963   /* Check for parameters */
2964   assert_param(IS_RCC_PLLSAIN_VALUE(PLLSAIInit->PLLSAIN));
2965   assert_param(IS_RCC_PLLSAIQ_VALUE(PLLSAIInit->PLLSAIQ));
2966 #if defined(RCC_PLLSAICFGR_PLLSAIM)
2967   assert_param(IS_RCC_PLLSAIM_VALUE(PLLSAIInit->PLLSAIM));
2968 #endif /* RCC_PLLSAICFGR_PLLSAIM */
2969 #if defined(RCC_PLLSAICFGR_PLLSAIP)
2970   assert_param(IS_RCC_PLLSAIP_VALUE(PLLSAIInit->PLLSAIP));
2971 #endif /* RCC_PLLSAICFGR_PLLSAIP */
2972 #if defined(RCC_PLLSAICFGR_PLLSAIR)
2973   assert_param(IS_RCC_PLLSAIR_VALUE(PLLSAIInit->PLLSAIR));
2974 #endif /* RCC_PLLSAICFGR_PLLSAIR */
2975 
2976   /* Disable the PLLSAI */
2977   __HAL_RCC_PLLSAI_DISABLE();
2978 
2979   /* Wait till PLLSAI is disabled */
2980   tickstart = HAL_GetTick();
2981   while (__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
2982   {
2983     if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
2984     {
2985       /* return in case of Timeout detected */
2986       return HAL_TIMEOUT;
2987     }
2988   }
2989 
2990   /* Configure the PLLSAI division factors */
2991 #if defined(STM32F446xx)
2992   /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * (PLLSAIN/PLLSAIM) */
2993   /* SAIPCLK = PLLSAI_VCO / PLLSAIP */
2994   /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */
2995   /* SAIRCLK = PLLSAI_VCO / PLLSAIR */
2996   __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIM, PLLSAIInit->PLLSAIN, \
2997                           PLLSAIInit->PLLSAIP, PLLSAIInit->PLLSAIQ, 0U);
2998 #elif defined(STM32F469xx) || defined(STM32F479xx)
2999   /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) * PLLSAIN */
3000   /* SAIPCLK = PLLSAI_VCO / PLLSAIP */
3001   /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */
3002   /* SAIRCLK = PLLSAI_VCO / PLLSAIR */
3003   __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIN, PLLSAIInit->PLLSAIP, \
3004                           PLLSAIInit->PLLSAIQ, PLLSAIInit->PLLSAIR);
3005 #else
3006   /* PLLSAI_VCO = f(VCO clock) = f(PLLSAI clock input) x PLLSAIN */
3007   /* SAIQCLK = PLLSAI_VCO / PLLSAIQ */
3008   /* SAIRCLK = PLLSAI_VCO / PLLSAIR */
3009   __HAL_RCC_PLLSAI_CONFIG(PLLSAIInit->PLLSAIN, PLLSAIInit->PLLSAIQ, PLLSAIInit->PLLSAIR);
3010 #endif /* STM32F446xx */
3011 
3012   /* Enable the PLLSAI */
3013   __HAL_RCC_PLLSAI_ENABLE();
3014 
3015   /* Wait till PLLSAI is ready */
3016   tickstart = HAL_GetTick();
3017   while (__HAL_RCC_PLLSAI_GET_FLAG() == RESET)
3018   {
3019     if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
3020     {
3021       /* return in case of Timeout detected */
3022       return HAL_TIMEOUT;
3023     }
3024   }
3025 
3026   return HAL_OK;
3027 }
3028 
3029 /**
3030   * @brief  Disable PLLSAI.
3031   * @retval HAL status
3032   */
HAL_RCCEx_DisablePLLSAI(void)3033 HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI(void)
3034 {
3035   uint32_t tickstart;
3036 
3037   /* Disable the PLLSAI */
3038   __HAL_RCC_PLLSAI_DISABLE();
3039 
3040   /* Wait till PLLSAI is disabled */
3041   tickstart = HAL_GetTick();
3042   while (__HAL_RCC_PLLSAI_GET_FLAG() != RESET)
3043   {
3044     if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
3045     {
3046       /* return in case of Timeout detected */
3047       return HAL_TIMEOUT;
3048     }
3049   }
3050 
3051   return HAL_OK;
3052 }
3053 
3054 #endif /* RCC_PLLSAI_SUPPORT */
3055 
3056 /**
3057   * @}
3058   */
3059 
3060 #if defined(STM32F446xx)
3061 /**
3062   * @brief  Returns the SYSCLK frequency
3063   *
3064   * @note   This function implementation is valid only for STM32F446xx devices.
3065   * @note   This function add the PLL/PLLR System clock source
3066   *
3067   * @note   The system frequency computed by this function is not the real
3068   *         frequency in the chip. It is calculated based on the predefined
3069   *         constant and the selected clock source:
3070   * @note     If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
3071   * @note     If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
3072   * @note     If SYSCLK source is PLL or PLLR, function returns values based on HSE_VALUE(**)
3073   *           or HSI_VALUE(*) multiplied/divided by the PLL factors.
3074   * @note     (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
3075   *               16 MHz) but the real value may vary depending on the variations
3076   *               in voltage and temperature.
3077   * @note     (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
3078   *                25 MHz), user has to ensure that HSE_VALUE is same as the real
3079   *                frequency of the crystal used. Otherwise, this function may
3080   *                have wrong result.
3081   *
3082   * @note   The result of this function could be not correct when using fractional
3083   *         value for HSE crystal.
3084   *
3085   * @note   This function can be used by the user application to compute the
3086   *         baudrate for the communication peripherals or configure other parameters.
3087   *
3088   * @note   Each time SYSCLK changes, this function must be called to update the
3089   *         right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
3090   *
3091   *
3092   * @retval SYSCLK frequency
3093   */
HAL_RCC_GetSysClockFreq(void)3094 uint32_t HAL_RCC_GetSysClockFreq(void)
3095 {
3096   uint32_t pllm = 0U;
3097   uint32_t pllvco = 0U;
3098   uint32_t pllp = 0U;
3099   uint32_t pllr = 0U;
3100   uint32_t sysclockfreq = 0U;
3101 
3102   /* Get SYSCLK source -------------------------------------------------------*/
3103   switch (RCC->CFGR & RCC_CFGR_SWS)
3104   {
3105     case RCC_CFGR_SWS_HSI:  /* HSI used as system clock source */
3106     {
3107       sysclockfreq = HSI_VALUE;
3108       break;
3109     }
3110     case RCC_CFGR_SWS_HSE:  /* HSE used as system clock  source */
3111     {
3112       sysclockfreq = HSE_VALUE;
3113       break;
3114     }
3115     case RCC_CFGR_SWS_PLL:  /* PLL/PLLP used as system clock  source */
3116     {
3117       /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
3118       SYSCLK = PLL_VCO / PLLP */
3119       pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
3120       if (__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_HSI)
3121       {
3122         /* HSE used as PLL clock source */
3123         pllvco = (uint32_t)((((uint64_t) HSE_VALUE * ((uint64_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
3124       }
3125       else
3126       {
3127         /* HSI used as PLL clock source */
3128         pllvco = (uint32_t)((((uint64_t) HSI_VALUE * ((uint64_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
3129       }
3130       pllp = ((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> RCC_PLLCFGR_PLLP_Pos) + 1U) * 2U);
3131 
3132       sysclockfreq = pllvco / pllp;
3133       break;
3134     }
3135     case RCC_CFGR_SWS_PLLR:  /* PLL/PLLR used as system clock  source */
3136     {
3137       /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
3138       SYSCLK = PLL_VCO / PLLR */
3139       pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
3140       if (__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_HSI)
3141       {
3142         /* HSE used as PLL clock source */
3143         pllvco = (uint32_t)((((uint64_t) HSE_VALUE * ((uint64_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
3144       }
3145       else
3146       {
3147         /* HSI used as PLL clock source */
3148         pllvco = (uint32_t)((((uint64_t) HSI_VALUE * ((uint64_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)))) / (uint64_t)pllm);
3149       }
3150       pllr = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos);
3151 
3152       sysclockfreq = pllvco / pllr;
3153       break;
3154     }
3155     default:
3156     {
3157       sysclockfreq = HSI_VALUE;
3158       break;
3159     }
3160   }
3161   return sysclockfreq;
3162 }
3163 #endif /* STM32F446xx */
3164 
3165 /**
3166   * @}
3167   */
3168 
3169 /**
3170   * @}
3171   */
3172 
3173 /**
3174   * @brief  Resets the RCC clock configuration to the default reset state.
3175   * @note   The default reset state of the clock configuration is given below:
3176   *            - HSI ON and used as system clock source
3177   *            - HSE, PLL, PLLI2S and PLLSAI OFF
3178   *            - AHB, APB1 and APB2 prescaler set to 1.
3179   *            - CSS, MCO1 and MCO2 OFF
3180   *            - All interrupts disabled
3181   * @note   This function doesn't modify the configuration of the
3182   *            - Peripheral clocks
3183   *            - LSI, LSE and RTC clocks
3184   * @retval HAL status
3185   */
HAL_RCC_DeInit(void)3186 HAL_StatusTypeDef HAL_RCC_DeInit(void)
3187 {
3188   uint32_t tickstart;
3189 
3190   /* Get Start Tick */
3191   tickstart = HAL_GetTick();
3192 
3193   /* Set HSION bit to the reset value */
3194   SET_BIT(RCC->CR, RCC_CR_HSION);
3195 
3196   /* Wait till HSI is ready */
3197   while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
3198   {
3199     if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
3200     {
3201       return HAL_TIMEOUT;
3202     }
3203   }
3204 
3205   /* Set HSITRIM[4:0] bits to the reset value */
3206   SET_BIT(RCC->CR, RCC_CR_HSITRIM_4);
3207 
3208   /* Get Start Tick */
3209   tickstart = HAL_GetTick();
3210 
3211   /* Reset CFGR register */
3212   CLEAR_REG(RCC->CFGR);
3213 
3214   /* Wait till clock switch is ready */
3215   while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RESET)
3216   {
3217     if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
3218     {
3219       return HAL_TIMEOUT;
3220     }
3221   }
3222 
3223   /* Get Start Tick */
3224   tickstart = HAL_GetTick();
3225 
3226   /* Clear HSEON, HSEBYP and CSSON bits */
3227   CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON);
3228 
3229   /* Wait till HSE is disabled */
3230   while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET)
3231   {
3232     if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
3233     {
3234       return HAL_TIMEOUT;
3235     }
3236   }
3237 
3238   /* Get Start Tick */
3239   tickstart = HAL_GetTick();
3240 
3241   /* Clear PLLON bit */
3242   CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
3243 
3244   /* Wait till PLL is disabled */
3245   while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET)
3246   {
3247     if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
3248     {
3249       return HAL_TIMEOUT;
3250     }
3251   }
3252 
3253 #if defined(RCC_PLLI2S_SUPPORT)
3254   /* Get Start Tick */
3255   tickstart = HAL_GetTick();
3256 
3257   /* Reset PLLI2SON bit */
3258   CLEAR_BIT(RCC->CR, RCC_CR_PLLI2SON);
3259 
3260   /* Wait till PLLI2S is disabled */
3261   while (READ_BIT(RCC->CR, RCC_CR_PLLI2SRDY) != RESET)
3262   {
3263     if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
3264     {
3265       return HAL_TIMEOUT;
3266     }
3267   }
3268 #endif /* RCC_PLLI2S_SUPPORT */
3269 
3270 #if defined(RCC_PLLSAI_SUPPORT)
3271   /* Get Start Tick */
3272   tickstart = HAL_GetTick();
3273 
3274   /* Reset PLLSAI bit */
3275   CLEAR_BIT(RCC->CR, RCC_CR_PLLSAION);
3276 
3277   /* Wait till PLLSAI is disabled */
3278   while (READ_BIT(RCC->CR, RCC_CR_PLLSAIRDY) != RESET)
3279   {
3280     if ((HAL_GetTick() - tickstart) > PLLSAI_TIMEOUT_VALUE)
3281     {
3282       return HAL_TIMEOUT;
3283     }
3284   }
3285 #endif /* RCC_PLLSAI_SUPPORT */
3286 
3287   /* Once PLL, PLLI2S and PLLSAI are OFF, reset PLLCFGR register to default value */
3288 #if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \
3289     defined(STM32F423xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
3290   RCC->PLLCFGR = RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLR_1;
3291 #elif defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx)
3292   RCC->PLLCFGR = RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLR_1 | RCC_PLLCFGR_PLLR_2 | RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_0 | RCC_PLLCFGR_PLLQ_1 | RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLQ_3;
3293 #else
3294   RCC->PLLCFGR = RCC_PLLCFGR_PLLM_4 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLQ_2;
3295 #endif /* STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F446xx || STM32F469xx || STM32F479xx */
3296 
3297   /* Reset PLLI2SCFGR register to default value */
3298 #if defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || \
3299     defined(STM32F423xx) || defined(STM32F446xx)
3300   RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | RCC_PLLI2SCFGR_PLLI2SR_1;
3301 #elif defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)
3302   RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1;
3303 #elif defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx)
3304   RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SQ_2 | RCC_PLLI2SCFGR_PLLI2SR_1;
3305 #elif defined(STM32F411xE)
3306   RCC->PLLI2SCFGR = RCC_PLLI2SCFGR_PLLI2SM_4 | RCC_PLLI2SCFGR_PLLI2SN_6 | RCC_PLLI2SCFGR_PLLI2SN_7 | RCC_PLLI2SCFGR_PLLI2SR_1;
3307 #endif /* STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F446xx */
3308 
3309   /* Reset PLLSAICFGR register */
3310 #if defined(STM32F427xx) || defined(STM32F429xx) || defined(STM32F437xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx)
3311   RCC->PLLSAICFGR = RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2 | RCC_PLLSAICFGR_PLLSAIR_1;
3312 #elif defined(STM32F446xx)
3313   RCC->PLLSAICFGR = RCC_PLLSAICFGR_PLLSAIM_4 | RCC_PLLSAICFGR_PLLSAIN_6 | RCC_PLLSAICFGR_PLLSAIN_7 | RCC_PLLSAICFGR_PLLSAIQ_2;
3314 #endif /* STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F469xx || STM32F479xx */
3315 
3316   /* Disable all interrupts */
3317   CLEAR_BIT(RCC->CIR, RCC_CIR_LSIRDYIE | RCC_CIR_LSERDYIE | RCC_CIR_HSIRDYIE | RCC_CIR_HSERDYIE | RCC_CIR_PLLRDYIE);
3318 
3319 #if defined(RCC_CIR_PLLI2SRDYIE)
3320   CLEAR_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYIE);
3321 #endif /* RCC_CIR_PLLI2SRDYIE */
3322 
3323 #if defined(RCC_CIR_PLLSAIRDYIE)
3324   CLEAR_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYIE);
3325 #endif /* RCC_CIR_PLLSAIRDYIE */
3326 
3327   /* Clear all interrupt flags */
3328   SET_BIT(RCC->CIR, RCC_CIR_LSIRDYC | RCC_CIR_LSERDYC | RCC_CIR_HSIRDYC | RCC_CIR_HSERDYC | RCC_CIR_PLLRDYC |
3329           RCC_CIR_CSSC);
3330 
3331 #if defined(RCC_CIR_PLLI2SRDYC)
3332   SET_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYC);
3333 #endif /* RCC_CIR_PLLI2SRDYC */
3334 
3335 #if defined(RCC_CIR_PLLSAIRDYC)
3336   SET_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYC);
3337 #endif /* RCC_CIR_PLLSAIRDYC */
3338 
3339   /* Clear LSION bit */
3340   CLEAR_BIT(RCC->CSR, RCC_CSR_LSION);
3341 
3342   /* Reset all CSR flags */
3343   SET_BIT(RCC->CSR, RCC_CSR_RMVF);
3344 
3345   /* Update the SystemCoreClock global variable */
3346   SystemCoreClock = HSI_VALUE;
3347 
3348   /* Adapt Systick interrupt period */
3349   if (HAL_InitTick(uwTickPrio) != HAL_OK)
3350   {
3351     return HAL_ERROR;
3352   }
3353   else
3354   {
3355     return HAL_OK;
3356   }
3357 }
3358 
3359 #if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\
3360     defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
3361 /**
3362   * @brief  Initializes the RCC Oscillators according to the specified parameters in the
3363   *         RCC_OscInitTypeDef.
3364   * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
3365   *         contains the configuration information for the RCC Oscillators.
3366   * @note   The PLL is not disabled when used as system clock.
3367   * @note   Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
3368   *         supported by this API. User should request a transition to LSE Off
3369   *         first and then LSE On or LSE Bypass.
3370   * @note   Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
3371   *         supported by this API. User should request a transition to HSE Off
3372   *         first and then HSE On or HSE Bypass.
3373   * @note   This function add the PLL/PLLR factor management during PLL configuration this feature
3374   *         is only available in STM32F410xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices
3375   * @retval HAL status
3376   */
HAL_RCC_OscConfig(RCC_OscInitTypeDef * RCC_OscInitStruct)3377 HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
3378 {
3379   uint32_t tickstart;
3380   uint32_t pll_config;
3381 
3382   /* Check Null pointer */
3383   if (RCC_OscInitStruct == NULL)
3384   {
3385     return HAL_ERROR;
3386   }
3387 
3388   /* Check the parameters */
3389   assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
3390   /*------------------------------- HSE Configuration ------------------------*/
3391   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
3392   {
3393     /* Check the parameters */
3394     assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
3395     /* When the HSE is used as system clock or clock source for PLL in these cases HSE will not disabled */
3396 #if defined(STM32F446xx)
3397     if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)
3398         || \
3399         ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)) || \
3400         ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLLR) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
3401 #else
3402     if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)
3403         || \
3404         ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
3405 #endif /* STM32F446xx */
3406     {
3407       if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
3408       {
3409         return HAL_ERROR;
3410       }
3411     }
3412     else
3413     {
3414       /* Set the new HSE configuration ---------------------------------------*/
3415       __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
3416 
3417       /* Check the HSE State */
3418       if ((RCC_OscInitStruct->HSEState) != RCC_HSE_OFF)
3419       {
3420         /* Get Start Tick*/
3421         tickstart = HAL_GetTick();
3422 
3423         /* Wait till HSE is ready */
3424         while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
3425         {
3426           if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
3427           {
3428             return HAL_TIMEOUT;
3429           }
3430         }
3431       }
3432       else
3433       {
3434         /* Get Start Tick*/
3435         tickstart = HAL_GetTick();
3436 
3437         /* Wait till HSE is bypassed or disabled */
3438         while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET)
3439         {
3440           if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
3441           {
3442             return HAL_TIMEOUT;
3443           }
3444         }
3445       }
3446     }
3447   }
3448   /*----------------------------- HSI Configuration --------------------------*/
3449   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
3450   {
3451     /* Check the parameters */
3452     assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
3453     assert_param(IS_RCC_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
3454 
3455     /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
3456 #if defined(STM32F446xx)
3457     if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)
3458         || \
3459         ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)) || \
3460         ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLLR) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)))
3461 #else
3462     if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)
3463         || \
3464         ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)))
3465 #endif /* STM32F446xx */
3466     {
3467       /* When HSI is used as system clock it will not disabled */
3468       if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON))
3469       {
3470         return HAL_ERROR;
3471       }
3472       /* Otherwise, just the calibration is allowed */
3473       else
3474       {
3475         /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
3476         __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
3477       }
3478     }
3479     else
3480     {
3481       /* Check the HSI State */
3482       if ((RCC_OscInitStruct->HSIState) != RCC_HSI_OFF)
3483       {
3484         /* Enable the Internal High Speed oscillator (HSI). */
3485         __HAL_RCC_HSI_ENABLE();
3486 
3487         /* Get Start Tick*/
3488         tickstart = HAL_GetTick();
3489 
3490         /* Wait till HSI is ready */
3491         while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
3492         {
3493           if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
3494           {
3495             return HAL_TIMEOUT;
3496           }
3497         }
3498 
3499         /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
3500         __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
3501       }
3502       else
3503       {
3504         /* Disable the Internal High Speed oscillator (HSI). */
3505         __HAL_RCC_HSI_DISABLE();
3506 
3507         /* Get Start Tick*/
3508         tickstart = HAL_GetTick();
3509 
3510         /* Wait till HSI is ready */
3511         while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET)
3512         {
3513           if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
3514           {
3515             return HAL_TIMEOUT;
3516           }
3517         }
3518       }
3519     }
3520   }
3521   /*------------------------------ LSI Configuration -------------------------*/
3522   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
3523   {
3524     /* Check the parameters */
3525     assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
3526 
3527     /* Check the LSI State */
3528     if ((RCC_OscInitStruct->LSIState) != RCC_LSI_OFF)
3529     {
3530       /* Enable the Internal Low Speed oscillator (LSI). */
3531       __HAL_RCC_LSI_ENABLE();
3532 
3533       /* Get Start Tick*/
3534       tickstart = HAL_GetTick();
3535 
3536       /* Wait till LSI is ready */
3537       while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET)
3538       {
3539         if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
3540         {
3541           return HAL_TIMEOUT;
3542         }
3543       }
3544     }
3545     else
3546     {
3547       /* Disable the Internal Low Speed oscillator (LSI). */
3548       __HAL_RCC_LSI_DISABLE();
3549 
3550       /* Get Start Tick*/
3551       tickstart = HAL_GetTick();
3552 
3553       /* Wait till LSI is ready */
3554       while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET)
3555       {
3556         if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
3557         {
3558           return HAL_TIMEOUT;
3559         }
3560       }
3561     }
3562   }
3563   /*------------------------------ LSE Configuration -------------------------*/
3564   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
3565   {
3566     FlagStatus       pwrclkchanged = RESET;
3567 
3568     /* Check the parameters */
3569     assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
3570 
3571     /* Update LSE configuration in Backup Domain control register    */
3572     /* Requires to enable write access to Backup Domain of necessary */
3573     if (__HAL_RCC_PWR_IS_CLK_DISABLED())
3574     {
3575       __HAL_RCC_PWR_CLK_ENABLE();
3576       pwrclkchanged = SET;
3577     }
3578 
3579     if (HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
3580     {
3581       /* Enable write access to Backup domain */
3582       SET_BIT(PWR->CR, PWR_CR_DBP);
3583 
3584       /* Wait for Backup domain Write protection disable */
3585       tickstart = HAL_GetTick();
3586 
3587       while (HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
3588       {
3589         if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
3590         {
3591           return HAL_TIMEOUT;
3592         }
3593       }
3594     }
3595 
3596     /* Set the new LSE configuration -----------------------------------------*/
3597     __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
3598     /* Check the LSE State */
3599     if ((RCC_OscInitStruct->LSEState) != RCC_LSE_OFF)
3600     {
3601       /* Get Start Tick*/
3602       tickstart = HAL_GetTick();
3603 
3604       /* Wait till LSE is ready */
3605       while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
3606       {
3607         if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
3608         {
3609           return HAL_TIMEOUT;
3610         }
3611       }
3612     }
3613     else
3614     {
3615       /* Get Start Tick*/
3616       tickstart = HAL_GetTick();
3617 
3618       /* Wait till LSE is ready */
3619       while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
3620       {
3621         if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
3622         {
3623           return HAL_TIMEOUT;
3624         }
3625       }
3626     }
3627 
3628     /* Restore clock configuration if changed */
3629     if (pwrclkchanged == SET)
3630     {
3631       __HAL_RCC_PWR_CLK_DISABLE();
3632     }
3633   }
3634   /*-------------------------------- PLL Configuration -----------------------*/
3635   /* Check the parameters */
3636   assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
3637   if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
3638   {
3639     /* Check if the PLL is used as system clock or not */
3640     if (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
3641     {
3642       if ((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
3643       {
3644         /* Check the parameters */
3645         assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
3646         assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
3647         assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
3648         assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
3649         assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
3650         assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));
3651 
3652         /* Disable the main PLL. */
3653         __HAL_RCC_PLL_DISABLE();
3654 
3655         /* Get Start Tick*/
3656         tickstart = HAL_GetTick();
3657 
3658         /* Wait till PLL is ready */
3659         while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
3660         {
3661           if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
3662           {
3663             return HAL_TIMEOUT;
3664           }
3665         }
3666 
3667         /* Configure the main PLL clock source, multiplication and division factors. */
3668         WRITE_REG(RCC->PLLCFGR, (RCC_OscInitStruct->PLL.PLLSource                                            | \
3669                                  RCC_OscInitStruct->PLL.PLLM                                                 | \
3670                                  (RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos)                       | \
3671                                  (((RCC_OscInitStruct->PLL.PLLP >> 1U) - 1U) << RCC_PLLCFGR_PLLP_Pos)        | \
3672                                  (RCC_OscInitStruct->PLL.PLLQ << RCC_PLLCFGR_PLLQ_Pos)                       | \
3673                                  (RCC_OscInitStruct->PLL.PLLR << RCC_PLLCFGR_PLLR_Pos)));
3674         /* Enable the main PLL. */
3675         __HAL_RCC_PLL_ENABLE();
3676 
3677         /* Get Start Tick*/
3678         tickstart = HAL_GetTick();
3679 
3680         /* Wait till PLL is ready */
3681         while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
3682         {
3683           if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
3684           {
3685             return HAL_TIMEOUT;
3686           }
3687         }
3688       }
3689       else
3690       {
3691         /* Disable the main PLL. */
3692         __HAL_RCC_PLL_DISABLE();
3693 
3694         /* Get Start Tick*/
3695         tickstart = HAL_GetTick();
3696 
3697         /* Wait till PLL is ready */
3698         while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
3699         {
3700           if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
3701           {
3702             return HAL_TIMEOUT;
3703           }
3704         }
3705       }
3706     }
3707     else
3708     {
3709       /* Check if there is a request to disable the PLL used as System clock source */
3710       if ((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF)
3711       {
3712         return HAL_ERROR;
3713       }
3714       else
3715       {
3716         /* Do not return HAL_ERROR if request repeats the current configuration */
3717         pll_config = RCC->PLLCFGR;
3718 #if defined (RCC_PLLCFGR_PLLR)
3719         if (((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF) ||
3720             (READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
3721             (READ_BIT(pll_config, RCC_PLLCFGR_PLLM) != (RCC_OscInitStruct->PLL.PLLM) << RCC_PLLCFGR_PLLM_Pos) ||
3722             (READ_BIT(pll_config, RCC_PLLCFGR_PLLN) != (RCC_OscInitStruct->PLL.PLLN) << RCC_PLLCFGR_PLLN_Pos) ||
3723             (READ_BIT(pll_config, RCC_PLLCFGR_PLLP) != (((RCC_OscInitStruct->PLL.PLLP >> 1U) - 1U)) << RCC_PLLCFGR_PLLP_Pos) ||
3724             (READ_BIT(pll_config, RCC_PLLCFGR_PLLQ) != (RCC_OscInitStruct->PLL.PLLQ << RCC_PLLCFGR_PLLQ_Pos)) ||
3725             (READ_BIT(pll_config, RCC_PLLCFGR_PLLR) != (RCC_OscInitStruct->PLL.PLLR << RCC_PLLCFGR_PLLR_Pos)))
3726 #else
3727         if (((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF) ||
3728             (READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
3729             (READ_BIT(pll_config, RCC_PLLCFGR_PLLM) != (RCC_OscInitStruct->PLL.PLLM) << RCC_PLLCFGR_PLLM_Pos) ||
3730             (READ_BIT(pll_config, RCC_PLLCFGR_PLLN) != (RCC_OscInitStruct->PLL.PLLN) << RCC_PLLCFGR_PLLN_Pos) ||
3731             (READ_BIT(pll_config, RCC_PLLCFGR_PLLP) != (((RCC_OscInitStruct->PLL.PLLP >> 1U) - 1U)) << RCC_PLLCFGR_PLLP_Pos) ||
3732             (READ_BIT(pll_config, RCC_PLLCFGR_PLLQ) != (RCC_OscInitStruct->PLL.PLLQ << RCC_PLLCFGR_PLLQ_Pos)))
3733 #endif /* RCC_PLLCFGR_PLLR */
3734         {
3735           return HAL_ERROR;
3736         }
3737       }
3738     }
3739   }
3740   return HAL_OK;
3741 }
3742 
3743 /**
3744   * @brief  Configures the RCC_OscInitStruct according to the internal
3745   * RCC configuration registers.
3746   * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that will be configured.
3747   *
3748   * @note   This function is only available in case of STM32F410xx/STM32F446xx/STM32F469xx/STM32F479xx/STM32F412Zx/STM32F412Vx/STM32F412Rx/STM32F412Cx devices.
3749   * @note   This function add the PLL/PLLR factor management
3750   * @retval None
3751   */
HAL_RCC_GetOscConfig(RCC_OscInitTypeDef * RCC_OscInitStruct)3752 void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
3753 {
3754   /* Set all possible values for the Oscillator type parameter ---------------*/
3755   RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
3756 
3757   /* Get the HSE configuration -----------------------------------------------*/
3758   if ((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
3759   {
3760     RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
3761   }
3762   else if ((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON)
3763   {
3764     RCC_OscInitStruct->HSEState = RCC_HSE_ON;
3765   }
3766   else
3767   {
3768     RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
3769   }
3770 
3771   /* Get the HSI configuration -----------------------------------------------*/
3772   if ((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
3773   {
3774     RCC_OscInitStruct->HSIState = RCC_HSI_ON;
3775   }
3776   else
3777   {
3778     RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
3779   }
3780 
3781   RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->CR & RCC_CR_HSITRIM) >> RCC_CR_HSITRIM_Pos);
3782 
3783   /* Get the LSE configuration -----------------------------------------------*/
3784   if ((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
3785   {
3786     RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
3787   }
3788   else if ((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
3789   {
3790     RCC_OscInitStruct->LSEState = RCC_LSE_ON;
3791   }
3792   else
3793   {
3794     RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
3795   }
3796 
3797   /* Get the LSI configuration -----------------------------------------------*/
3798   if ((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION)
3799   {
3800     RCC_OscInitStruct->LSIState = RCC_LSI_ON;
3801   }
3802   else
3803   {
3804     RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
3805   }
3806 
3807   /* Get the PLL configuration -----------------------------------------------*/
3808   if ((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON)
3809   {
3810     RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
3811   }
3812   else
3813   {
3814     RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
3815   }
3816   RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
3817   RCC_OscInitStruct->PLL.PLLM = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
3818   RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
3819   RCC_OscInitStruct->PLL.PLLP = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) + RCC_PLLCFGR_PLLP_0) << 1U) >> RCC_PLLCFGR_PLLP_Pos);
3820   RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos);
3821   RCC_OscInitStruct->PLL.PLLR = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos);
3822 }
3823 #endif /* STM32F410xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */
3824 
3825 #endif /* HAL_RCC_MODULE_ENABLED */
3826 /**
3827   * @}
3828   */
3829 
3830 /**
3831   * @}
3832   */
3833 
3834