1 /**
2   ******************************************************************************
3   * @file    stm32wbxx_ll_utils.c
4   * @author  MCD Application Team
5   * @brief   UTILS LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * Copyright (c) 2019 STMicroelectronics.
10   * All rights reserved.
11   *
12   * This software is licensed under terms that can be found in the LICENSE file
13   * in the root directory of this software component.
14   * If no LICENSE file comes with this software, it is provided AS-IS.
15   *
16   ******************************************************************************
17   */
18 /* Includes ------------------------------------------------------------------*/
19 #include "stm32wbxx_ll_utils.h"
20 #include "stm32wbxx_ll_rcc.h"
21 #include "stm32wbxx_ll_system.h"
22 #include "stm32wbxx_ll_pwr.h"
23 #ifdef  USE_FULL_ASSERT
24 #include "stm32_assert.h"
25 #else
26 #define assert_param(expr) ((void)0U)
27 #endif /* USE_FULL_ASSERT */
28 
29 /** @addtogroup STM32WBxx_LL_Driver
30   * @{
31   */
32 
33 /** @addtogroup UTILS_LL
34   * @{
35   */
36 
37 /* Private types -------------------------------------------------------------*/
38 /* Private variables ---------------------------------------------------------*/
39 /* Private constants ---------------------------------------------------------*/
40 /** @addtogroup UTILS_LL_Private_Constants
41   * @{
42   */
43 #define UTILS_MAX_FREQUENCY_SCALE1  64000000U        /*!< Maximum frequency for system clock at power scale1, in Hz */
44 #if defined(PWR_CR1_VOS)
45 #define UTILS_MAX_FREQUENCY_SCALE2  16000000U        /*!< Maximum frequency for system clock at power scale2, in Hz */
46 #endif /* PWR_CR1_VOS */
47 
48 /* Defines used for PLL range */
49 #define UTILS_PLLVCO_INPUT_MIN        2660000U       /*!< Frequency min for PLLVCO input, in Hz   */
50 #define UTILS_PLLVCO_INPUT_MAX       16000000U       /*!< Frequency max for PLLVCO input, in Hz   */
51 #define UTILS_PLLVCO_OUTPUT_MIN      96000000U       /*!< Frequency min for PLLVCO output, in Hz  */
52 #define UTILS_PLLVCO_OUTPUT_MAX     344000000U       /*!< Frequency max for PLLVCO output, in Hz  */
53 
54 /* Defines used for HCLK2 frequency check */
55 #define UTILS_HCLK2_MAX             32000000U        /*!< HCLK2 frequency maximum at 32MHz */
56 
57 /**
58   * @}
59   */
60 
61 /* Private macros ------------------------------------------------------------*/
62 /** @addtogroup UTILS_LL_Private_Macros
63   * @{
64   */
65 #define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1)   \
66                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2)   \
67                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_3)   \
68                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4)   \
69                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_5)   \
70                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_6)   \
71                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8)   \
72                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_10)  \
73                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16)  \
74                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_32)  \
75                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_64)  \
76                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \
77                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \
78                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_512))
79 
80 #define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
81                                          || ((__VALUE__) == LL_RCC_APB1_DIV_2) \
82                                          || ((__VALUE__) == LL_RCC_APB1_DIV_4) \
83                                          || ((__VALUE__) == LL_RCC_APB1_DIV_8) \
84                                          || ((__VALUE__) == LL_RCC_APB1_DIV_16))
85 
86 #define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \
87                                          || ((__VALUE__) == LL_RCC_APB2_DIV_2) \
88                                          || ((__VALUE__) == LL_RCC_APB2_DIV_4) \
89                                          || ((__VALUE__) == LL_RCC_APB2_DIV_8) \
90                                          || ((__VALUE__) == LL_RCC_APB2_DIV_16))
91 
92 #define IS_LL_UTILS_PLLM_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLM_DIV_1) \
93                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_2) \
94                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_3) \
95                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_4) \
96                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_5) \
97                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_6) \
98                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_7) \
99                                            || ((__VALUE__) == LL_RCC_PLLM_DIV_8))
100 
101 #define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((6U <= (__VALUE__)) && ((__VALUE__) <= 127U))
102 
103 #define IS_LL_UTILS_PLLR_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLR_DIV_2) \
104                                            || ((__VALUE__) == LL_RCC_PLLR_DIV_3) \
105                                            || ((__VALUE__) == LL_RCC_PLLR_DIV_4) \
106                                            || ((__VALUE__) == LL_RCC_PLLR_DIV_5) \
107                                            || ((__VALUE__) == LL_RCC_PLLR_DIV_6) \
108                                            || ((__VALUE__) == LL_RCC_PLLR_DIV_7) \
109                                            || ((__VALUE__) == LL_RCC_PLLR_DIV_8))
110 
111 #define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__)  ((UTILS_PLLVCO_INPUT_MIN <= (__VALUE__)) &&\
112                                               ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX))
113 
114 #define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__) ((UTILS_PLLVCO_OUTPUT_MIN <= (__VALUE__)) &&\
115                                               ((__VALUE__) <= UTILS_PLLVCO_OUTPUT_MAX))
116 
117 #if defined(PWR_CR1_VOS)
118 #define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \
119                                               ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2))
120 #else
121 #define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1)
122 #endif /* PWR_CR1_VOS */
123 
124 #define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \
125                                            || ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
126 
127 #define countof(a)   (sizeof(a) / sizeof(*(a)))
128 /**
129   * @}
130   */
131 /* Private function prototypes -----------------------------------------------*/
132 /** @defgroup UTILS_LL_Private_Functions UTILS Private functions
133   * @{
134   */
135 static uint32_t    UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,
136                                                LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct);
137 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,
138                                                   LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
139 static ErrorStatus UTILS_PLL_IsBusy(void);
140 
141 /**
142   * @}
143   */
144 
145 /* Exported functions --------------------------------------------------------*/
146 /** @addtogroup UTILS_LL_Exported_Functions
147   * @{
148   */
149 
150 /** @addtogroup UTILS_LL_EF_DELAY
151   * @{
152   */
153 
154 /**
155   * @brief  This function configures the Cortex-M SysTick source to have 1ms time base.
156   * @note   When a RTOS is used, it is recommended to avoid changing the Systick
157   *         configuration by calling this function, for a delay use rather osDelay RTOS service.
158   * @param  HCLKFrequency HCLK frequency in Hz
159   * @note   HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq (HCLK1_Frequency field)
160   * @retval None
161   */
LL_Init1msTick(uint32_t HCLKFrequency)162 void LL_Init1msTick(uint32_t HCLKFrequency)
163 {
164   /* Use frequency provided in argument */
165   LL_InitTick(HCLKFrequency, 1000);
166 }
167 
168 
169 /**
170   * @brief  This function provides accurate delay (in milliseconds) based
171   *         on SysTick counter flag
172   * @note   When a RTOS is used, it is recommended to avoid using blocking delay
173   *         and use rather osDelay service.
174   * @note   To respect 1ms timebase, user should call @ref LL_Init1msTick function which
175   *         will configure Systick to 1ms
176   * @param  Delay specifies the delay time length, in milliseconds.
177   * @retval None
178   */
LL_mDelay(uint32_t Delay)179 void LL_mDelay(uint32_t Delay)
180 {
181   uint32_t mDelay = Delay;
182   __IO uint32_t  tmp = SysTick->CTRL;  /* Clear the COUNTFLAG first */
183   /* Add this code to indicate that local variable is not used */
184   ((void)tmp);
185 
186   /* Add a period to guaranty minimum wait */
187   if (mDelay < LL_MAX_DELAY)
188   {
189     mDelay++;
190   }
191 
192   while (mDelay != 0U)
193   {
194     if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
195     {
196       mDelay--;
197     }
198   }
199 }
200 
201 /**
202   * @}
203   */
204 
205 /** @addtogroup UTILS_EF_SYSTEM
206   *  @brief    System Configuration functions
207   *
208   @verbatim
209  ===============================================================================
210            ##### System Configuration functions #####
211  ===============================================================================
212     [..]
213          System, HCLK1, HCLK2, AHBS, AHBRF and APB buses clocks configuration
214 
215          (+) The maximum frequency of the SYSCLK, HCLK1, HCLK4, PCLK1 and PCLK2
216              is 640000000 Hz.
217  ....... (+) The maximum frequency of the HCLK2 is 320000000 Hz.
218 
219   @endverbatim
220   @internal
221              Depending on the device voltage range, the maximum frequency should be
222              adapted accordingly:
223              (++) HCLK4 clock frequency for STM32WB55xx device
224              (++) +--------------------------------------------------------+
225              (++) | Latency         |     HCLK4 clock frequency (MHz)      |
226              (++) |                 |--------------------------------------|
227              (++) |                 |  voltage range 1  | voltage range 2  |
228              (++) |                 |       1.2 V       |     1.0 V        |
229              (++) |-----------------|-------------------|------------------|
230              (++) |0WS(1 CPU cycles)|   0 < HCLK4 <= 18 |  0 < HCLK4 <= 6  |
231              (++) |-----------------|-------------------|------------------|
232              (++) |1WS(2 CPU cycles)|  18 < HCLK4 <= 36 |  6 < HCLK4 <= 12 |
233              (++) |-----------------|-------------------|------------------|
234              (++) |2WS(3 CPU cycles)|  36 < HCLK4 <= 54 | 12 < HCLK4 <= 16|
235              (++) |-----------------|-------------------|------------------|
236              (++) |3WS(4 CPU cycles)|  54 < HCLK4 <= 64 |       N.A.       |
237              (++) +--------------------------------------------------------+
238   @endinternal
239   * @{
240   */
241 
242 /**
243   * @brief  This function sets directly SystemCoreClock CMSIS variable.
244   * @note   Variable can be calculated also through SystemCoreClockUpdate function.
245   * @param  HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq (HCLK1_Frequency field))
246   * @retval None
247   */
LL_SetSystemCoreClock(uint32_t HCLKFrequency)248 void LL_SetSystemCoreClock(uint32_t HCLKFrequency)
249 {
250   /* HCLK clock frequency */
251   SystemCoreClock = HCLKFrequency;
252 }
253 
254 /**
255   * @brief  Update number of Flash wait states in line with new frequency and current
256             voltage range.
257   * @param  HCLK4Frequency  HCLK4 frequency
258   * @retval An ErrorStatus enumeration value:
259   *          - SUCCESS: Latency has been modified
260   *          - ERROR: Latency cannot be modified
261   */
LL_SetFlashLatency(uint32_t HCLK4Frequency)262 ErrorStatus LL_SetFlashLatency(uint32_t HCLK4Frequency)
263 {
264   ErrorStatus status = ERROR;
265   uint32_t latency   = LL_FLASH_LATENCY_0;  /* default value 0WS */
266   uint16_t index;
267   uint32_t timeout;
268   uint32_t getlatency;
269 #if defined(PWR_CR1_VOS)
270   uint32_t voltagescaling = LL_PWR_GetRegulVoltageScaling();
271   uint32_t maxfreq = (voltagescaling == LL_PWR_REGU_VOLTAGE_SCALE1) ? UTILS_MAX_FREQUENCY_SCALE1 : UTILS_MAX_FREQUENCY_SCALE2;
272 #else
273   uint32_t maxfreq = UTILS_MAX_FREQUENCY_SCALE1;
274 #endif /* PWR_CR1_VOS */
275 
276   /* Array used for FLASH latency according to HCLK4 Frequency */
277   /* Flash Clock source (HCLK4) range in MHz with a VCORE is range1 */
278   const uint32_t UTILS_CLK_SRC_RANGE_VOS1[] = {18000000U, 36000000U, 54000000U, UTILS_MAX_FREQUENCY_SCALE1};
279 
280 #if defined(PWR_CR1_VOS)
281   /* Flash Clock source (HCLK4) range in MHz with a VCORE is range2 */
282   const uint32_t UTILS_CLK_SRC_RANGE_VOS2[] = {6000000U, 12000000U, UTILS_MAX_FREQUENCY_SCALE2};
283 #endif /* PWR_CR1_VOS */
284 
285   /* Flash Latency range */
286   const uint32_t UTILS_LATENCY_RANGE[] = {LL_FLASH_LATENCY_0, LL_FLASH_LATENCY_1, LL_FLASH_LATENCY_2, LL_FLASH_LATENCY_3};
287 
288   /* Frequency cannot be equal to 0 or greater than max clock */
289   if ((HCLK4Frequency > 0U) && (HCLK4Frequency <= maxfreq))
290   {
291 #if defined(PWR_CR1_VOS)
292     if (voltagescaling == LL_PWR_REGU_VOLTAGE_SCALE1)
293     {
294       for (index = 0; index < countof(UTILS_CLK_SRC_RANGE_VOS1); index++)
295       {
296         if (HCLK4Frequency <= UTILS_CLK_SRC_RANGE_VOS1[index])
297         {
298           latency = UTILS_LATENCY_RANGE[index];
299           status = SUCCESS;
300           break;
301         }
302       }
303     }
304     else /* SCALE2 */
305     {
306       for (index = 0; index < countof(UTILS_CLK_SRC_RANGE_VOS2); index++)
307       {
308         if (HCLK4Frequency <= UTILS_CLK_SRC_RANGE_VOS2[index])
309         {
310           latency = UTILS_LATENCY_RANGE[index];
311           status = SUCCESS;
312           break;
313         }
314       }
315     }
316 #else
317     for (index = 0; index < countof(UTILS_CLK_SRC_RANGE_VOS1); index++)
318     {
319       if (HCLK4Frequency <= UTILS_CLK_SRC_RANGE_VOS1[index])
320       {
321         latency = UTILS_LATENCY_RANGE[index];
322         status = SUCCESS;
323         break;
324       }
325     }
326 #endif /* PWR_CR1_VOS */
327   }
328 
329   if (status != ERROR)
330   {
331     LL_FLASH_SetLatency(latency);
332 
333     /* Check that the new number of wait states is taken into account to access the Flash
334        memory by reading the FLASH_ACR register */
335     timeout = 2U;
336     do
337     {
338       /* Wait for Flash latency to be updated */
339       getlatency = LL_FLASH_GetLatency();
340       timeout--;
341     } while ((getlatency != latency) && (timeout > 0U));
342 
343     if (getlatency != latency)
344     {
345       status = ERROR;
346     }
347   }
348   return status;
349 }
350 
351 /**
352   * @brief  This function configures system clock with MSI as clock source of the PLL
353   * @note   The application needs to ensure that PLL and PLLSAI1 are disabled.
354   * @note   The application needs to ensure that PLL configuration is valid
355   * @note   The application needs to ensure that MSI range is valid.
356   * @note   The application needs to ensure that BUS prescalers are valid
357   * @note   Function is based on the following formula:
358   *         - PLL output frequency = (((MSI frequency / PLLM) * PLLN) / PLLR)
359   *         - PLLM: ensure that the VCO input frequency ranges from 2.66 to 16 MHz (PLLVCO_input = MSI frequency / PLLM)
360   *         - PLLN: ensure that the VCO output frequency is between 96 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
361   *         - PLLR: ensure that max frequency at 64000000 Hz is reached (PLLVCO_output / PLLR)
362   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
363   *                             the configuration information for the PLL.
364   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
365   *                             the configuration information for the BUS prescalers.
366   * @retval An ErrorStatus enumeration value:
367   *          - SUCCESS: Max frequency configuration done
368   *          - ERROR: Max frequency configuration not done
369   */
LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)370 ErrorStatus LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
371                                          LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
372 {
373   ErrorStatus status;
374   uint32_t pllrfreq, hclk2freq, msi_range;
375 
376   /* Check if one of the PLL is enabled */
377   if (UTILS_PLL_IsBusy() == SUCCESS)
378   {
379     /* Get the current MSI range & check coherency */
380     msi_range =  LL_RCC_MSI_GetRange();
381     switch (msi_range)
382     {
383       case LL_RCC_MSIRANGE_0:     /* MSI = 100 KHz  */
384       case LL_RCC_MSIRANGE_1:     /* MSI = 200 KHz  */
385       case LL_RCC_MSIRANGE_2:     /* MSI = 400 KHz  */
386       case LL_RCC_MSIRANGE_3:     /* MSI = 800 KHz  */
387       case LL_RCC_MSIRANGE_4:     /* MSI = 1 MHz    */
388       case LL_RCC_MSIRANGE_5:     /* MSI = 2 MHz    */
389         /* PLLVCO input frequency can not in the range from 2.66 to 16 MHz*/
390         status = ERROR;
391         break;
392 
393       case LL_RCC_MSIRANGE_6:     /* MSI = 4 MHz    */
394       case LL_RCC_MSIRANGE_7:     /* MSI = 8 MHz    */
395       case LL_RCC_MSIRANGE_8:     /* MSI = 16 MHz   */
396       case LL_RCC_MSIRANGE_9:     /* MSI = 24 MHz   */
397       case LL_RCC_MSIRANGE_10:    /* MSI = 32 MHz   */
398       case LL_RCC_MSIRANGE_11:    /* MSI = 48 MHz   */
399       default:
400         status = SUCCESS;
401         break;
402     }
403 
404     /* PLL is ready, MSI range is valid and HCLK2 frequency is coherent
405        Main PLL configuration and activation */
406     if (status != ERROR)
407     {
408       /* Calculate the new PLL output frequency & verify all PLL stages are correct (VCO input ranges,
409          VCO output ranges & SYSCLK max) when assert activated */
410       pllrfreq = UTILS_GetPLLOutputFrequency(__LL_RCC_CALC_MSI_FREQ(msi_range), UTILS_PLLInitStruct);
411       hclk2freq = __LL_RCC_CALC_HCLK2_FREQ(pllrfreq, UTILS_ClkInitStruct->CPU2CLKDivider);
412 
413       /* Check HCLK2 frequency coherency */
414       if (hclk2freq > UTILS_HCLK2_MAX)
415       {
416         /* HCLK2 frequency can not be higher than 32Mhz */
417         status = ERROR;
418       }
419       else
420       {
421 
422         /* Enable MSI if not enabled */
423         if (LL_RCC_MSI_IsReady() != 1U)
424         {
425           LL_RCC_MSI_Enable();
426           while ((LL_RCC_MSI_IsReady() != 1U))
427           {
428             /* Wait for MSI ready */
429           }
430         }
431 
432         /* Configure PLL domain SYS */
433         LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
434                                     UTILS_PLLInitStruct->PLLR);
435 
436         /* Enable PLL and switch system clock to PLL - latency check done internally */
437         status = UTILS_EnablePLLAndSwitchSystem(pllrfreq, UTILS_ClkInitStruct);
438       }
439     }
440   }
441   else
442   {
443     /* Current PLL configuration cannot be modified */
444     status = ERROR;
445   }
446 
447   return status;
448 }
449 
450 /**
451   * @brief  This function configures system clock at maximum frequency with HSI as clock source of the PLL
452   * @note   The application need to ensure that PLL and/or PLLSAI1 are disabled.
453   * @note   The application needs to ensure that PLL configuration is valid
454   * @note   The application needs to ensure that BUS prescalers are valid
455   * @note   Function is based on the following formula:
456   *         - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLR)
457   *         - PLLM: ensure that the VCO input frequency ranges from 2.66 to 16 MHz (PLLVCO_input = HSI frequency / PLLM)
458   *         - PLLN: ensure that the VCO output frequency is between 96 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
459   *         - PLLR: ensure that max frequency at 64000000 Hz is reach (PLLVCO_output / PLLR)
460   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
461   *                             the configuration information for the PLL.
462   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
463   *                             the configuration information for the BUS prescalers.
464   * @retval An ErrorStatus enumeration value:
465   *          - SUCCESS: Max frequency configuration done
466   *          - ERROR: Max frequency configuration not done
467   */
LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)468 ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
469                                          LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
470 {
471   ErrorStatus status;
472   uint32_t pllrfreq, hclk2freq;
473 
474   /* Check if one of the PLL is enabled */
475   if (UTILS_PLL_IsBusy() == SUCCESS)
476   {
477     /* Calculate the new PLL output frequency */
478     pllrfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct);
479     hclk2freq = __LL_RCC_CALC_HCLK2_FREQ(pllrfreq, UTILS_ClkInitStruct->CPU2CLKDivider);
480 
481     /* Check HCLK2 frequency coherency */
482     if (hclk2freq > UTILS_HCLK2_MAX)
483     {
484       /* HCLK2 frequency can not be higher than 32Mhz */
485       status = ERROR;
486     }
487     else
488     {
489       /* Enable HSI if not enabled */
490       if (LL_RCC_HSI_IsReady() != 1U)
491       {
492         LL_RCC_HSI_Enable();
493         while (LL_RCC_HSI_IsReady() != 1U)
494         {
495           /* Wait for HSI ready */
496         }
497       }
498 
499       /* Configure PLL */
500       LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
501                                   UTILS_PLLInitStruct->PLLR);
502 
503       /* Enable PLL and switch system clock to PLL */
504       status = UTILS_EnablePLLAndSwitchSystem(pllrfreq, UTILS_ClkInitStruct);
505     }
506   }
507   else
508   {
509     /* Current PLL configuration cannot be modified */
510     status = ERROR;
511   }
512 
513   return status;
514 }
515 
516 /**
517   * @brief  This function configures system clock with HSE as clock source of the PLL
518   * @note   The application need to ensure that PLL and/or PLLSAI1 are disabled.
519   * @note   The application needs to ensure that PLL configuration is valid
520   * @note   The application needs to ensure that BUS prescalers are valid
521   * @note   Function is based on the following formula:
522   *         - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLR)
523   *         - PLLM: ensure that the VCO input frequency ranges from 2.66 to 16 MHz (PLLVCO_input = HSE frequency / PLLM)
524   *         - PLLN: ensure that the VCO output frequency is between 96 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
525   *         - PLLR: ensure that max frequency at 64000000 Hz is reached (PLLVCO_output / PLLR)
526   * @param  HSEBypass This parameter can be one of the following values:
527   *         @arg @ref LL_UTILS_HSEBYPASS_ON
528   *         @arg @ref LL_UTILS_HSEBYPASS_OFF
529   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
530   *                             the configuration information for the PLL.
531   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
532   *                             the configuration information for the BUS prescalers.
533   * @retval An ErrorStatus enumeration value:
534   *          - SUCCESS: Max frequency configuration done
535   *          - ERROR: Max frequency configuration not done
536   */
LL_PLL_ConfigSystemClock_HSE(uint32_t HSEBypass,LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)537 ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEBypass, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
538                                          LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
539 {
540   ErrorStatus status;
541   uint32_t pllrfreq, hclk2freq;
542 
543   /* Check the parameters */
544   assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
545 
546   /* Check if one of the PLL is enabled */
547   if (UTILS_PLL_IsBusy() == SUCCESS)
548   {
549     /* Calculate the new PLL output frequency */
550     pllrfreq = UTILS_GetPLLOutputFrequency(HSE_VALUE, UTILS_PLLInitStruct);
551     hclk2freq = __LL_RCC_CALC_HCLK2_FREQ(pllrfreq, UTILS_ClkInitStruct->CPU2CLKDivider);
552 
553     /* Check HCLK2 frequency coherency */
554     if (hclk2freq > UTILS_HCLK2_MAX)
555     {
556       /* HCLK2 frequency can not be higher than 32Mhz */
557       status = ERROR;
558     }
559     else
560     {
561 
562       /* Enable HSE if not enabled */
563       if (LL_RCC_HSE_IsReady() != 1U)
564       {
565 #if defined(RCC_CR_HSEBYP)
566         /* Check if need to enable HSE bypass feature or not */
567         if (HSEBypass == LL_UTILS_HSEBYPASS_ON)
568         {
569           LL_RCC_HSE_EnableBypass();
570         }
571         else
572         {
573           LL_RCC_HSE_DisableBypass();
574         }
575 #endif /* RCC_CR_HSEBYP */
576         /* Enable HSE */
577         LL_RCC_HSE_Enable();
578         while (LL_RCC_HSE_IsReady() != 1U)
579         {
580           /* Wait for HSE ready */
581         }
582       }
583 
584       /* Configure PLL */
585       LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
586                                   UTILS_PLLInitStruct->PLLR);
587 
588       /* Enable PLL and switch system clock to PLL */
589       status = UTILS_EnablePLLAndSwitchSystem(pllrfreq, UTILS_ClkInitStruct);
590     }
591   }
592   else
593   {
594     /* Current PLL configuration cannot be modified */
595     status = ERROR;
596   }
597 
598   return status;
599 }
600 
601 
602 /**
603   * @}
604   */
605 
606 
607 /**
608   * @}
609   */
610 
611 /** @addtogroup UTILS_LL_Private_Functions
612   * @{
613   */
614 /**
615   * @brief  Function to check that PLL can be modified
616   * @param  PLL_InputFrequency  PLL input frequency (in Hz)
617   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
618   *                             the configuration information for the PLL.
619   * @retval PLL output frequency (in Hz)
620   */
UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct)621 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct)
622 {
623   uint32_t pllfreq;
624 
625   /* Check the parameters */
626   assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
627   assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
628   assert_param(IS_LL_UTILS_PLLR_VALUE(UTILS_PLLInitStruct->PLLR));
629 
630   /* Check different PLL parameters according to RM                          */
631   /*  - PLLM: ensure that the VCO input frequency ranges from 2.66 to 16 MHz.   */
632   pllfreq = PLL_InputFrequency / (((UTILS_PLLInitStruct->PLLM >> RCC_PLLCFGR_PLLM_Pos) + 1U));
633   assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq));
634 
635   /*  - PLLN: ensure that the VCO output frequency is between 96 and 344 MHz.*/
636   pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN & (RCC_PLLCFGR_PLLN >> RCC_PLLCFGR_PLLN_Pos));
637   assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq));
638 
639   /*  - PLLR: ensure that max frequency at 64000000 Hz is reached                   */
640   pllfreq = pllfreq / ((UTILS_PLLInitStruct->PLLR >> RCC_PLLCFGR_PLLR_Pos) + 1U);
641   assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq));
642 
643   return pllfreq;
644 }
645 
646 /**
647   * @brief  Function to check that PLL can be modified
648   * @retval An ErrorStatus enumeration value:
649   *          - SUCCESS: PLL modification can be done
650   *          - ERROR: PLL is busy
651   */
UTILS_PLL_IsBusy(void)652 static ErrorStatus UTILS_PLL_IsBusy(void)
653 {
654   ErrorStatus status = SUCCESS;
655 
656   /* Check if PLL is busy*/
657   if (LL_RCC_PLL_IsReady() != 0U)
658   {
659     /* PLL configuration cannot be modified */
660     status = ERROR;
661   }
662 #if defined(SAI1)
663   /* Check if PLLSAI1 is busy*/
664   if (LL_RCC_PLLSAI1_IsReady() != 0U)
665   {
666     /* PLLSAI1 configuration cannot be modified */
667     status = ERROR;
668   }
669 #endif /* SAI1 */
670 
671   return status;
672 }
673 
674 /**
675   * @brief  Function to enable PLL and switch system clock to PLL
676   * @param  SYSCLK_Frequency SYSCLK frequency
677   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
678   *                             the configuration information for the BUS prescalers.
679   * @retval An ErrorStatus enumeration value:
680   *          - SUCCESS: No problem to switch system to PLL
681   *          - ERROR: Problem to switch system to PLL
682   */
UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)683 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,
684                                                   LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
685 {
686   ErrorStatus status = SUCCESS;
687   uint32_t hclks_frequency_target, hclks_frequency_current, sysclk_current;
688 
689   assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->CPU1CLKDivider));
690   assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->CPU2CLKDivider));
691   assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHB4CLKDivider));
692   assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
693   assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider));
694 
695   /* Calculate HCLK4 frequency based on SYSCLK_Frequency target */
696   hclks_frequency_target = __LL_RCC_CALC_HCLK4_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHB4CLKDivider);
697 
698   /* Calculate HCLK4 frequency current */
699   sysclk_current = (SystemCoreClock * AHBPrescTable[(LL_RCC_GetAHBPrescaler() & RCC_CFGR_HPRE) >>  RCC_CFGR_HPRE_Pos]);
700   hclks_frequency_current = __LL_RCC_CALC_HCLK4_FREQ(sysclk_current, LL_RCC_GetAHB4Prescaler());
701 
702   /* Increasing the number of wait states because of higher CPU frequency */
703   if (hclks_frequency_current < hclks_frequency_target)
704   {
705     /* Set FLASH latency to highest latency */
706     status = LL_SetFlashLatency(hclks_frequency_target);
707   }
708 
709   /* Update system clock configuration */
710   if (status == SUCCESS)
711   {
712     /* Enable PLL */
713     LL_RCC_PLL_Enable();
714     LL_RCC_PLL_EnableDomain_SYS();
715     while (LL_RCC_PLL_IsReady() != 1U)
716     {
717       /* Wait for PLL ready */
718     }
719 
720     /* Sysclk activation on the main PLL */
721     LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->CPU1CLKDivider);
722     LL_C2_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->CPU2CLKDivider);
723     LL_RCC_SetAHB4Prescaler(UTILS_ClkInitStruct->AHB4CLKDivider);
724     LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
725     while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
726     {
727       /* Wait for system clock switch to PLL */
728     }
729 
730     /* Set APB1 & APB2 prescaler*/
731     LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
732     LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider);
733   }
734 
735   /* Decreasing the number of wait states because of lower CPU frequency */
736   if (hclks_frequency_current > hclks_frequency_target)
737   {
738     /* Set FLASH latency to lowest latency */
739     status = LL_SetFlashLatency(hclks_frequency_target);
740   }
741 
742   /* Update SystemCoreClock variable */
743   if (status == SUCCESS)
744   {
745     LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK1_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->CPU1CLKDivider));
746   }
747 
748   return status;
749 }
750 
751 /**
752   * @}
753   */
754 
755 
756 
757 /**
758   * @}
759   */
760 
761 /**
762   * @}
763   */
764