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