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