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