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