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