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