1 /**
2 ******************************************************************************
3 * @file stm32u0xx_ll_utils.c
4 * @author MCD Application Team
5 * @brief UTILS LL module driver.
6 ******************************************************************************
7 * @attention
8 *
9 * Copyright (c) 2023 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 "stm32u0xx_ll_utils.h"
20 #include "stm32u0xx_ll_rcc.h"
21 #include "stm32u0xx_ll_system.h"
22 #include "stm32u0xx_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 STM32U0xx_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 56000000U /*!< Maximum frequency for system clock at power scale1, in Hz */
44 #define UTILS_MAX_FREQUENCY_SCALE2 18000000U /*!< Maximum frequency for system clock at power scale2, in Hz */
45
46 /* Defines used for PLL range */
47 #define UTILS_PLLVCO_INPUT_MIN 4000000U /*!< 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 FLASH latency according to HCLK Frequency */
53 #define UTILS_SCALE1_LATENCY1_FREQ 24000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
54 #define UTILS_SCALE1_LATENCY2_FREQ 48000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
55 #define UTILS_SCALE1_LATENCY3_FREQ 56000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */
56 #define UTILS_SCALE2_LATENCY1_FREQ 8000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */
57 #define UTILS_SCALE2_LATENCY2_FREQ 16000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */
58 #define UTILS_SCALE2_LATENCY3_FREQ 18000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 2 */
59
60 /* Defines used for HCLK frequency check */
61 #define UTILS_HCLK_MAX 56000000U /*!< HCLK frequency maximum at 64MHz */
62
63
64 /**
65 * @}
66 */
67
68 /* Private macros ------------------------------------------------------------*/
69 /** @addtogroup UTILS_LL_Private_Macros
70 * @{
71 */
72 #define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \
73 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \
74 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \
75 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \
76 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \
77 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \
78 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \
79 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \
80 || ((__VALUE__) == LL_RCC_SYSCLK_DIV_512))
81
82 #define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
83 || ((__VALUE__) == LL_RCC_APB1_DIV_2) \
84 || ((__VALUE__) == LL_RCC_APB1_DIV_4) \
85 || ((__VALUE__) == LL_RCC_APB1_DIV_8) \
86 || ((__VALUE__) == LL_RCC_APB1_DIV_16))
87
88 #define IS_LL_UTILS_HSI_DIV(__VALUE__) (((__VALUE__) == LL_RCC_HSI_DIV_1) \
89 || ((__VALUE__) == LL_RCC_HSI_DIV_2) \
90 || ((__VALUE__) == LL_RCC_HSI_DIV_4) \
91 || ((__VALUE__) == LL_RCC_HSI_DIV_8) \
92 || ((__VALUE__) == LL_RCC_HSI_DIV_16) \
93 || ((__VALUE__) == LL_RCC_HSI_DIV_32) \
94 || ((__VALUE__) == LL_RCC_HSI_DIV_64) \
95 || ((__VALUE__) == LL_RCC_HSI_DIV_128))
96
97 #define IS_LL_UTILS_PLLM_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLM_DIV_1) \
98 || ((__VALUE__) == LL_RCC_PLLM_DIV_2) \
99 || ((__VALUE__) == LL_RCC_PLLM_DIV_3) \
100 || ((__VALUE__) == LL_RCC_PLLM_DIV_4) \
101 || ((__VALUE__) == LL_RCC_PLLM_DIV_5) \
102 || ((__VALUE__) == LL_RCC_PLLM_DIV_6) \
103 || ((__VALUE__) == LL_RCC_PLLM_DIV_7) \
104 || ((__VALUE__) == LL_RCC_PLLM_DIV_8))
105
106 #define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((8 <= (__VALUE__)) && ((__VALUE__) <= 86))
107
108 #define IS_LL_UTILS_PLLR_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLR_DIV_2) \
109 || ((__VALUE__) == LL_RCC_PLLR_DIV_3) \
110 || ((__VALUE__) == LL_RCC_PLLR_DIV_4) \
111 || ((__VALUE__) == LL_RCC_PLLR_DIV_5) \
112 || ((__VALUE__) == LL_RCC_PLLR_DIV_6) \
113 || ((__VALUE__) == LL_RCC_PLLR_DIV_7) \
114 || ((__VALUE__) == LL_RCC_PLLR_DIV_8))
115
116 #define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__) ((UTILS_PLLVCO_INPUT_MIN <= (__VALUE__)) && \
117 ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX))
118
119 #define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__) ((UTILS_PLLVCO_OUTPUT_MIN <= (__VALUE__)) && \
120 ((__VALUE__) <= UTILS_PLLVCO_OUTPUT_MAX))
121
122 #define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) \
123 ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? \
124 ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \
125 ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2))
126
127 #define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \
128 || ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
129 /**
130 * @}
131 */
132 /* Private function prototypes -----------------------------------------------*/
133 /** @defgroup UTILS_LL_Private_Functions UTILS Private functions
134 * @{
135 */
136 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,
137 LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct);
138 static ErrorStatus UTILS_SetFlashLatency(uint32_t HCLKS_Frequency);
139 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,
140 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
141 static ErrorStatus UTILS_PLL_IsBusy(void);
142
143 /**
144 * @}
145 */
146
147 /* Exported functions --------------------------------------------------------*/
148 /** @addtogroup UTILS_LL_Exported_Functions
149 * @{
150 */
151
152 /** @addtogroup UTILS_LL_EF_DELAY
153 * @{
154 */
155 /**
156 * @brief This function configures the Cortex-M SysTick source to have 1ms time base.
157 * @note When a RTOS is used, it is recommended to avoid changing the Systick
158 * configuration by calling this function, for a delay use rather osDelay RTOS service.
159 * @param HCLKFrequency HCLK frequency in Hz
160 * @note HCLK frequency can be calculated thanks to RCC helper macro or function
161 @ref LL_RCC_GetSystemClocksFreq (HCLK_Frequency field)
162 * @retval None
163 */
LL_Init1msTick(uint32_t HCLKFrequency)164 void LL_Init1msTick(uint32_t HCLKFrequency)
165 {
166 /* Use frequency provided in argument */
167 LL_InitTick(HCLKFrequency, 1000);
168 }
169
170
171 /**
172 * @brief This function provides accurate delay (in milliseconds) based
173 * on SysTick counter flag
174 * @note When a RTOS is used, it is recommended to avoid using blocking delay
175 * and use rather osDelay service.
176 * @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which
177 * will configure Systick to 1ms
178 * @param Delay specifies the delay time length, in milliseconds.
179 * @retval None
180 */
LL_mDelay(uint32_t Delay)181 void LL_mDelay(uint32_t Delay)
182 {
183 __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
184 /* Add this code to indicate that local variable is not used */
185 ((void)tmp);
186
187 /* Add a period to guaranty minimum wait */
188 if (Delay < LL_MAX_DELAY)
189 {
190 Delay++;
191 }
192
193 while (Delay)
194 {
195 if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0)
196 {
197 Delay--;
198 }
199 }
200 }
201
202 /**
203 * @}
204 */
205
206 /** @addtogroup UTILS_EF_SYSTEM
207 * @brief System Configuration functions
208 *
209 @verbatim
210 ===============================================================================
211 ##### System Configuration functions #####
212 ===============================================================================
213 [..]
214 System, HCLK, AHB, and APB buses clocks configuration
215
216 (+) The maximum frequency of the SYSCLK, HCLK, and PCLK
217 is 640000000 Hz.
218
219 @endverbatim
220 @internal
221 Depending on the device voltage range, the maximum frequency should be
222 adapted accordingly:
223 (++) HCLK clock frequency for STM32U0xx device
224 (++) +--------------------------------------------------------+
225 (++) | Latency | HCLKS 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 < HCLKS <= 24 | 0 < HCLKS <= 8 |
231 (++) |-----------------|-------------------|------------------|
232 (++) |1WS(2 CPU cycles)| 24< HCLKS <= 48 | 8 < HCLKS <= 16 |
233 (++) |-----------------|-------------------|------------------|
234 (++) |2WS(3 CPU cycles)| 48< HCLKS <= 56 | 16< HCLKS <= 18 |
235 (++) +--------------------------------------------------------+
236 @endinternal
237 * @{
238 */
239
240 /**
241 * @brief This function sets directly SystemCoreClock CMSIS variable.
242 * @note Variable can be calculated also through SystemCoreClockUpdate function.
243 * @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro)
244 * @retval None
245 */
LL_SetSystemCoreClock(uint32_t HCLKFrequency)246 void LL_SetSystemCoreClock(uint32_t HCLKFrequency)
247 {
248 /* HCLK clock frequency */
249 SystemCoreClock = HCLKFrequency;
250 }
251
252 /**
253 * @brief This function configures system clock with MSI as clock source of the PLL
254 * @note The application needs to ensure that PLL is disabled
255 * @note The application needs to ensure that PLL configuration is valid
256 * @note The application needs to ensure that MSI range is valid.
257 * @note The application needs to ensure that BUS prescalers are valid
258 * @note Function is based on the following formula:
259 * - PLL output frequency = (((MSI frequency / PLLM) * PLLN) / PLLR)
260 * - PLLM:ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = MSI frequency / PLLM)
261 * - PLLN:ensure that the VCO output frequency is between 96 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
262 * - PLLR:ensure that max frequency at 122000000 Hz is reached (PLLVCO_output / PLLR)
263 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
264 * the configuration information for the PLL.
265 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
266 * the configuration information for the BUS prescalers.
267 * @retval An ErrorStatus enumeration value:
268 * - SUCCESS: Max frequency configuration done
269 * - ERROR: Max frequency configuration not done
270 */
LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)271 ErrorStatus LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
272 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
273 {
274 ErrorStatus status = SUCCESS;
275 uint32_t pllrfreq = 0U;
276 uint32_t msi_range = 0U;
277
278 /* Check if one of the PLL is enabled */
279 if (UTILS_PLL_IsBusy() == SUCCESS)
280 {
281 /* Get the current MSI range & check coherency */
282 msi_range = LL_RCC_MSI_GetRange();
283 switch (msi_range)
284 {
285 case LL_RCC_MSIRANGE_0: /* MSI = 100 KHz */
286 case LL_RCC_MSIRANGE_1: /* MSI = 200 KHz */
287 case LL_RCC_MSIRANGE_2: /* MSI = 400 KHz */
288 case LL_RCC_MSIRANGE_3: /* MSI = 800 KHz */
289 case LL_RCC_MSIRANGE_4: /* MSI = 1 MHz */
290 case LL_RCC_MSIRANGE_5: /* MSI = 2 MHz */
291 /* PLLVCO input frequency can not in the range from 4 to 16 MHz*/
292 status = ERROR;
293 break;
294
295 case LL_RCC_MSIRANGE_6: /* MSI = 4 MHz */
296 case LL_RCC_MSIRANGE_7: /* MSI = 8 MHz */
297 case LL_RCC_MSIRANGE_8: /* MSI = 16 MHz */
298 case LL_RCC_MSIRANGE_9: /* MSI = 24 MHz */
299 case LL_RCC_MSIRANGE_10: /* MSI = 32 MHz */
300 case LL_RCC_MSIRANGE_11: /* MSI = 48 MHz */
301 default:
302 break;
303 }
304
305 /* PLL is ready, MSI range is valid and HCLK frequency is coherent
306 Main PLL configuration and activation */
307 if (status != ERROR)
308 {
309 /* Calculate the new PLL output frequency & verify all PLL stages are correct (VCO input ranges,
310 VCO output ranges & SYSCLK max) when assert activated */
311 pllrfreq = UTILS_GetPLLOutputFrequency(__LL_RCC_CALC_MSI_FREQ(LL_RCC_MSIRANGESEL_RUN, msi_range),
312 UTILS_PLLInitStruct);
313
314 /* Enable MSI if not enabled */
315 if (LL_RCC_MSI_IsReady() != 1U)
316 {
317 LL_RCC_MSI_Enable();
318 while ((LL_RCC_MSI_IsReady() != 1U))
319 {
320 /* Wait for MSI ready */
321 }
322 }
323
324 /* Configure PLL domain SYS */
325 LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
326 UTILS_PLLInitStruct->PLLR);
327
328 /* Enable PLL and switch system clock to PLL - latency check done internally */
329 status = UTILS_EnablePLLAndSwitchSystem(pllrfreq, UTILS_ClkInitStruct);
330 }
331 }
332 else
333 {
334 /* Current PLL configuration cannot be modified */
335 status = ERROR;
336 }
337
338 return status;
339 }
340
341 /**
342 * @brief This function configures system clock at maximum frequency with HSI as clock source of the PLL
343 * @note The application need to ensure that PLL is disabled
344 * @note The application needs to ensure that PLL configuration is valid
345 * @note The application needs to ensure that BUS prescalers are valid
346 * @note Function is based on the following formula:
347 * - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLR)
348 * - PLLM:ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSI frequency / PLLM)
349 * - PLLN:ensure that the VCO output frequency is between 96 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
350 * - PLLR:ensure that max frequency at 122000000 Hz is reach (PLLVCO_output / PLLR)
351 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
352 * the configuration information for the PLL.
353 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
354 * the configuration information for the BUS prescalers.
355 * @retval An ErrorStatus enumeration value:
356 * - SUCCESS: Max frequency configuration done
357 * - ERROR: Max frequency configuration not done
358 */
LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)359 ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
360 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
361 {
362 ErrorStatus status = SUCCESS;
363 uint32_t pllrfreq = 0U;
364
365 /* Check if one of the PLL is enabled */
366 if (UTILS_PLL_IsBusy() == SUCCESS)
367 {
368 /* Calculate the new PLL output frequency */
369 pllrfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct);
370
371 /* Enable HSI if not enabled */
372 if (LL_RCC_HSI_IsReady() != 1U)
373 {
374 LL_RCC_HSI_Enable();
375 while (LL_RCC_HSI_IsReady() != 1U)
376 {
377 /* Wait for HSI ready */
378 }
379 }
380
381 /* Configure PLL */
382 LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
383 UTILS_PLLInitStruct->PLLR);
384
385 /* Enable PLL and switch system clock to PLL */
386 status = UTILS_EnablePLLAndSwitchSystem(pllrfreq, UTILS_ClkInitStruct);
387 }
388 else
389 {
390 /* Current PLL configuration cannot be modified */
391 status = ERROR;
392 }
393
394 return status;
395 }
396
397 /**
398 * @brief This function configures system clock with HSE as clock source of the PLL
399 * @note The application need to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled.
400 * @note The application needs to ensure that PLL configuration is valid
401 * @note The application needs to ensure that BUS prescalers are valid
402 * @note Function is based on the following formula:
403 * - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLR)
404 * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSE frequency / PLLM)
405 * - PLLN: ensure that the VCO output frequency is between 96 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
406 * - PLLR: ensure that max frequency at 122000000 Hz is reached (PLLVCO_output / PLLR)
407 * @param HSEBypass This parameter can be one of the following values:
408 * @arg @ref LL_UTILS_HSEBYPASS_ON
409 * @arg @ref LL_UTILS_HSEBYPASS_OFF
410 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
411 * the configuration information for the PLL.
412 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
413 * the configuration information for the BUS prescalers.
414 * @retval An ErrorStatus enumeration value:
415 * - SUCCESS: Max frequency configuration done
416 * - ERROR: Max frequency configuration not done
417 */
LL_PLL_ConfigSystemClock_HSE(uint32_t HSEBypass,LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)418 ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEBypass, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
419 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
420 {
421 ErrorStatus status = SUCCESS;
422 uint32_t pllrfreq = 0U;
423
424 /* Check the parameters */
425 assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
426
427 /* Check if one of the PLL is enabled */
428 if (UTILS_PLL_IsBusy() == SUCCESS)
429 {
430 /* Calculate the new PLL output frequency */
431 pllrfreq = UTILS_GetPLLOutputFrequency(HSE_VALUE, UTILS_PLLInitStruct);
432
433 /* Enable HSE if not enabled */
434 if (LL_RCC_HSE_IsReady() != 1U)
435 {
436 /* Check if need to enable HSE bypass feature or not */
437 if (HSEBypass == LL_UTILS_HSEBYPASS_ON)
438 {
439 LL_RCC_HSE_EnableBypass();
440 }
441 else
442 {
443 LL_RCC_HSE_DisableBypass();
444 }
445
446 /* Enable HSE */
447 LL_RCC_HSE_Enable();
448 while (LL_RCC_HSE_IsReady() != 1U)
449 {
450 /* Wait for HSE ready */
451 }
452 }
453
454 /* Configure PLL */
455 LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
456 UTILS_PLLInitStruct->PLLR);
457
458 /* Enable PLL and switch system clock to PLL */
459 status = UTILS_EnablePLLAndSwitchSystem(pllrfreq, UTILS_ClkInitStruct);
460 }
461 else
462 {
463 /* Current PLL configuration cannot be modified */
464 status = ERROR;
465 }
466
467 return status;
468 }
469
470
471 /**
472 * @}
473 */
474
475
476 /**
477 * @}
478 */
479
480 /** @addtogroup UTILS_LL_Private_Functions
481 * @{
482 */
483 /**
484 * @brief Update number of Flash wait states in line with new frequency and current
485 voltage range.
486 * @param HCLK_Frequency HCLK frequency
487 * @retval An ErrorStatus enumeration value:
488 * - SUCCESS: Latency has been modified
489 * - ERROR: Latency cannot be modified
490 */
UTILS_SetFlashLatency(uint32_t HCLK_Frequency)491 static ErrorStatus UTILS_SetFlashLatency(uint32_t HCLK_Frequency)
492 {
493 ErrorStatus status = SUCCESS;
494
495 uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */
496
497 /* Frequency cannot be equal to 0 */
498 if (HCLK_Frequency == 0U)
499 {
500 status = ERROR;
501 }
502 else
503 {
504 if (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1)
505 {
506 if (HCLK_Frequency <= UTILS_SCALE1_LATENCY1_FREQ)
507 {
508 /* HCLKS_Frequency <= 24MHz default LL_FLASH_LATENCY_0 0WS */
509 latency = LL_FLASH_LATENCY_0;
510 }
511 else if (HCLK_Frequency <= UTILS_SCALE1_LATENCY2_FREQ)
512 {
513 /* 24 < HCLKS <= 48 => 1WS (1 CPU cycles) */
514 latency = LL_FLASH_LATENCY_1;
515 }
516 else if (HCLK_Frequency <= UTILS_SCALE1_LATENCY3_FREQ)
517 {
518 /* 48 < HCLK <= 56 => 2WS (3 CPU cycles) */
519 latency = LL_FLASH_LATENCY_2;
520 }
521 else
522 {
523 status = ERROR;
524 }
525 }
526 else if (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2)
527 {
528 if (HCLK_Frequency <= UTILS_SCALE2_LATENCY1_FREQ)
529 {
530 /* HCLK < 8 => 0WS (1 CPU cycles) */
531 latency = LL_FLASH_LATENCY_0;
532 }
533 else if (HCLK_Frequency <= UTILS_SCALE2_LATENCY2_FREQ)
534 {
535 /* 8 < HCLK <= 16 => 1WS (2 CPU cycles) */
536 latency = LL_FLASH_LATENCY_1;
537 }
538 else if (HCLK_Frequency <= UTILS_SCALE2_LATENCY3_FREQ)
539 {
540 /* 16 < HCLK <= 18 => 2WS (3 CPU cycles) */
541 latency = LL_FLASH_LATENCY_2;
542 }
543 else
544 {
545 status = ERROR;
546 }
547 }
548 /* else HCLK_Frequency <= 10MHz default LL_FLASH_LATENCY_0 0WS */
549 LL_FLASH_SetLatency(latency);
550
551 /* Check that the new number of wait states is taken into account to access the Flash
552 memory by reading the FLASH_ACR register */
553 if (LL_FLASH_GetLatency() != latency)
554 {
555 status = ERROR;
556 }
557 }
558 return status;
559 }
560
LL_SetFlashLatency(uint32_t HCLK_Frequency)561 ErrorStatus LL_SetFlashLatency(uint32_t HCLK_Frequency)
562 {
563 return UTILS_SetFlashLatency(HCLK_Frequency);
564 }
565
566 /**
567 * @brief Function to check that PLL can be modified
568 * @param PLL_InputFrequency PLL input frequency (in Hz)
569 * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
570 * the configuration information for the PLL.
571 * @retval PLL output frequency (in Hz)
572 */
UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,LL_UTILS_PLLInitTypeDef * UTILS_PLLInitStruct)573 static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct)
574 {
575 uint32_t pllfreq = 0U;
576
577 /* Check the parameters */
578 assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
579 assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
580 assert_param(IS_LL_UTILS_PLLR_VALUE(UTILS_PLLInitStruct->PLLR));
581
582 /* Check different PLL parameters according to RM */
583 /* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz. */
584 pllfreq = PLL_InputFrequency / (((UTILS_PLLInitStruct->PLLM >> RCC_PLLCFGR_PLLM_Pos) + 1U));
585 assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq));
586
587 /* - PLLN: ensure that the VCO output frequency is between 96 and 344 MHz.*/
588 pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN & (RCC_PLLCFGR_PLLN >> RCC_PLLCFGR_PLLN_Pos));
589 assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq));
590
591 /* - PLLR: ensure that max frequency at 64000000 Hz is reached */
592 pllfreq = pllfreq / ((UTILS_PLLInitStruct->PLLR >> RCC_PLLCFGR_PLLR_Pos) + 1U);
593 assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq));
594
595 return pllfreq;
596 }
597
598 /**
599 * @brief Function to check that PLL can be modified
600 * @retval An ErrorStatus enumeration value:
601 * - SUCCESS: PLL modification can be done
602 * - ERROR: PLL is busy
603 */
UTILS_PLL_IsBusy(void)604 static ErrorStatus UTILS_PLL_IsBusy(void)
605 {
606 ErrorStatus status = SUCCESS;
607
608 /* Check if PLL is busy*/
609 if (LL_RCC_PLL_IsReady() != 0U)
610 {
611 /* PLL configuration cannot be modified */
612 status = ERROR;
613 }
614 return status;
615 }
616
617 /**
618 * @brief Function to enable PLL and switch system clock to PLL
619 * @param SYSCLK_Frequency SYSCLK frequency
620 * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
621 * the configuration information for the BUS prescalers.
622 * @retval An ErrorStatus enumeration value:
623 * - SUCCESS: No problem to switch system to PLL
624 * - ERROR: Problem to switch system to PLL
625 */
UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,LL_UTILS_ClkInitTypeDef * UTILS_ClkInitStruct)626 static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency,
627 LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
628 {
629 ErrorStatus status = SUCCESS;
630 uint32_t hclk_frequency ;
631
632 assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider));
633 assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
634
635 /* Calculate HCLK frequency */
636 hclk_frequency = __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider);
637
638 /* Increasing the number of wait states because of higher CPU frequency */
639 if (SystemCoreClock < hclk_frequency)
640 {
641 /* Set FLASH latency to highest latency */
642 status = UTILS_SetFlashLatency(hclk_frequency);
643 }
644
645 /* Update system clock configuration */
646 if (status == SUCCESS)
647 {
648 /* Enable PLL */
649 LL_RCC_PLL_Enable();
650 LL_RCC_PLL_EnableDomain_SYS();
651 while (LL_RCC_PLL_IsReady() != 1U)
652 {
653 /* Wait for PLL ready */
654 }
655
656 /* Sysclk activation on the main PLL */
657 LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
658 LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
659 while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
660 {
661 /* Wait for system clock switch to PLL */
662 }
663
664 /* Set APB1 prescaler*/
665 LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
666 }
667
668 /* Decreasing the number of wait states because of lower CPU frequency */
669 if (SystemCoreClock > hclk_frequency)
670 {
671 /* Set FLASH latency to lowest latency */
672 status = UTILS_SetFlashLatency(hclk_frequency);
673 }
674
675 /* Update SystemCoreClock variable */
676 if (status == SUCCESS)
677 {
678 LL_SetSystemCoreClock(hclk_frequency);
679 }
680
681 return status;
682 }
683
684 /**
685 * @}
686 */
687
688
689 /**
690 * @}
691 */
692
693 /**
694 * @}
695 */
696