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