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