1 /**
2   ******************************************************************************
3   * @file    stm32wbaxx_ll_utils.c
4   * @author  MCD Application Team
5   * @brief   UTILS LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * Copyright (c) 2022 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 "stm32wbaxx_ll_utils.h"
20 #include "stm32wbaxx_ll_rcc.h"
21 #include "stm32wbaxx_ll_system.h"
22 #include "stm32wbaxx_ll_pwr.h"
23 #include <math.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 STM32WBAxx_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_SCALE1  100000000U  /*!< Maximum frequency for system clock at power scale1, in Hz */
45 #define UTILS_MAX_FREQUENCY_SCALE2   16000000U  /*!< Maximum frequency for system clock at power scale2, 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     128000000U  /*!< Frequency min for PLLVCO output, in Hz  */
51 #define UTILS_PLLVCO_OUTPUT_MAX     544000000U  /*!< Frequency max for PLLVCO output, in Hz  */
52 
53 /* Defines used for FLASH latency according to HCLK Frequency */
54 #define UTILS_SCALE1_LATENCY0_FREQ   32000000U  /*!< HCLK frequency to set FLASH latency 0 in power scale 1 */
55 #define UTILS_SCALE1_LATENCY1_FREQ   64000000U  /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
56 #define UTILS_SCALE1_LATENCY2_FREQ   96000000U  /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
57 #define UTILS_SCALE1_LATENCY3_FREQ  100000000U  /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */
58 #define UTILS_SCALE2_LATENCY0_FREQ    8000000U  /*!< HCLK frequency to set FLASH latency 0 in power scale 2 */
59 #define UTILS_SCALE2_LATENCY1_FREQ   16000000U  /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */
60 
61 /**
62   * @}
63   */
64 
65 /* Private macros ------------------------------------------------------------*/
66 /** @addtogroup UTILS_LL_Private_Macros
67   * @{
68   */
69 #define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1)   \
70                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2)   \
71                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4)   \
72                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8)   \
73                                            || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16))
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_APB7_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB7_DIV_1) \
88                                          || ((__VALUE__) == LL_RCC_APB7_DIV_2) \
89                                          || ((__VALUE__) == LL_RCC_APB7_DIV_4) \
90                                          || ((__VALUE__) == LL_RCC_APB7_DIV_8) \
91                                          || ((__VALUE__) == LL_RCC_APB7_DIV_16))
92 
93 #define IS_LL_UTILS_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U))
94 
95 #define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((4U <= (__VALUE__)) && ((__VALUE__) <= 512U))
96 
97 #define IS_LL_UTILS_PLLR_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 128U))
98 
99 #define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__)  ((UTILS_PLLVCO_INPUT_MIN <= (__VALUE__))\
100                                               && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX))
101 
102 #define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__) ((UTILS_PLLVCO_OUTPUT_MIN <= (__VALUE__))\
103                                               && ((__VALUE__) <= UTILS_PLLVCO_OUTPUT_MAX))
104 
105 #define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? \
106                                               ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \
107                                               ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2))
108 
109 #define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) ((__FREQUENCY__) == 32000000U)
110 /**
111   * @}
112   */
113 /* Private function prototypes -----------------------------------------------*/
114 /** @defgroup UTILS_LL_Private_Functions UTILS Private functions
115   * @{
116   */
117 static uint32_t    UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,
118                                                const LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct);
119 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,
120                                                   LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
121 static ErrorStatus UTILS_PLL_IsBusy(void);
122 /**
123   * @}
124   */
125 
126 /* Exported functions --------------------------------------------------------*/
127 /** @addtogroup UTILS_LL_Exported_Functions
128   * @{
129   */
130 
131 /** @addtogroup UTILS_LL_EF_DELAY
132   * @{
133   */
134 
135 /**
136   * @brief  This function configures the Cortex-M SysTick source to have 1ms time base with HCLK as SysTick clock source.
137   * @note   When a RTOS is used, it is recommended to avoid changing the Systick
138   *         configuration by calling this function, for a delay use rather osDelay RTOS service.
139   * @param  HCLKFrequency HCLK frequency in Hz
140   * @note   HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq
141   * @retval None
142   */
LL_Init1msTick(uint32_t HCLKFrequency)143 void LL_Init1msTick(uint32_t HCLKFrequency)
144 {
145   /* Use frequency provided in argument */
146   LL_InitTick(HCLKFrequency, 1000U);
147 }
148 
149 /**
150   * @brief  This function configures the Cortex-M SysTick source to have 1ms time base with HCLK/8 as SysTick clock source.
151   * @note   When a RTOS is used, it is recommended to avoid changing the Systick
152   *         configuration by calling this function, for a delay use rather osDelay RTOS service.
153   * @param  HCLKFrequency HCLK frequency in Hz
154   * @retval None
155   */
LL_Init1msTick_HCLK_Div8(uint32_t HCLKFrequency)156 void LL_Init1msTick_HCLK_Div8(uint32_t HCLKFrequency)
157 {
158   /* Configure the SysTick to have  1ms time base with HCLK/8 as SysTick clock source */
159   SysTick->LOAD = (uint32_t)((HCLKFrequency / 8000U) - 1UL);
160   SysTick->VAL = 0UL;
161   SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
162 }
163 
164 /**
165   * @brief  This function configures the Cortex-M SysTick source to have 1ms time base with LSE as SysTick clock source.
166   * @note   When a RTOS is used, it is recommended to avoid changing the Systick
167   *         configuration by calling this function, for a delay use rather osDelay RTOS service.
168   * @retval None
169   */
LL_Init1msTick_LSE(void)170 void LL_Init1msTick_LSE(void)
171 {
172   /* Configure the SysTick to have  1ms time base with LSE as SysTick clock source */
173   SysTick->LOAD = (uint32_t)((LSE_VALUE / 1000U) - 1UL);
174   SysTick->VAL = 0UL;
175   SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
176 }
177 
178 /**
179   * @brief  This function configures the Cortex-M SysTick source to have 1ms time base with LSI as SysTick clock source.
180   * @note   When a RTOS is used, it is recommended to avoid changing the Systick
181   *         configuration by calling this function, for a delay use rather osDelay RTOS service.
182   * @retval None
183   */
LL_Init1msTick_LSI(void)184 void LL_Init1msTick_LSI(void)
185 {
186   /* Configure the SysTick to have  1ms time base with LSI as SysTick clock source */
187   SysTick->LOAD = (uint32_t)((LSI_VALUE / 1000U) - 1UL);
188   SysTick->VAL = 0UL;
189   SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
190 }
191 
192 /**
193   * @brief  This function provides minimum delay (in milliseconds) based
194   *         on SysTick counter flag
195   * @note   When a RTOS is used, it is recommended to avoid using blocking delay
196   *         and use rather osDelay service.
197   * @note   To respect 1ms timebase, user should call @ref LL_Init1msTick function which
198   *         will configure Systick to 1ms
199   * @param  Delay specifies the minimum delay time length, in milliseconds.
200   * @retval None
201   */
LL_mDelay(uint32_t Delay)202 void LL_mDelay(uint32_t Delay)
203 {
204   __IO uint32_t  tmp = SysTick->CTRL;  /* Clear the COUNTFLAG first */
205   uint32_t tmpDelay = Delay;
206 
207   /* Add this code to indicate that local variable is not used */
208   ((void)tmp);
209 
210   /* Add a period to guaranty minimum wait */
211   if (tmpDelay < LL_MAX_DELAY)
212   {
213     tmpDelay++;
214   }
215 
216   while (tmpDelay != 0U)
217   {
218     if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
219     {
220       tmpDelay--;
221     }
222   }
223 }
224 
225 /**
226   * @}
227   */
228 
229 /** @addtogroup UTILS_EF_SYSTEM
230   *  @brief    System Configuration functions
231   *
232   @verbatim
233  ===============================================================================
234            ##### System Configuration functions #####
235  ===============================================================================
236     [..]
237          System, AHB and APB buses clocks configuration
238 
239          (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2, PCLK7 is
240              100000000 Hz.
241   @endverbatim
242   @internal
243              Depending on the device voltage range, the maximum frequency should be
244              adapted accordingly:
245 
246              (++) Table 1. HCLK clock frequency for STM32WBA devices
247              (++) +----------------------------------------------------------+
248              (++) | Latency           |       HCLK clock frequency (MHz)     |
249              (++) |                   |--------------------------------------|
250              (++) |                   |  voltage range 1  |  voltage range 2 |
251              (++) |                   |       1.2 V       |       1.1 V      |
252              (++) |-------------------|-------------------|------------------|
253              (++) |0 WS (1 CPU cycles)|   0 < HCLK <= 32  |  0 < HCLK <= 8   |
254              (++) |-------------------|-------------------|------------------|
255              (++) |1 WS (2 CPU cycles)|  32 < HCLK <= 64  |  25 < HCLK <= 16 |
256              (++) |-------------------|-------------------|------------------|
257              (++) |2 WS (3 CPU cycles)|  64 < HCLK <= 96  |  50 < HCLK <= 24 |
258              (++) |-------------------|-------------------|------------------|
259              (++) |3 WS (4 CPU cycles)|  96 < HCLK <= 100 |
260              (++) |-------------------|-------------------|
261 
262 
263   @endinternal
264   * @{
265   */
266 
267 /**
268   * @brief  This function sets directly SystemCoreClock CMSIS variable.
269   * @note   Variable can be calculated also through SystemCoreClockUpdate function.
270   * @param  HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro)
271   * @retval None
272   */
LL_SetSystemCoreClock(uint32_t HCLKFrequency)273 void LL_SetSystemCoreClock(uint32_t HCLKFrequency)
274 {
275   /* HCLK clock frequency */
276   SystemCoreClock = HCLKFrequency;
277 }
278 
279 
280 
281 /**
282   * @brief  This function configures system clock at maximum frequency with HSI as clock source of the PLL
283   * @note   The application need to ensure that PLL1, PLL2 and/or PLL3 are disabled.
284   * @note   Function is based on the following formula:
285   *         - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLR)
286   *         - PLL1M: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLL1VCO_input = HSI frequency / PLL1M)
287   *         - PLL1N: ensure that the VCO output frequency is between 128 and 544 MHz
288              (PLL1VCO_output = PLL1VCO_input * PLL1N)
289   *         - PLL1R: ensure that max frequency at 100 MHz is reached (PLL1VCO_output / PLL1R)
290   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
291   *                             the configuration information for the PLL.
292   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
293   *                             the configuration information for the BUS prescalers.
294   * @retval An ErrorStatus enumeration value:
295   *          - SUCCESS: Max frequency configuration done
296   *          - ERROR: Max frequency configuration not done
297   */
LL_PLL1_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)298 ErrorStatus LL_PLL1_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
299                                           LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
300 {
301   ErrorStatus status;
302   uint32_t pllfreq;
303 
304   /* Check if one of the PLL is enabled */
305   if (UTILS_PLL_IsBusy() == SUCCESS)
306   {
307     /* Calculate the new PLL output frequency */
308     pllfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct);
309 
310     /* Enable HSI if not enabled */
311     if (LL_RCC_HSI_IsReady() != 1U)
312     {
313       LL_RCC_HSI_Enable();
314       while (LL_RCC_HSI_IsReady() != 1U)
315       {
316         /* Wait for HSI ready */
317       }
318     }
319 
320     /* Configure PLL */
321     LL_RCC_PLL1_ConfigDomain_SYS(LL_RCC_PLL1SOURCE_HSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
322                                  UTILS_PLLInitStruct->PLLR);
323 
324     /* Enable PLL and switch system clock to PLL */
325     status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
326   }
327   else
328   {
329     /* Current PLL configuration cannot be modified */
330     status = ERROR;
331   }
332 
333   return status;
334 }
335 
336 /**
337   * @brief  This function configures system clock with HSE as clock source of the PLL
338   * @note   The application need to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled.
339   * @note   Function is based on the following formula:
340   *         - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLR)
341   *         - PLL1M: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLL1VCO_input = HSE frequency / PLL1M)
342   *         - PLL1N: ensure that the VCO output frequency is between 128 and 544 MHz
343              (PLL1VCO_output = PLL1VCO_input * PLL1N)
344   *         - PLL1R: ensure that max frequency at 100 MHz is reached (PLL1VCO_output / PLL1R)
345   * @param  HSEFrequency Value at 32000000
346   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
347   *                             the configuration information for the PLL.
348   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
349   *                             the configuration information for the BUS prescalers.
350   * @retval An ErrorStatus enumeration value:
351   *          - SUCCESS: Max frequency configuration done
352   *          - ERROR: Max frequency configuration not done
353   */
LL_PLL1_ConfigSystemClock_HSE(uint32_t HSEFrequency,LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)354 ErrorStatus LL_PLL1_ConfigSystemClock_HSE(uint32_t HSEFrequency,
355                                           LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
356                                           LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
357 {
358   ErrorStatus status;
359   uint32_t pllfreq;
360 
361   /* Check the parameters */
362   assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
363 
364   /* Check if one of the PLL is enabled */
365   if (UTILS_PLL_IsBusy() == SUCCESS)
366   {
367     /* Calculate the new PLL output frequency */
368     pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct);
369 
370     /* Enable HSE if not enabled */
371     if (LL_RCC_HSE_IsReady() != 1U)
372     {
373       /* Enable HSE */
374       LL_RCC_HSE_Enable();
375       while (LL_RCC_HSE_IsReady() != 1U)
376       {
377         /* Wait for HSE ready */
378       }
379     }
380 
381     /* Configure PLL */
382     LL_RCC_PLL1_ConfigDomain_SYS(LL_RCC_PLL1SOURCE_HSE, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
383                                  UTILS_PLLInitStruct->PLLR);
384 
385     /* Enable PLL and switch system clock to PLL */
386     status = UTILS_EnablePLLAndSwitchSystem(pllfreq, 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   * @}
399   */
400 
401 /**
402   * @}
403   */
404 
405 /**
406   * @brief  Update number of Flash wait states in line with new frequency and current
407             voltage range.
408   * @param  HCLK_Frequency  HCLK frequency
409   * @retval An ErrorStatus enumeration value:
410   *          - SUCCESS: Latency has been modified
411   *          - ERROR: Latency cannot be modified
412   */
LL_SetFlashLatency(uint32_t HCLK_Frequency)413 ErrorStatus LL_SetFlashLatency(uint32_t HCLK_Frequency)
414 {
415   ErrorStatus status = SUCCESS;
416   uint32_t latency;
417 
418   /* Frequency cannot be equal to 0 */
419   if (HCLK_Frequency == 0U)
420   {
421     status = ERROR;
422   }
423   else
424   {
425     if (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1)
426     {
427       if ((HCLK_Frequency > UTILS_SCALE1_LATENCY2_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY3_FREQ))
428       {
429         /* 96MHz < HCLK <= 100MHz => 3WS (4 CPU cycles) */
430         latency = LL_FLASH_LATENCY_3;
431       }
432       else if ((HCLK_Frequency > UTILS_SCALE1_LATENCY1_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY2_FREQ))
433       {
434         /* 64MHz < HCLK <= 96MHz => 2WS (3 CPU cycles) */
435         latency = LL_FLASH_LATENCY_2;
436       }
437       else if ((HCLK_Frequency > UTILS_SCALE1_LATENCY0_FREQ) && (HCLK_Frequency <= UTILS_SCALE1_LATENCY1_FREQ))
438       {
439         /* 32MHz < HCLK <= 64MHz  => 1WS (2 CPU cycles) */
440         latency = LL_FLASH_LATENCY_1;
441       }
442       else if (HCLK_Frequency <= UTILS_SCALE1_LATENCY0_FREQ)
443       {
444         /* HCLK <= 32MHz => 0WS (1 CPU cycle) */
445         latency = LL_FLASH_LATENCY_0;
446       }
447       else
448       {
449         status = ERROR;
450       }
451     }
452     else /* LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2 */
453     {
454       if ((HCLK_Frequency > UTILS_SCALE2_LATENCY0_FREQ) && (HCLK_Frequency <= UTILS_SCALE2_LATENCY1_FREQ))
455       {
456         /* 8MHz < HCLK <= 16MHz => 1WS (2 CPU cycles) */
457         latency = LL_FLASH_LATENCY_1;
458       }
459       else if (HCLK_Frequency <= UTILS_SCALE2_LATENCY0_FREQ)
460       {
461         /* HCLK <= 8MHz => 0WS (1 CPU cycle) */
462         latency = LL_FLASH_LATENCY_0;
463       }
464       else
465       {
466         status = ERROR;
467       }
468     }
469   }
470 
471   if (status == SUCCESS)
472   {
473     LL_FLASH_SetLatency(latency);
474 
475     /* Check that the new number of wait states is taken into account to access the Flash
476     memory by reading the FLASH_ACR register */
477     if (LL_FLASH_GetLatency() != latency)
478     {
479       status = ERROR;
480     }
481   }
482 
483   return status;
484 }
485 
486 /** @addtogroup UTILS_LL_Private_Functions
487   * @{
488   */
489 /**
490   * @brief  Function to check that PLL can be modified
491   * @param  PLL_InputFrequency  PLL input frequency (in Hz)
492   * @param  UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
493   *                             the configuration information for the PLL.
494   * @retval PLL output frequency (in Hz)
495   */
UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,const LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct)496 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, const LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct)
497 {
498   uint32_t pllfreq;
499 
500   /* Check the parameters */
501   assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
502   assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
503   assert_param(IS_LL_UTILS_PLLR_VALUE(UTILS_PLLInitStruct->PLLR));
504 
505   /* Check different PLL parameters according to RM                          */
506   /*  - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz.   */
507   pllfreq = PLL_InputFrequency / (UTILS_PLLInitStruct->PLLM);
508   assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq));
509 
510   /*  - PLLN: ensure that the VCO output frequency is between 128 and 544 MHz.*/
511   pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN);
512   assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq));
513 
514   /*  - PLLR: ensure that max frequency at 100 MHz is reached                   */
515   pllfreq = pllfreq / (UTILS_PLLInitStruct->PLLR);
516   assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq));
517 
518   return pllfreq;
519 }
520 
521 /**
522   * @brief  Function to check that PLL can be modified
523   * @retval An ErrorStatus enumeration value:
524   *          - SUCCESS: PLL modification can be done
525   *          - ERROR: PLL is busy
526   */
UTILS_PLL_IsBusy(void)527 static ErrorStatus UTILS_PLL_IsBusy(void)
528 {
529   ErrorStatus status = SUCCESS;
530 
531   /* Check if PLL1 is busy*/
532   if (LL_RCC_PLL1_IsReady() != 0U)
533   {
534     /* PLL configuration cannot be modified */
535     status = ERROR;
536   }
537 
538   return status;
539 }
540 
541 /**
542   * @brief  Function to enable PLL and switch system clock to PLL
543   * @param  SYSCLK_Frequency SYSCLK frequency
544   * @param  UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
545   *                             the configuration information for the BUS prescalers.
546   * @retval An ErrorStatus enumeration value:
547   *          - SUCCESS: No problem to switch system to PLL
548   *          - ERROR: Problem to switch system to PLL
549   */
UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)550 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,
551                                                   LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
552 {
553   ErrorStatus status = SUCCESS;
554   uint32_t hclk_frequency;
555 
556   assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider));
557   assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
558   assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider));
559   assert_param(IS_LL_UTILS_APB7_DIV(UTILS_ClkInitStruct->APB7CLKDivider));
560 
561   /* Calculate HCLK frequency */
562   hclk_frequency = __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider);
563 
564   /* Increasing the number of wait states because of higher CPU frequency */
565   if (SystemCoreClock < hclk_frequency)
566   {
567     /* Set FLASH latency to highest latency */
568     status = LL_SetFlashLatency(hclk_frequency);
569   }
570 
571   /* Update system clock configuration */
572   if (status == SUCCESS)
573   {
574     /* Enable PLL1 */
575     LL_RCC_PLL1_Enable();
576     LL_RCC_PLL1_EnableDomain_PLL1R();
577     while (LL_RCC_PLL1_IsReady() != 1U)
578     {
579       /* Wait for PLL ready */
580     }
581 
582     /* Sysclk activation on the main PLL */
583     LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
584     LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1R);
585     while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1R)
586     {
587       /* Wait for system clock switch to PLL */
588     }
589 
590     /* Set APB1, APB2 & APB7 prescaler*/
591     LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
592     LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider);
593     LL_RCC_SetAPB7Prescaler(UTILS_ClkInitStruct->APB7CLKDivider);
594   }
595 
596   /* Decreasing the number of wait states because of lower CPU frequency */
597   if (SystemCoreClock > hclk_frequency)
598   {
599     /* Set FLASH latency to lowest latency */
600     status = LL_SetFlashLatency(hclk_frequency);
601   }
602 
603   /* Update SystemCoreClock variable */
604   if (status == SUCCESS)
605   {
606     LL_SetSystemCoreClock(hclk_frequency);
607   }
608 
609   return status;
610 }
611 
612 /**
613   * @}
614   */
615 
616 /**
617   * @}
618   */
619 
620 /**
621   * @}
622   */
623 
624