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