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