1 /**
2   ******************************************************************************
3   * @file    stm32l5xx_hal_rcc.c
4   * @author  MCD Application Team
5   * @brief   RCC HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Reset and Clock Control (RCC) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + Peripheral Control functions
10   *
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2019 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file in
18   * the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   ******************************************************************************
21   @verbatim
22   ==============================================================================
23                       ##### RCC specific features #####
24   ==============================================================================
25     [..]
26       After reset the device is running from Multiple Speed Internal oscillator
27       (4 MHz) with Flash 0 wait state. I-Cache is disabled, and all peripherals
28       are off except internal SRAMs, Flash and JTAG.
29 
30       (+) There is no prescaler on High speed (AHBs) and Low speed (APBs) buses:
31           all peripherals mapped on these buses are running at MSI speed.
32       (+) The clock for all peripherals is switched off, except the SRAM and FLASH.
33       (+) All GPIOs are in analog mode, except the JTAG pins which
34           are assigned to be used for debug purpose.
35 
36     [..]
37       Once the device is started from reset, the user application has to:
38       (+) Configure the clock source to be used to drive the System clock
39           (if the application needs higher frequency/performance)
40       (+) Configure the System clock frequency and Flash settings
41       (+) Configure the AHB and APB buses prescalers
42       (+) Enable the clock for the peripheral(s) to be used
43       (+) Configure the clock source(s) for peripherals which clocks are not
44           derived from the System clock (SAIx, RTC, ADC, USB FS/SDMMC1/RNG, FDCAN)
45 
46   @endverbatim
47   ******************************************************************************
48   */
49 
50 /* Includes ------------------------------------------------------------------*/
51 #include "stm32l5xx_hal.h"
52 
53 /** @addtogroup STM32L5xx_HAL_Driver
54   * @{
55   */
56 
57 /** @defgroup RCC RCC
58   * @brief RCC HAL module driver
59   * @{
60   */
61 
62 #ifdef HAL_RCC_MODULE_ENABLED
63 
64 /* Private typedef -----------------------------------------------------------*/
65 /* Private define ------------------------------------------------------------*/
66 /** @defgroup RCC_Private_Constants RCC Private Constants
67   * @{
68   */
69 #define LSI_TIMEOUT_VALUE          7UL     /* 7 ms (maximum 6ms + 1) */
70 #define HSI48_TIMEOUT_VALUE        2UL     /* 2 ms (minimum Tick + 1) */
71 #define PLL_TIMEOUT_VALUE          2UL     /* 2 ms (minimum Tick + 1) */
72 #define CLOCKSWITCH_TIMEOUT_VALUE  5000UL  /* 5 s    */
73 /**
74   * @}
75   */
76 
77 /* Private macro -------------------------------------------------------------*/
78 /** @defgroup RCC_Private_Macros RCC Private Macros
79   * @{
80   */
81 #define __MCO1_CLK_ENABLE()   __HAL_RCC_GPIOA_CLK_ENABLE()
82 #define MCO1_GPIO_PORT        GPIOA
83 #define MCO1_PIN              GPIO_PIN_8
84 /**
85   * @}
86   */
87 
88 /* Private variables ---------------------------------------------------------*/
89 
90 /* Private function prototypes -----------------------------------------------*/
91 /** @defgroup RCC_Private_Functions RCC Private Functions
92   * @{
93   */
94 static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange);
95 static uint32_t          RCC_GetSysClockFreqFromPLLSource(void);
96 /**
97   * @}
98   */
99 
100 /* Exported functions --------------------------------------------------------*/
101 
102 /** @defgroup RCC_Exported_Functions RCC Exported Functions
103   * @{
104   */
105 
106 /** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions
107   *  @brief    Initialization and Configuration functions
108   *
109   @verbatim
110  ===============================================================================
111            ##### Initialization and de-initialization functions #####
112  ===============================================================================
113     [..]
114       This section provides functions allowing to configure the internal and external oscillators
115       (HSE, HSI, LSE, MSI, LSI, PLL, CSS and MCO) and the System buses clocks (SYSCLK, AHB, APB1
116        and APB2).
117 
118     [..] Internal/external clock and PLL configuration
119          (+) HSI (high-speed internal): 16 MHz factory-trimmed RC used directly or through
120              the PLL as System clock source.
121 
122          (+) MSI (Multiple Speed Internal): Its frequency is software trimmable from 100KHz to 48MHz.
123              It can be used to generate the clock for the USB FS (48 MHz).
124              The number of flash wait states is automatically adjusted when MSI range is updated with
125              HAL_RCC_OscConfig() and the MSI is used as System clock source.
126 
127          (+) LSI (low-speed internal): 32 KHz low consumption RC used as IWDG and/or RTC
128              clock source.
129 
130          (+) HSE (high-speed external): 4 to 48 MHz crystal oscillator used directly or
131              through the PLL as System clock source. Can be used also optionally as RTC clock source.
132 
133          (+) LSE (low-speed external): 32.768 KHz oscillator used optionally as RTC clock source.
134 
135          (+) PLL (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
136            (++) The first output is used to generate the high speed system clock (up to 110 MHz).
137            (++) The second output is used to generate the clock for the USB FS (48 MHz),
138                 the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz).
139            (++) The third output is used to generate an accurate clock to achieve
140                 high-quality audio performance on SAI interface.
141 
142          (+) PLLSAI1 (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
143            (++) The first output is used to generate the ADCs clock.
144            (++) The second output is used to generate the clock for the USB FS (48 MHz),
145                 the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz).
146            (++) The third output is used to generate an accurate clock to achieve
147                 high-quality audio performance on SAI interface.
148 
149          (+) PLLSAI2 (clocked by HSI, HSE or MSI) providing an independent output clock:
150            (++) The output is used to generate an accurate clock to achieve
151                 high-quality audio performance on SAI interface.
152 
153          (+) CSS (Clock security system): once enabled, if a HSE clock failure occurs
154             (HSE used directly or through PLL as System clock source), the System clock
155              is automatically switched to HSI and an interrupt is generated.
156              The interrupt is linked to the Cortex-M33 NMI (non-maskable interrupt)
157              exception vector.
158 
159          (+) CSS on LSE (Clock security system on LSE): once enabled for RTC, if a LSE clock
160              failure occurs it is not supplied anymore to the RTC. If the MSI was used in
161              PLL-mode, this mode is disabled. The CSS on LSE failure is detected by a tamper event.
162 
163          (+) MCO (microcontroller clock output): used to output LSI, LSE, System clock, HSI, HSI48,
164              HSE, main PLL clock or MSI (through a configurable prescaler) on PA8 pin.
165 
166     [..] System, AHB and APB buses clocks configuration
167          (+) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI,
168              HSE and main PLL.
169              The AHB clock (HCLK) is derived from System clock through configurable
170              prescaler and used to clock the CPU, memory and peripherals mapped
171              on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived
172              from AHB clock through configurable prescalers and used to clock
173              the peripherals mapped on these buses. You can use
174              "HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks.
175 
176          -@- All the peripheral clocks are derived from the System clock (SYSCLK) except:
177 
178            (+@) SAI: the SAI clock can be derived either from a specific PLL (PLLSAI1) or (PLLSAI2) or
179                 from an external clock mapped on the SAI_CKIN pin.
180                 You have to use HAL_RCCEx_PeriphCLKConfig() function to configure this clock.
181            (+@) RTC: the RTC clock can be derived either from the LSI, LSE or HSE clock
182                 divided by 2 to 31.
183                 You have to use __HAL_RCC_RTC_ENABLE() and HAL_RCCEx_PeriphCLKConfig() function
184                 to configure this clock.
185            (+@) USB FS, SDMMC1 and RNG: USB FS requires a frequency equal to 48 MHz
186                 to work correctly, while the SDMMC1 and RNG peripherals require a frequency
187                 equal or lower than to 48 MHz. This clock is derived of the main PLL or PLLSAI1
188                 through PLLQ divider. You have to enable the peripheral clock and use
189                 HAL_RCCEx_PeriphCLKConfig() function to configure this clock.
190            (+@) IWDG clock which is always the LSI clock.
191 
192 
193          (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 110 MHz.
194              The clock source frequency should be adapted depending on the device voltage range
195              as listed in the Reference Manual "Clock source frequency versus voltage scaling" chapter.
196 
197   @endverbatim
198   @internal
199              Depending on the device voltage range, the maximum frequency should be
200              adapted accordingly:
201 
202              (++) Table 1. HCLK clock frequency for STM32L5 devices
203              (++) +---------------------------------------------------------------------------+
204              (++) | Latency         |                 HCLK clock frequency (MHz)              |
205              (++) |                 |---------------------------------------------------------|
206              (++) |                 |  voltage range 0  |  voltage range 1 | voltage range 2  |
207              (++) |-----------------|-------------------|------------------|------------------|
208              (++) |0WS(1 CPU cycles)|   0 < HCLK <= 20  |  0 < HCLK <= 8   |  0 < HCLK <= 8   |
209              (++) |-----------------|-------------------|------------------|------------------|
210              (++) |1WS(2 CPU cycles)|  20 < HCLK <= 40  |  20 < HCLK <= 40 |  8 < HCLK <= 16  |
211              (++) |-----------------|-------------------|------------------|------------------|
212              (++) |2WS(3 CPU cycles)|  40 < HCLK <= 60  |  40 < HCLK <= 60 | 16 < HCLK <= 26  |
213              (++) |-----------------|-------------------|------------------|------------------|
214              (++) |3WS(4 CPU cycles)|  60 < HCLK <= 80  |  60 < HCLK <= 80 |                  |
215              (++) |-----------------|-------------------|------------------|------------------|
216              (++) |4WS(5 CPU cycles)|  80 < HCLK <= 100 |                  |                  |
217              (++) |-----------------|-------------------|------------------|------------------|
218              (++) |5WS(6 CPU cycles)| 100 < HCLK <= 110 |                  |                  |
219              (++) +---------------------------------------------------------------------------+
220 
221   @endinternal
222   * @{
223   */
224 
225 /**
226   * @brief  Reset the RCC clock configuration to the default reset state.
227   * @note   The default reset state of the clock configuration is given below:
228   *            - MSI ON and used as system clock source
229   *            - HSE, HSI, HSI48, LSI, LSE, PLL, PLLSAI1 and PLLISAI2 OFF
230   *            - AHB, APB1 and APB2 prescaler set to 1.
231   *            - CSS, MCO1 OFF
232   *            - All interrupts disabled
233   *            - All interrupt and reset flags cleared
234   * @note   This function doesn't modify the configuration of the
235   *            - Peripheral clocks source selection
236   * @note   The SystemCoreClock CMSIS variable is used to store System Clock Frequency
237   *         and is updated by this function
238   * @retval HAL status
239   */
HAL_RCC_DeInit(void)240 HAL_StatusTypeDef HAL_RCC_DeInit(void)
241 {
242   uint32_t   tickstart;
243   FlagStatus pwrclkchanged = RESET;
244 
245   /* Set MSION bit */
246   SET_BIT(RCC->CR, RCC_CR_MSION);
247 
248   /* Insure MSIRDY bit is set before writing default MSIRANGE value */
249   /* Get start tick */
250   tickstart = HAL_GetTick();
251 
252   /* Wait till MSI is ready */
253   while (READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
254   {
255     if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
256     {
257       /* New check to avoid false timeout detection in case of preemption */
258       if (READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
259       {
260         return HAL_TIMEOUT;
261       }
262     }
263   }
264 
265   /* Set MSIRANGE default value */
266   MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6);
267 
268   /* Reset CFGR register (MSI is selected as system clock source) */
269   CLEAR_REG(RCC->CFGR);
270 
271   /* Insure MSI selected as system clock source */
272   /* Get start tick */
273   tickstart = HAL_GetTick();
274 
275   /* Update the SystemCoreClock global variable for MSI as system clock source */
276   SystemCoreClock = MSI_VALUE;
277 
278   /* Configure the source of time base considering new system clock settings  */
279   if (HAL_InitTick(uwTickPrio) != HAL_OK)
280   {
281     return HAL_ERROR;
282   }
283 
284   /* Wait till system clock source is ready */
285   while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_SYSCLKSOURCE_STATUS_MSI)
286   {
287     if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
288     {
289       /* New check to avoid false timeout detection in case of preemption */
290       if (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_SYSCLKSOURCE_STATUS_MSI)
291       {
292         return HAL_TIMEOUT;
293       }
294     }
295   }
296 
297   /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */
298   CLEAR_BIT(RCC->CR, RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON | RCC_CR_HSIASFS | RCC_CR_PLLON |
299             RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON);
300 
301   /* Insure PLLRDY, PLLSAI1RDY and PLLSAI2RDY (if present) are reset */
302   /* Get start tick */
303   tickstart = HAL_GetTick();
304 
305 #if defined(RCC_PLLSAI2_SUPPORT)
306 
307   while (READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U)
308   {
309     if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
310     {
311       /* New check to avoid false timeout detection in case of preemption */
312       if (READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U)
313       {
314         return HAL_TIMEOUT;
315       }
316     }
317   }
318 
319 #else
320 
321   while (READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U)
322   {
323     if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
324     {
325       /* New check to avoid false timeout detection in case of preemption */
326       if (READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U)
327       {
328         return HAL_TIMEOUT;
329       }
330     }
331   }
332 
333 #endif /* RCC_PLLSAI2_SUPPORT */
334 
335   /* Reset PLLCFGR register */
336   CLEAR_REG(RCC->PLLCFGR);
337   SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4);
338 
339   /* Reset PLLSAI1CFGR register */
340   CLEAR_REG(RCC->PLLSAI1CFGR);
341   SET_BIT(RCC->PLLSAI1CFGR,  RCC_PLLSAI1CFGR_PLLSAI1N_4);
342 
343   /* Reset PLLSAI2CFGR register */
344   CLEAR_REG(RCC->PLLSAI2CFGR);
345   SET_BIT(RCC->PLLSAI2CFGR,  RCC_PLLSAI2CFGR_PLLSAI2N_4);
346 
347   /* Reset LSION bit */
348   CLEAR_BIT(RCC->CSR, RCC_CSR_LSION);
349 
350   /* Insure LSIRDY bit is reset before LSIPRE bit reset */
351   /* Get start tick */
352   tickstart = HAL_GetTick();
353 
354   /* Wait till LSI is disabled */
355   while (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
356   {
357     if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
358     {
359       /* New check to avoid false timeout detection in case of preemption */
360       if (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
361       {
362         return HAL_TIMEOUT;
363       }
364     }
365   }
366 
367   /* Reset LSIPRE bit */
368   CLEAR_BIT(RCC->CSR, RCC_CSR_LSIPRE);
369 
370   /* Reset HSI48ON bit */
371   CLEAR_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON);
372 
373   /* Reset HSEBYP bit */
374   CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
375 
376   /* Disable all interrupts */
377   CLEAR_REG(RCC->CIER);
378 
379   /* Clear all interrupt flags */
380   WRITE_REG(RCC->CICR, 0xFFFFFFFFU);
381 
382   /* Clear all reset flags */
383   SET_BIT(RCC->CSR, RCC_CSR_RMVF);
384 
385   /* Reset LSEON/LSESYSON/LSEBYP in Backup domain register */
386   /* Requires to enable write access to Backup Domain if necessary */
387   if (HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN))
388   {
389     __HAL_RCC_PWR_CLK_ENABLE();
390     pwrclkchanged = SET;
391   }
392 
393   if (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
394   {
395     /* Enable write access to Backup domain */
396     SET_BIT(PWR->CR1, PWR_CR1_DBP);
397   }
398 
399   /* Reset LSEON/LSEBYP/LSESYSEN bit */
400   CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON);
401   CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP | RCC_BDCR_LSESYSEN);
402 
403   /* Restore clock configuration if changed */
404   if (pwrclkchanged == SET)
405   {
406     __HAL_RCC_PWR_CLK_DISABLE();
407   }
408 
409   return HAL_OK;
410 }
411 
412 /**
413   * @brief  Initialize the RCC Oscillators according to the specified parameters in the
414   *         RCC_OscInitTypeDef.
415   * @param  RCC_OscInitStruct  pointer to an RCC_OscInitTypeDef structure that
416   *         contains the configuration information for the RCC Oscillators.
417   * @note   The PLL is not disabled when used as system clock.
418   * @note   Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
419   *         supported by this macro. User should request a transition to LSE Off
420   *         first and then LSE On or LSE Bypass.
421   * @note   Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
422   *         supported by this macro. User should request a transition to HSE Off
423   *         first and then HSE On or HSE Bypass.
424   * @note   The SystemCoreClock CMSIS variable is used to store System Clock Frequency
425   *         and is updated by this function in case of simple MSI range update when MSI
426   *         used as system clock.
427   * @retval HAL status
428   */
HAL_RCC_OscConfig(RCC_OscInitTypeDef * RCC_OscInitStruct)429 HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
430 {
431   uint32_t tickstart;
432   HAL_StatusTypeDef status;
433   uint32_t sysclk_source, pll_config;
434 
435   /* Check Null pointer */
436   if (RCC_OscInitStruct == NULL)
437   {
438     return HAL_ERROR;
439   }
440 
441   /* Check the parameters */
442   assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
443 
444   sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE();
445   pll_config = __HAL_RCC_GET_PLL_OSCSOURCE();
446 
447   /*----------------------------- MSI Configuration --------------------------*/
448   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
449   {
450     /* Check the parameters */
451     assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState));
452     assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue));
453     assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange));
454 
455     /* Check if MSI is used as system clock or as PLL source when PLL is selected as system clock */
456     if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI) ||
457         ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_MSI)))
458     {
459       if ((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF))
460       {
461         return HAL_ERROR;
462       }
463 
464       /* Otherwise, just the calibration and MSI range change are allowed */
465       else
466       {
467         /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
468            must be correctly programmed according to the frequency of the CPU clock
469            (HCLK) and the supply voltage of the device. */
470         if (RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE())
471         {
472           /* First increase number of wait states update if necessary */
473           if (RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
474           {
475             return HAL_ERROR;
476           }
477 
478           /* Selects the Multiple Speed oscillator (MSI) clock range .*/
479           __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
480           /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
481           __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
482         }
483         else
484         {
485           /* Else, keep current flash latency while decreasing applies */
486           /* Selects the Multiple Speed oscillator (MSI) clock range .*/
487           __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
488           /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
489           __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
490 
491           /* Decrease number of wait states update if necessary */
492           /* Only possible when MSI is the System clock source  */
493           if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI)
494           {
495             if (RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
496             {
497               return HAL_ERROR;
498             }
499           }
500         }
501 
502         /* Update the SystemCoreClock global variable */
503         SystemCoreClock = HAL_RCC_GetHCLKFreq();
504 
505         /* Configure the source of time base considering new system clocks settings*/
506         status = HAL_InitTick(uwTickPrio);
507         if (status != HAL_OK)
508         {
509           return status;
510         }
511       }
512     }
513     else
514     {
515       /* Check the MSI State */
516       if (RCC_OscInitStruct->MSIState != RCC_MSI_OFF)
517       {
518         /* Enable the Internal High Speed oscillator (MSI). */
519         __HAL_RCC_MSI_ENABLE();
520 
521         /* Get timeout */
522         tickstart = HAL_GetTick();
523 
524         /* Wait till MSI is ready */
525         while (READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
526         {
527           if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
528           {
529             /* New check to avoid false timeout detection in case of preemption */
530             if (READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
531             {
532               return HAL_TIMEOUT;
533             }
534           }
535         }
536         /* Selects the Multiple Speed oscillator (MSI) clock range .*/
537         __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
538         /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
539         __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
540 
541       }
542       else
543       {
544         /* Disable the Internal High Speed oscillator (MSI). */
545         __HAL_RCC_MSI_DISABLE();
546 
547         /* Get timeout */
548         tickstart = HAL_GetTick();
549 
550         /* Wait till MSI is ready */
551         while (READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U)
552         {
553           if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
554           {
555             /* New check to avoid false timeout detection in case of preemption */
556             if (READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U)
557             {
558               return HAL_TIMEOUT;
559             }
560           }
561         }
562       }
563     }
564   }
565   /*------------------------------- HSE Configuration ------------------------*/
566   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
567   {
568     /* Check the parameters */
569     assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
570 
571     /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
572     if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSE) ||
573         ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_HSE)))
574     {
575       if ((READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
576       {
577         return HAL_ERROR;
578       }
579     }
580     else
581     {
582       /* Set the new HSE configuration ---------------------------------------*/
583       __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
584 
585       /* Check the HSE State */
586       if (RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
587       {
588         /* Get Start Tick*/
589         tickstart = HAL_GetTick();
590 
591         /* Wait till HSE is ready */
592         while (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
593         {
594           if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
595           {
596             /* New check to avoid false timeout detection in case of preemption */
597             if (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
598             {
599               return HAL_TIMEOUT;
600             }
601           }
602         }
603       }
604       else
605       {
606         /* Get Start Tick*/
607         tickstart = HAL_GetTick();
608 
609         /* Wait till HSE is disabled */
610         while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U)
611         {
612           if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
613           {
614             /* New check to avoid false timeout detection in case of preemption */
615             if (READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U)
616             {
617               return HAL_TIMEOUT;
618             }
619           }
620         }
621       }
622     }
623   }
624   /*----------------------------- HSI Configuration --------------------------*/
625   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
626   {
627     /* Check the parameters */
628     assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
629     assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
630 
631     /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
632     if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSI) ||
633         ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_HSI)))
634     {
635       /* When HSI is used as system clock it will not be disabled */
636       if ((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF))
637       {
638         return HAL_ERROR;
639       }
640       /* Otherwise, just the calibration is allowed */
641       else
642       {
643         /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
644         __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
645       }
646     }
647     else
648     {
649       /* Check the HSI State */
650       if (RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
651       {
652         /* Enable the Internal High Speed oscillator (HSI). */
653         __HAL_RCC_HSI_ENABLE();
654 
655         /* Get Start Tick*/
656         tickstart = HAL_GetTick();
657 
658         /* Wait till HSI is ready */
659         while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
660         {
661           if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
662           {
663             /* New check to avoid false timeout detection in case of preemption */
664             if (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
665             {
666               return HAL_TIMEOUT;
667             }
668           }
669         }
670 
671         /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
672         __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
673       }
674       else
675       {
676         /* Disable the Internal High Speed oscillator (HSI). */
677         __HAL_RCC_HSI_DISABLE();
678 
679         /* Get Start Tick*/
680         tickstart = HAL_GetTick();
681 
682         /* Wait till HSI is disabled */
683         while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U)
684         {
685           if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
686           {
687             /* New check to avoid false timeout detection in case of preemption */
688             if (READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U)
689             {
690               return HAL_TIMEOUT;
691             }
692           }
693         }
694       }
695     }
696   }
697   /*------------------------------ LSI Configuration -------------------------*/
698   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
699   {
700     /* Check the parameters */
701     assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
702 
703     /* Check the LSI State */
704     if (RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
705     {
706       /* Apply prescaler value */
707       if (RCC_OscInitStruct->LSIDiv == RCC_LSI_DIV1)
708       {
709         CLEAR_BIT(RCC->CSR, RCC_CSR_LSIPRE);
710       }
711       else
712       {
713         SET_BIT(RCC->CSR, RCC_CSR_LSIPRE);
714       }
715 
716       /* Enable the Internal Low Speed oscillator (LSI). */
717       __HAL_RCC_LSI_ENABLE();
718 
719       /* Get Start Tick*/
720       tickstart = HAL_GetTick();
721 
722       /* Wait till LSI is ready */
723       while (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == 0U)
724       {
725         if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
726         {
727           /* New check to avoid false timeout detection in case of preemption */
728           if (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == 0U)
729           {
730             return HAL_TIMEOUT;
731           }
732         }
733       }
734     }
735     else
736     {
737       /* Disable the Internal Low Speed oscillator (LSI). */
738       __HAL_RCC_LSI_DISABLE();
739 
740       /* Get Start Tick*/
741       tickstart = HAL_GetTick();
742 
743       /* Wait till LSI is disabled */
744       while (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
745       {
746         if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
747         {
748           /* New check to avoid false timeout detection in case of preemption */
749           if (READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
750           {
751             return HAL_TIMEOUT;
752           }
753         }
754       }
755     }
756   }
757   /*------------------------------ LSE Configuration -------------------------*/
758   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
759   {
760     FlagStatus       pwrclkchanged = RESET;
761 
762     /* Check the parameters */
763     assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
764 
765     /* Update LSE configuration in Backup Domain control register    */
766     /* Requires to enable write access to Backup Domain of necessary */
767     if (HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN))
768     {
769       __HAL_RCC_PWR_CLK_ENABLE();
770       pwrclkchanged = SET;
771     }
772 
773     if (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
774     {
775       /* Enable write access to Backup domain */
776       SET_BIT(PWR->CR1, PWR_CR1_DBP);
777 
778       /* Wait for Backup domain Write protection disable */
779       tickstart = HAL_GetTick();
780 
781       while (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
782       {
783         if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
784         {
785           /* New check to avoid false timeout detection in case of preemption */
786           if (HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
787           {
788             return HAL_TIMEOUT;
789           }
790         }
791       }
792     }
793 
794     /* Set the new LSE configuration -----------------------------------------*/
795     if ((RCC_OscInitStruct->LSEState & RCC_BDCR_LSEON) != 0U)
796     {
797       if ((RCC_OscInitStruct->LSEState & RCC_BDCR_LSEBYP) != 0U)
798       {
799         /* LSE oscillator bypass enable */
800         SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP);
801         SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);
802       }
803       else
804       {
805         /* LSE oscillator enable */
806         SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);
807       }
808     }
809     else
810     {
811       CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON);
812       CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP);
813     }
814 
815     /* Check the LSE State */
816     if (RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
817     {
818       /* Get Start Tick*/
819       tickstart = HAL_GetTick();
820 
821       /* Wait till LSE is ready */
822       while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)
823       {
824         if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
825         {
826           /* New check to avoid false timeout detection in case of preemption */
827           if (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)
828           {
829             return HAL_TIMEOUT;
830           }
831         }
832       }
833 
834       /* Enable LSESYS additionally if requested */
835       if ((RCC_OscInitStruct->LSEState & RCC_BDCR_LSESYSEN) != 0U)
836       {
837         SET_BIT(RCC->BDCR, RCC_BDCR_LSESYSEN);
838 
839         /* Wait till LSESYS is ready */
840         while (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) == 0U)
841         {
842           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
843           {
844             /* New check to avoid false timeout detection in case of preemption */
845             if (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) == 0U)
846             {
847               return HAL_TIMEOUT;
848             }
849           }
850         }
851       }
852       else
853       {
854         /* Make sure LSESYSEN/LSESYSRDY are reset */
855         CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSESYSEN);
856 
857         /* Wait till LSESYSRDY is cleared */
858         while (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) != 0U)
859         {
860           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
861           {
862             /* New check to avoid false timeout detection in case of preemption */
863             if (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) != 0U)
864             {
865               return HAL_TIMEOUT;
866             }
867           }
868         }
869       }
870     }
871     else
872     {
873       /* Get Start Tick*/
874       tickstart = HAL_GetTick();
875 
876       /* Wait till LSE is disabled */
877       while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != 0U)
878       {
879         if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
880         {
881           /* New check to avoid false timeout detection in case of preemption */
882           if (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != 0U)
883           {
884             return HAL_TIMEOUT;
885           }
886         }
887       }
888 
889       if (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSEN) != 0U)
890       {
891         /* Reset LSESYSEN once LSE is disabled */
892         CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSESYSEN);
893 
894         /* Wait till LSESYSRDY is cleared */
895         while (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) != 0U)
896         {
897           if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
898           {
899             /* New check to avoid false timeout detection in case of preemption */
900             if (READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSRDY) != 0U)
901             {
902               return HAL_TIMEOUT;
903             }
904           }
905         }
906       }
907     }
908 
909     /* Restore clock configuration if changed */
910     if (pwrclkchanged == SET)
911     {
912       __HAL_RCC_PWR_CLK_DISABLE();
913     }
914   }
915   /*------------------------------ HSI48 Configuration -----------------------*/
916   if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48)
917   {
918     /* Check the parameters */
919     assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State));
920 
921     /* Check the LSI State */
922     if (RCC_OscInitStruct->HSI48State != RCC_HSI48_OFF)
923     {
924       /* Enable the Internal Low Speed oscillator (HSI48). */
925       __HAL_RCC_HSI48_ENABLE();
926 
927       /* Get Start Tick*/
928       tickstart = HAL_GetTick();
929 
930       /* Wait till HSI48 is ready */
931       while (READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == 0U)
932       {
933         if ((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
934         {
935           /* New check to avoid false timeout detection in case of preemption */
936           if (READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == 0U)
937           {
938             return HAL_TIMEOUT;
939           }
940         }
941       }
942     }
943     else
944     {
945       /* Disable the Internal Low Speed oscillator (HSI48). */
946       __HAL_RCC_HSI48_DISABLE();
947 
948       /* Get Start Tick*/
949       tickstart = HAL_GetTick();
950 
951       /* Wait till HSI48 is disabled */
952       while (READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != 0U)
953       {
954         if ((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
955         {
956           /* New check to avoid false timeout detection in case of preemption */
957           if (READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != 0U)
958           {
959             return HAL_TIMEOUT;
960           }
961         }
962       }
963     }
964   }
965   /*-------------------------------- PLL Configuration -----------------------*/
966   /* Check the parameters */
967   assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
968 
969   if (RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
970   {
971     /* Check if the PLL is used as system clock or not */
972     if (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
973     {
974       if (RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON)
975       {
976         /* Check the parameters */
977         assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
978         assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
979         assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
980         assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
981         assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
982         assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));
983 
984         /* Disable the main PLL. */
985         __HAL_RCC_PLL_DISABLE();
986 
987         /* Get Start Tick*/
988         tickstart = HAL_GetTick();
989 
990         /* Wait till PLL is ready */
991         while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
992         {
993           if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
994           {
995             /* New check to avoid false timeout detection in case of preemption */
996             if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
997             {
998               return HAL_TIMEOUT;
999             }
1000           }
1001         }
1002 
1003         /* Configure the main PLL clock source, multiplication and division factors. */
1004         __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
1005                              RCC_OscInitStruct->PLL.PLLM,
1006                              RCC_OscInitStruct->PLL.PLLN,
1007                              RCC_OscInitStruct->PLL.PLLP,
1008                              RCC_OscInitStruct->PLL.PLLQ,
1009                              RCC_OscInitStruct->PLL.PLLR);
1010 
1011         /* Enable the main PLL. */
1012         __HAL_RCC_PLL_ENABLE();
1013 
1014         /* Enable PLL System Clock output. */
1015         __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
1016 
1017         /* Get Start Tick*/
1018         tickstart = HAL_GetTick();
1019 
1020         /* Wait till PLL is ready */
1021         while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
1022         {
1023           if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
1024           {
1025             /* New check to avoid false timeout detection in case of preemption */
1026             if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
1027             {
1028               return HAL_TIMEOUT;
1029             }
1030           }
1031         }
1032       }
1033       else
1034       {
1035         /* Disable the main PLL. */
1036         __HAL_RCC_PLL_DISABLE();
1037 
1038         /* Get Start Tick*/
1039         tickstart = HAL_GetTick();
1040 
1041         /* Wait till PLL is disabled */
1042         while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
1043         {
1044           if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
1045           {
1046             /* New check to avoid false timeout detection in case of preemption */
1047             if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
1048             {
1049               return HAL_TIMEOUT;
1050             }
1051           }
1052         }
1053 
1054         /* Unselect PLL clock source and disable outputs to save power */
1055         RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLSRC | RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK);
1056       }
1057     }
1058     else
1059     {
1060       /* Check if there is a request to disable the PLL used as System clock source */
1061       if (RCC_OscInitStruct->PLL.PLLState == RCC_PLL_OFF)
1062       {
1063         return HAL_ERROR;
1064       }
1065       else
1066       {
1067         pll_config = RCC->PLLCFGR;
1068         /* Do not return HAL_ERROR if request repeats the current configuration */
1069         if ((READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC)  != RCC_OscInitStruct->PLL.PLLSource) ||
1070             (READ_BIT(pll_config, RCC_PLLCFGR_PLLM)    != ((RCC_OscInitStruct->PLL.PLLM - 1U) << RCC_PLLCFGR_PLLM_Pos)) ||
1071             (READ_BIT(pll_config, RCC_PLLCFGR_PLLN)    != (RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos)) ||
1072             (READ_BIT(pll_config, RCC_PLLCFGR_PLLPDIV) != (RCC_OscInitStruct->PLL.PLLP << RCC_PLLCFGR_PLLPDIV_Pos)) ||
1073             (READ_BIT(pll_config, RCC_PLLCFGR_PLLQ)    != ((((RCC_OscInitStruct->PLL.PLLQ) >> 1U) - 1U) << RCC_PLLCFGR_PLLQ_Pos)) ||
1074             (READ_BIT(pll_config, RCC_PLLCFGR_PLLR)    != ((((RCC_OscInitStruct->PLL.PLLR) >> 1U) - 1U) << RCC_PLLCFGR_PLLR_Pos)))
1075         {
1076           return HAL_ERROR;
1077         }
1078       }
1079     }
1080   }
1081 
1082   return HAL_OK;
1083 }
1084 
1085 /**
1086   * @brief  Initialize the CPU, AHB and APB buses clocks according to the specified
1087   *         parameters in the RCC_ClkInitStruct.
1088   * @param  RCC_ClkInitStruct  pointer to an RCC_OscInitTypeDef structure that
1089   *         contains the configuration information for the RCC peripheral.
1090   * @param  FLatency  FLASH Latency
1091   *          This parameter can be one of the following values:
1092   *            @arg FLASH_LATENCY_0   FLASH 0 Latency cycle
1093   *            @arg FLASH_LATENCY_1   FLASH 1 Latency cycle
1094   *            @arg FLASH_LATENCY_2   FLASH 2 Latency cycles
1095   *            @arg FLASH_LATENCY_3   FLASH 3 Latency cycles
1096   *            @arg FLASH_LATENCY_4   FLASH 4 Latency cycles
1097   *            @arg FLASH_LATENCY_5   FLASH 5 Latency cycles
1098   *            @arg FLASH_LATENCY_6   FLASH 6 Latency cycles
1099   *            @arg FLASH_LATENCY_7   FLASH 7 Latency cycles
1100   *            @arg FLASH_LATENCY_8   FLASH 8 Latency cycles
1101   *            @arg FLASH_LATENCY_9   FLASH 9 Latency cycles
1102   *            @arg FLASH_LATENCY_10  FLASH 10 Latency cycles
1103   *            @arg FLASH_LATENCY_11  FLASH 11 Latency cycles
1104   *            @arg FLASH_LATENCY_12  FLASH 12 Latency cycles
1105   *            @arg FLASH_LATENCY_13  FLASH 13 Latency cycles
1106   *            @arg FLASH_LATENCY_14  FLASH 14 Latency cycles
1107   *            @arg FLASH_LATENCY_15  FLASH 15 Latency cycles
1108   *
1109   * @note   The SystemCoreClock CMSIS variable is used to store System Clock Frequency
1110   *         and is updated by this function
1111   *
1112   * @note   The MSI is used by default as system clock source after
1113   *         startup from Reset, wake-up from STANDBY mode. After restart from Reset,
1114   *         the MSI frequency is set to its default value 4 MHz.
1115   *
1116   * @note   The HSI can be selected as system clock source after
1117   *         from STOP modes or in case of failure of the HSE used directly or indirectly
1118   *         as system clock (if the Clock Security System CSS is enabled).
1119   *
1120   * @note   A switch from one clock source to another occurs only if the target
1121   *         clock source is ready (clock stable after startup delay or PLL locked).
1122   *         If a clock source which is not yet ready is selected, the switch will
1123   *         occur when the clock source is ready.
1124   *
1125   * @note   HAL_RCC_ClockConfig() function takes care of clock switching transition state
1126   *         with AHB prescaler when switching from HSE or HSI or MSI to PLL with AHB
1127   *         frequency (HCLK) higher than 80 MHz and when switching from PLL with HCLK
1128   *         higher than 80 MHz to HSE or HSI or MSI currently used as system clock source.
1129   *
1130   * @note   You can use HAL_RCC_GetClockConfig() function to know which clock is
1131   *         currently used as system clock source.
1132   *
1133   * @note   Depending on the device voltage range, the software has to set correctly
1134   *         HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency
1135   *         (for more details refer to section above "Initialization/de-initialization functions")
1136   * @retval None
1137   */
HAL_RCC_ClockConfig(RCC_ClkInitTypeDef * RCC_ClkInitStruct,uint32_t FLatency)1138 HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
1139 {
1140   uint32_t tickstart;
1141   uint32_t pllfreq;
1142   uint32_t hpre = RCC_SYSCLK_DIV1;
1143 
1144   /* Check Null pointer */
1145   if (RCC_ClkInitStruct == NULL)
1146   {
1147     return HAL_ERROR;
1148   }
1149 
1150   /* Check the parameters */
1151   assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
1152   assert_param(IS_FLASH_LATENCY(FLatency));
1153 
1154   /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
1155     must be correctly programmed according to the frequency of the CPU clock
1156     (HCLK) and the supply voltage of the device. */
1157 
1158   /* Increasing the number of wait states because of higher CPU frequency */
1159   if (FLatency > __HAL_FLASH_GET_LATENCY())
1160   {
1161     /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
1162     __HAL_FLASH_SET_LATENCY(FLatency);
1163 
1164     /* Check that the new number of wait states is taken into account to access the Flash
1165     memory by reading the FLASH_ACR register */
1166     if (__HAL_FLASH_GET_LATENCY() != FLatency)
1167     {
1168       return HAL_ERROR;
1169     }
1170   }
1171 
1172   /*----------------- HCLK Configuration prior to SYSCLK----------------------*/
1173   /* Apply higher HCLK prescaler request here to ensure CPU clock is not of of spec when SYSCLK is increased */
1174   if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
1175   {
1176     assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
1177 
1178     if(RCC_ClkInitStruct->AHBCLKDivider > READ_BIT(RCC->CFGR, RCC_CFGR_HPRE))
1179     {
1180       MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
1181     }
1182   }
1183 
1184   /*------------------------- SYSCLK Configuration ---------------------------*/
1185   if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
1186   {
1187     assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
1188 
1189     /* PLL is selected as System Clock Source */
1190     if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
1191     {
1192       /* Check the PLL ready flag */
1193       if (READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
1194       {
1195         return HAL_ERROR;
1196       }
1197 
1198       /* Transition state management when selecting PLL as SYSCLK source and */
1199       /* target frequency above 80Mhz */
1200       /* Compute target PLL output frequency */
1201       pllfreq = RCC_GetSysClockFreqFromPLLSource();
1202 
1203       /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */
1204       if (pllfreq > 80000000U)
1205       {
1206         /* If lowest HCLK prescaler, apply intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */
1207         if (READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)
1208         {
1209           MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
1210           hpre = RCC_SYSCLK_DIV2;
1211         }
1212       }
1213     }
1214     else
1215     {
1216       /* HSE is selected as System Clock Source */
1217       if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
1218       {
1219         /* Check the HSE ready flag */
1220         if (READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
1221         {
1222           return HAL_ERROR;
1223         }
1224       }
1225       /* MSI is selected as System Clock Source */
1226       else if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
1227       {
1228         /* Check the MSI ready flag */
1229         if (READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
1230         {
1231           return HAL_ERROR;
1232         }
1233       }
1234       /* HSI is selected as System Clock Source */
1235       else
1236       {
1237         /* Check the HSI ready flag */
1238         if (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
1239         {
1240           return HAL_ERROR;
1241         }
1242       }
1243 
1244       /* Transition state management when when going down from PLL used as */
1245       /* SYSCLK source and frequency above 80Mhz */
1246       pllfreq = HAL_RCC_GetSysClockFreq();
1247 
1248       /* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */
1249       if (pllfreq > 80000000U)
1250       {
1251         /* If lowest HCLK prescaler, apply intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */
1252         if(READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)
1253         {
1254           MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
1255           hpre = RCC_SYSCLK_DIV2;
1256         }
1257       }
1258     }
1259 
1260     MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);
1261 
1262     /* Get Start Tick*/
1263     tickstart = HAL_GetTick();
1264 
1265     while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
1266     {
1267       if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
1268       {
1269         /* New check to avoid false timeout detection in case of preemption */
1270         if (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
1271         {
1272           return HAL_TIMEOUT;
1273         }
1274       }
1275     }
1276   }
1277 
1278   /* Is intermediate HCLK prescaler 2 applied internally, resume with HCLK prescaler 1 */
1279   if(hpre == RCC_SYSCLK_DIV2)
1280   {
1281     MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1);
1282   }
1283 
1284   /*----------------- HCLK Configuration after SYSCLK-------------------------*/
1285   /* Apply lower HCLK prescaler request here to ensure CPU clock is not of of spec when SYSCLK is set */
1286   if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
1287   {
1288     if(RCC_ClkInitStruct->AHBCLKDivider < READ_BIT(RCC->CFGR, RCC_CFGR_HPRE))
1289     {
1290       MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
1291     }
1292   }
1293 
1294   /* Allow decreasing of the number of wait states (because of lower CPU frequency expected) */
1295   if (FLatency < __HAL_FLASH_GET_LATENCY())
1296   {
1297     /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
1298     __HAL_FLASH_SET_LATENCY(FLatency);
1299 
1300     /* Check that the new number of wait states is taken into account to access the Flash
1301     memory by reading the FLASH_ACR register */
1302     if (__HAL_FLASH_GET_LATENCY() != FLatency)
1303     {
1304       return HAL_ERROR;
1305     }
1306   }
1307 
1308   /*-------------------------- PCLK1 Configuration ---------------------------*/
1309   if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
1310   {
1311     assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
1312     MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
1313   }
1314 
1315   /*-------------------------- PCLK2 Configuration ---------------------------*/
1316   if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
1317   {
1318     assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
1319     MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
1320   }
1321 
1322   /* Update the SystemCoreClock global variable */
1323   SystemCoreClock = HAL_RCC_GetHCLKFreq();
1324 
1325   /* Configure the source of time base considering new system clocks settings*/
1326   return HAL_InitTick(uwTickPrio);
1327 }
1328 
1329 /**
1330   * @}
1331   */
1332 
1333 /** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions
1334   *  @brief   RCC clocks control functions
1335   *
1336 @verbatim
1337  ===============================================================================
1338                       ##### Peripheral Control functions #####
1339  ===============================================================================
1340     [..]
1341     This subsection provides a set of functions allowing to:
1342 
1343     (+) Output clock to MCO pin.
1344     (+) Retrieve current clock frequencies.
1345     (+) Enable the Clock Security System.
1346 
1347 @endverbatim
1348   * @{
1349   */
1350 
1351 /**
1352   * @brief  Select the clock source to output on MCO pin(PA8).
1353   * @note   PA8 should be configured in alternate function mode.
1354   * @param  RCC_MCOx  specifies the output direction for the clock source.
1355   *          For STM32L5xx family this parameter can have only one value:
1356   *            @arg @ref RCC_MCO1  Clock source to output on MCO1 pin(PA8).
1357   * @param  RCC_MCOSource  specifies the clock source to output.
1358   *          This parameter can be one of the following values:
1359   *            @arg @ref RCC_MCO1SOURCE_NOCLOCK  MCO output disabled, no clock on MCO
1360   *            @arg @ref RCC_MCO1SOURCE_SYSCLK  system  clock selected as MCO source
1361   *            @arg @ref RCC_MCO1SOURCE_MSI  MSI clock selected as MCO source
1362   *            @arg @ref RCC_MCO1SOURCE_HSI  HSI clock selected as MCO source
1363   *            @arg @ref RCC_MCO1SOURCE_HSE  HSE clock selected as MCO sourcee
1364   *            @arg @ref RCC_MCO1SOURCE_PLLCLK  main PLL clock selected as MCO source
1365   *            @arg @ref RCC_MCO1SOURCE_LSI  LSI clock selected as MCO source
1366   *            @arg @ref RCC_MCO1SOURCE_LSE  LSE clock selected as MCO source
1367   *            @arg @ref RCC_MCO1SOURCE_HSI48  HSI48 clock selected as MCO source
1368   * @param  RCC_MCODiv  specifies the MCO prescaler.
1369   *          This parameter can be one of the following values:
1370   *            @arg @ref RCC_MCODIV_1  no division applied to MCO clock
1371   *            @arg @ref RCC_MCODIV_2  division by 2 applied to MCO clock
1372   *            @arg @ref RCC_MCODIV_4  division by 4 applied to MCO clock
1373   *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
1374   *            @arg @ref RCC_MCODIV_16  division by 16 applied to MCO clock
1375   * @retval None
1376   */
HAL_RCC_MCOConfig(uint32_t RCC_MCOx,uint32_t RCC_MCOSource,uint32_t RCC_MCODiv)1377 void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
1378 {
1379   GPIO_InitTypeDef GPIO_InitStruct;
1380 
1381   /* Prevent unused argument(s) compilation warning */
1382   UNUSED(RCC_MCOx);
1383 
1384   /* Check the parameters */
1385   assert_param(IS_RCC_MCODIV(RCC_MCODiv));
1386   assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
1387 
1388   /* MCO Clock Enable */
1389   __MCO1_CLK_ENABLE();
1390 
1391   /* Configure the MCO1 pin in alternate function mode */
1392   GPIO_InitStruct.Pin = MCO1_PIN;
1393   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
1394   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
1395   GPIO_InitStruct.Pull = GPIO_NOPULL;
1396   GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
1397   HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
1398 
1399   /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */
1400   MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv));
1401 }
1402 
1403 /**
1404   * @brief  Return the SYSCLK frequency.
1405   *
1406   * @note   The system frequency computed by this function is not the real
1407   *         frequency in the chip. It is calculated based on the predefined
1408   *         constant and the selected clock source:
1409   * @note     If SYSCLK source is MSI, function returns values based on MSI
1410   *             Value as defined by the MSI range.
1411   * @note     If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
1412   * @note     If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
1413   * @note     If SYSCLK source is PLL, function returns values based on HSE_VALUE(**),
1414   *           HSI_VALUE(*) or MSI Value multiplied/divided by the PLL factors.
1415   * @note     (*) HSI_VALUE is a constant defined in stm32l5xx_hal_conf.h file (default value
1416   *               16 MHz) but the real value may vary depending on the variations
1417   *               in voltage and temperature.
1418   * @note     (**) HSE_VALUE is a constant defined in stm32l5xx_hal_conf.h file (default value
1419   *                8 MHz), user has to ensure that HSE_VALUE is same as the real
1420   *                frequency of the crystal used. Otherwise, this function may
1421   *                have wrong result.
1422   *
1423   * @note   The result of this function could be not correct when using fractional
1424   *         value for HSE crystal.
1425   *
1426   * @note   This function can be used by the user application to compute the
1427   *         baudrate for the communication peripherals or configure other parameters.
1428   *
1429   * @note   Each time SYSCLK changes, this function must be called to update the
1430   *         right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
1431   *
1432   *
1433   * @retval SYSCLK frequency
1434   */
HAL_RCC_GetSysClockFreq(void)1435 uint32_t HAL_RCC_GetSysClockFreq(void)
1436 {
1437   uint32_t msirange = 0U, sysclockfreq = 0U;
1438   uint32_t pllvco, pllsource, pllr, pllm;    /* no init needed */
1439   uint32_t sysclk_source, pll_oscsource;
1440 
1441   sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE();
1442   pll_oscsource = __HAL_RCC_GET_PLL_OSCSOURCE();
1443 
1444   if ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI) ||
1445       ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_oscsource == RCC_PLLSOURCE_MSI)))
1446   {
1447     /* MSI or PLL with MSI source used as system clock source */
1448 
1449     /* Get SYSCLK source */
1450     if (READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == 0U)
1451     {
1452       /* MSISRANGE from RCC_CSR applies */
1453       msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos;
1454     }
1455     else
1456     {
1457       /* MSIRANGE from RCC_CR applies */
1458       msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos;
1459     }
1460     /*MSI frequency range in Hz*/
1461     msirange = MSIRangeTable[msirange];
1462 
1463     if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_MSI)
1464     {
1465       /* MSI used as system clock source */
1466       sysclockfreq = msirange;
1467     }
1468   }
1469   else if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSI)
1470   {
1471     /* HSI used as system clock source */
1472     sysclockfreq = HSI_VALUE;
1473   }
1474   else if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSE)
1475   {
1476     /* HSE used as system clock source */
1477     sysclockfreq = HSE_VALUE;
1478   }
1479   else
1480   {
1481     /* unexpected case: sysclockfreq at 0 */
1482   }
1483 
1484   if (sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK)
1485   {
1486     /* PLL used as system clock  source */
1487 
1488     /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
1489     SYSCLK = PLL_VCO / PLLR
1490     */
1491     pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
1492     pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
1493 
1494     switch (pllsource)
1495     {
1496       case RCC_PLLSOURCE_HSI:  /* HSI used as PLL clock source */
1497         pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
1498         break;
1499 
1500       case RCC_PLLSOURCE_HSE:  /* HSE used as PLL clock source */
1501         pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
1502         break;
1503 
1504       case RCC_PLLSOURCE_MSI:  /* MSI used as PLL clock source */
1505       default:
1506         pllvco = (msirange / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
1507         break;
1508     }
1509     pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) * 2U;
1510     sysclockfreq = pllvco / pllr;
1511   }
1512 
1513   return sysclockfreq;
1514 }
1515 
1516 /**
1517   * @brief  Return the HCLK frequency.
1518   * @note   Each time HCLK changes, this function must be called to update the
1519   *         right HCLK value. Otherwise, any configuration based on this function will be incorrect.
1520   * @retval HCLK frequency in Hz
1521   */
HAL_RCC_GetHCLKFreq(void)1522 uint32_t HAL_RCC_GetHCLKFreq(void)
1523 {
1524   return (HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]);
1525 }
1526 
1527 /**
1528   * @brief  Return the PCLK1 frequency.
1529   * @note   Each time PCLK1 changes, this function must be called to update the
1530   *         right PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
1531   * @retval PCLK1 frequency in Hz
1532   */
HAL_RCC_GetPCLK1Freq(void)1533 uint32_t HAL_RCC_GetPCLK1Freq(void)
1534 {
1535   /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
1536   return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]);
1537 }
1538 
1539 /**
1540   * @brief  Return the PCLK2 frequency.
1541   * @note   Each time PCLK2 changes, this function must be called to update the
1542   *         right PCLK2 value. Otherwise, any configuration based on this function will be incorrect.
1543   * @retval PCLK2 frequency in Hz
1544   */
HAL_RCC_GetPCLK2Freq(void)1545 uint32_t HAL_RCC_GetPCLK2Freq(void)
1546 {
1547   /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
1548   return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]);
1549 }
1550 
1551 /**
1552   * @brief  Return the oscillators and main PLL configuration in RCC_OscInitStruct
1553   *         according to the internal RCC configuration registers.
1554   * @param  RCC_OscInitStruct  pointer to an RCC_OscInitTypeDef structure that
1555   *         will be configured.
1556   * @retval None
1557   */
HAL_RCC_GetOscConfig(RCC_OscInitTypeDef * RCC_OscInitStruct)1558 void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
1559 {
1560   /* Check the parameters */
1561   assert_param(RCC_OscInitStruct != (void *)NULL);
1562 
1563   /* Set all possible values for the Oscillator type parameter ---------------*/
1564   RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \
1565                                       RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48;
1566 
1567   /* Get the HSE configuration -----------------------------------------------*/
1568   if ((RCC->CR & RCC_CR_HSERDY) == RCC_CR_HSERDY)
1569   {
1570     if ((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
1571     {
1572       RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
1573     }
1574     else
1575     {
1576       RCC_OscInitStruct->HSEState = RCC_HSE_ON;
1577     }
1578   }
1579   else
1580   {
1581     RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
1582   }
1583 
1584   /* Get the MSI configuration -----------------------------------------------*/
1585   if ((RCC->CR & RCC_CR_MSIRDY) == RCC_CR_MSIRDY)
1586   {
1587     RCC_OscInitStruct->MSIState = RCC_MSI_ON;
1588   }
1589   else
1590   {
1591     RCC_OscInitStruct->MSIState = RCC_MSI_OFF;
1592   }
1593 
1594   RCC_OscInitStruct->MSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos);
1595   RCC_OscInitStruct->MSIClockRange = (uint32_t)((RCC->CR & RCC_CR_MSIRANGE));
1596 
1597   /* Get the HSI configuration -----------------------------------------------*/
1598   if ((RCC->CR & RCC_CR_HSIRDY) == RCC_CR_HSIRDY)
1599   {
1600     RCC_OscInitStruct->HSIState = RCC_HSI_ON;
1601   }
1602   else
1603   {
1604     RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
1605   }
1606 
1607   RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos);
1608 
1609   /* Get the LSE configuration -----------------------------------------------*/
1610   if ((RCC->BDCR & RCC_BDCR_LSERDY) == RCC_BDCR_LSERDY)
1611   {
1612     if ((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
1613     {
1614       if ((RCC->BDCR & RCC_BDCR_LSESYSEN) == RCC_BDCR_LSESYSEN)
1615       {
1616         RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
1617       }
1618       else
1619       {
1620         RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS_RTC_ONLY;
1621       }
1622     }
1623     else
1624     {
1625       if ((RCC->BDCR & RCC_BDCR_LSESYSEN) == RCC_BDCR_LSESYSEN)
1626       {
1627         RCC_OscInitStruct->LSEState = RCC_LSE_ON;
1628       }
1629       else
1630       {
1631         RCC_OscInitStruct->LSEState = RCC_LSE_ON_RTC_ONLY;
1632       }
1633     }
1634   }
1635   else
1636   {
1637     RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
1638   }
1639 
1640   /* Get the LSI configuration -----------------------------------------------*/
1641   if ((RCC->CSR & RCC_CSR_LSIRDY) == RCC_CSR_LSIRDY)
1642   {
1643     RCC_OscInitStruct->LSIState = RCC_LSI_ON;
1644   }
1645   else
1646   {
1647     RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
1648   }
1649 
1650   if ((RCC->CSR & RCC_CSR_LSIPRE) == RCC_CSR_LSIPRE)
1651   {
1652     RCC_OscInitStruct->LSIDiv = RCC_LSI_DIV128;
1653   }
1654   else
1655   {
1656     RCC_OscInitStruct->LSIDiv = RCC_LSI_DIV1;
1657   }
1658 
1659   /* Get the HSI48 configuration ---------------------------------------------*/
1660   if ((RCC->CRRCR & RCC_CRRCR_HSI48RDY) == RCC_CRRCR_HSI48RDY)
1661   {
1662     RCC_OscInitStruct->HSI48State = RCC_HSI48_ON;
1663   }
1664   else
1665   {
1666     RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF;
1667   }
1668 
1669   /* Get the PLL configuration -----------------------------------------------*/
1670   if ((RCC->CR & RCC_CR_PLLRDY) == RCC_CR_PLLRDY)
1671   {
1672     RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
1673   }
1674   else
1675   {
1676     RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
1677   }
1678   RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
1679   RCC_OscInitStruct->PLL.PLLM = (uint32_t)(((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U);
1680   RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
1681   RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U);
1682   RCC_OscInitStruct->PLL.PLLR = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U);
1683   RCC_OscInitStruct->PLL.PLLP = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos);
1684 }
1685 
1686 /**
1687   * @brief  Return the clocks configuration in RCC_ClkInitStruct according to the
1688   *         internal RCC configuration registers as well as the current FLASH latency.
1689   * @param  RCC_ClkInitStruct  pointer to an RCC_ClkInitTypeDef structure that
1690   *         will be configured.
1691   * @param  pFLatency  Pointer on the Flash Latency.
1692   * @retval None
1693   */
HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef * RCC_ClkInitStruct,uint32_t * pFLatency)1694 void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t *pFLatency)
1695 {
1696   /* Check the parameters */
1697   assert_param(RCC_ClkInitStruct != (void *)NULL);
1698   assert_param(pFLatency != (void *)NULL);
1699 
1700   /* Set all possible values for the Clock type parameter --------------------*/
1701   RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
1702 
1703   /* Get the SYSCLK configuration --------------------------------------------*/
1704   RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW);
1705 
1706   /* Get the HCLK configuration ----------------------------------------------*/
1707   RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE);
1708 
1709   /* Get the APB1 configuration ----------------------------------------------*/
1710   RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1);
1711 
1712   /* Get the APB2 configuration ----------------------------------------------*/
1713   RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3U);
1714 
1715   /* Get the Flash Wait State (Latency) configuration ------------------------*/
1716   *pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_LATENCY);
1717 }
1718 
1719 /**
1720   * @brief  Enable the Clock Security System.
1721   * @note   If a failure is detected on the HSE oscillator clock, this oscillator
1722   *         is automatically disabled and an interrupt is generated to inform the
1723   *         software about the failure (Clock Security System Interrupt, CSSI),
1724   *         allowing the MCU to perform rescue operations. The CSSI is linked to
1725   *         the Cortex-M33 NMI (Non-Maskable Interrupt) exception vector.
1726   * @note   The Clock Security System can only be cleared by reset.
1727   * @retval None
1728   */
HAL_RCC_EnableCSS(void)1729 void HAL_RCC_EnableCSS(void)
1730 {
1731   SET_BIT(RCC->CR, RCC_CR_CSSON) ;
1732 }
1733 
1734 /**
1735   * @brief Handle the RCC Clock Security System interrupt request.
1736   * @note This API should be called under the NMI_Handler().
1737   * @retval None
1738   */
HAL_RCC_NMI_IRQHandler(void)1739 void HAL_RCC_NMI_IRQHandler(void)
1740 {
1741   /* Check RCC CSSF interrupt flag  */
1742   if (__HAL_RCC_GET_IT(RCC_IT_CSS))
1743   {
1744     /* RCC Clock Security System interrupt user callback */
1745     HAL_RCC_CSSCallback();
1746 
1747     /* Clear RCC CSS pending bit */
1748     __HAL_RCC_CLEAR_IT(RCC_IT_CSS);
1749   }
1750 }
1751 
1752 /**
1753   * @brief  RCC Clock Security System interrupt callback.
1754   * @retval none
1755   */
HAL_RCC_CSSCallback(void)1756 __weak void HAL_RCC_CSSCallback(void)
1757 {
1758   /* NOTE : This function should not be modified, when the callback is needed,
1759             the HAL_RCC_CSSCallback should be implemented in the user file
1760    */
1761 }
1762 
1763 /**
1764   * @brief  Get and clear reset flags
1765   * @note   Once reset flags are retrieved, this API is clearing them in order
1766   *         to isolate next reset reason.
1767   * @retval can be a combination of @ref RCC_Reset_Flag
1768   */
HAL_RCC_GetResetSource(void)1769 uint32_t HAL_RCC_GetResetSource(void)
1770 {
1771   uint32_t reset;
1772 
1773   /* Get all reset flags */
1774   reset = RCC->CSR & RCC_RESET_FLAG_ALL;
1775 
1776   /* Clear Reset flags */
1777   RCC->CSR |= RCC_CSR_RMVF;
1778 
1779   return reset;
1780 }
1781 
1782 /**
1783   * @}
1784   */
1785 
1786 /** @defgroup RCC_Exported_Functions_Group3 Attributes management functions
1787   *  @brief Attributes management functions.
1788   *
1789 @verbatim
1790  ===============================================================================
1791                        ##### RCC attributes functions #####
1792  ===============================================================================
1793 
1794 @endverbatim
1795   * @{
1796   */
1797 
1798 /**
1799   * @brief  Configure the RCC item attribute(s).
1800   * @note   Available attributes are to secure items and set RCC as privileged.
1801   *         Default state is not secure and unprivileged access allowed.
1802   * @note   Secure and non-secure attributes can only be set from the secure
1803   *         state when the system implements the security (TZEN=1).
1804   * @note   Security and privilege attributes can be set independently.
1805   * @param  Item Item(s) to set attributes on.
1806   *         This parameter can be a one or a combination of @ref RCC_items
1807   * @param  Attributes can be one or a combination of the following values:
1808   *            @arg @ref RCC_PRIV         Privileged-only access
1809   *            @arg @ref RCC_NPRIV        Privileged/Non-privileged access
1810   *            @arg @ref RCC_SEC          Secure-only access
1811   *            @arg @ref RCC_NSEC         Secure/Non-secure access
1812   * @retval None
1813   */
HAL_RCC_ConfigAttributes(uint32_t Item,uint32_t Attributes)1814 void HAL_RCC_ConfigAttributes(uint32_t Item, uint32_t Attributes)
1815 {
1816   /* Check the parameters */
1817   assert_param(IS_RCC_ATTRIBUTES(Attributes));
1818 
1819   /* Privilege/non-privilege attribute */
1820   if ((Attributes & RCC_PRIV) == RCC_PRIV)
1821   {
1822     SET_BIT(RCC->CR, RCC_CR_PRIV);
1823   }
1824   else if ((Attributes & RCC_NPRIV) == RCC_NPRIV)
1825   {
1826     CLEAR_BIT(RCC->CR, RCC_CR_PRIV);
1827   }
1828   else
1829   {
1830     /* do nothing */
1831   }
1832 
1833 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1834 
1835   /* Check the parameters */
1836   assert_param(IS_RCC_ITEMS_ATTRIBUTES(Item));
1837 
1838   /* Secure/non-secure attribute */
1839   if ((Attributes & RCC_SEC) == RCC_SEC)
1840   {
1841     SET_BIT(RCC_S->SECCFGR, Item);
1842   }
1843   else if ((Attributes & RCC_NSEC) == RCC_NSEC)
1844   {
1845     CLEAR_BIT(RCC_S->SECCFGR, Item);
1846   }
1847   else
1848   {
1849     /* do nothing */
1850   }
1851 
1852 #else
1853 
1854   /* Prevent unused argument(s) compilation warning */
1855   UNUSED(Item);
1856 
1857 #endif /* __ARM_FEATURE_CMSE */
1858 }
1859 
1860 /**
1861   * @brief  Get the attribute of a RCC item.
1862   * @note   Secure and non-secure attributes are only available from secure state
1863   *         when the system implements the security (TZEN=1)
1864   * @param  Item Single item to get secure/non-secure and privilege/non-privilege attribute from.
1865   * @param  pAttributes pointer to return the attributes value.
1866   * @retval HAL Status.
1867   */
HAL_RCC_GetConfigAttributes(uint32_t Item,uint32_t * pAttributes)1868 HAL_StatusTypeDef HAL_RCC_GetConfigAttributes(uint32_t Item, uint32_t *pAttributes)
1869 {
1870   uint32_t attributes;
1871 
1872   /* Check null pointer */
1873   if (pAttributes == NULL)
1874   {
1875     return HAL_ERROR;
1876   }
1877 
1878 
1879   /* Get privilege or non-privilege attribute */
1880   if (READ_BIT(RCC->CR, RCC_CR_PRIV) != 0U)
1881   {
1882     attributes = RCC_PRIV;
1883   }
1884   else
1885   {
1886     attributes = RCC_NPRIV;
1887   }
1888 
1889 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1890 
1891   /* Check the parameters */
1892   assert_param(IS_RCC_ITEMS_ATTRIBUTES(Item));
1893 
1894   /* Get the secure or non-secure attribute state */
1895   if ((RCC_S->SECCFGR & Item) == Item)
1896   {
1897     attributes |= RCC_SEC;
1898   }
1899   else
1900   {
1901     attributes |= RCC_NSEC;
1902   }
1903 
1904 #else
1905 
1906   /* Prevent unused argument(s) compilation warning */
1907   UNUSED(Item);
1908 
1909 #endif /* __ARM_FEATURE_CMSE */
1910 
1911   /* return value */
1912   *pAttributes = attributes;
1913 
1914   return HAL_OK;
1915 }
1916 
1917 
1918 /**
1919   * @}
1920   */
1921 
1922 /**
1923   * @}
1924   */
1925 
1926 /* Private function prototypes -----------------------------------------------*/
1927 /** @addtogroup RCC_Private_Functions
1928   * @{
1929   */
1930 /**
1931   * @brief  Update number of Flash wait states in line with MSI range and current
1932             voltage range.
1933   * @param  msirange  MSI range value from RCC_MSIRANGE_0 to RCC_MSIRANGE_11
1934   * @retval HAL status
1935   */
RCC_SetFlashLatencyFromMSIRange(uint32_t msirange)1936 static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange)
1937 {
1938   uint32_t latency = FLASH_LATENCY_0;  /* default value 0WS */
1939   uint32_t vos;
1940 
1941   if (__HAL_RCC_PWR_IS_CLK_ENABLED())
1942   {
1943     vos = HAL_PWREx_GetVoltageRange();
1944   }
1945   else
1946   {
1947     __HAL_RCC_PWR_CLK_ENABLE();
1948     vos = HAL_PWREx_GetVoltageRange();
1949     __HAL_RCC_PWR_CLK_DISABLE();
1950   }
1951 
1952   if ((vos == PWR_REGULATOR_VOLTAGE_SCALE0) || (vos == PWR_REGULATOR_VOLTAGE_SCALE1))
1953   {
1954     if (msirange > RCC_MSIRANGE_8)
1955     {
1956       /* MSI > 16Mhz */
1957       if (msirange > RCC_MSIRANGE_10)
1958       {
1959         /* MSI 48Mhz */
1960         latency = FLASH_LATENCY_2; /* 2WS */
1961       }
1962       else
1963       {
1964         /* MSI 24Mhz or 32Mhz */
1965         latency = FLASH_LATENCY_1; /* 1WS */
1966       }
1967     }
1968     /* else MSI <= 16Mhz default FLASH_LATENCY_0 0WS */
1969   }
1970   else
1971   {
1972     if (msirange > RCC_MSIRANGE_8)
1973     {
1974       /* MSI > 16Mhz */
1975       latency = FLASH_LATENCY_3; /* 3WS */
1976     }
1977     else
1978     {
1979       if (msirange == RCC_MSIRANGE_8)
1980       {
1981         /* MSI 16Mhz */
1982         latency = FLASH_LATENCY_2; /* 2WS */
1983       }
1984       else if (msirange == RCC_MSIRANGE_7)
1985       {
1986         /* MSI 8Mhz */
1987         latency = FLASH_LATENCY_1; /* 1WS */
1988       }
1989       else
1990       {
1991         /* MSI < 8Mhz default FLASH_LATENCY_0 0WS */
1992       }
1993     }
1994   }
1995 
1996   __HAL_FLASH_SET_LATENCY(latency);
1997 
1998   /* Check that the new number of wait states is taken into account to access the Flash
1999      memory by reading the FLASH_ACR register */
2000   if ((FLASH->ACR & FLASH_ACR_LATENCY) != latency)
2001   {
2002     return HAL_ERROR;
2003   }
2004 
2005   return HAL_OK;
2006 }
2007 
2008 /**
2009   * @brief  Compute SYSCLK frequency based on PLL SYSCLK source.
2010   * @retval SYSCLK frequency
2011   */
RCC_GetSysClockFreqFromPLLSource(void)2012 static uint32_t RCC_GetSysClockFreqFromPLLSource(void)
2013 {
2014   uint32_t msirange, pllvco, pllsource, pllr, pllm, sysclockfreq;    /* no init needed */
2015 
2016   /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
2017      SYSCLK = PLL_VCO / PLLR
2018    */
2019   pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC);
2020   pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
2021 
2022   switch (pllsource)
2023   {
2024     case RCC_PLLSOURCE_HSI:  /* HSI used as PLL clock source */
2025       pllvco = (HSI_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
2026       break;
2027 
2028     case RCC_PLLSOURCE_HSE:  /* HSE used as PLL clock source */
2029       pllvco = (HSE_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
2030       break;
2031 
2032     case RCC_PLLSOURCE_MSI:  /* MSI used as PLL clock source */
2033       /* Get MSI range source */
2034       if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == 0U)
2035       { /* MSISRANGE from RCC_CSR applies */
2036         msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos;
2037       }
2038       else
2039       { /* MSIRANGE from RCC_CR applies */
2040         msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos;
2041       }
2042         /*MSI frequency range in HZ*/
2043         pllvco = MSIRangeTable[msirange];
2044         break;
2045     default:
2046       /* unexpected */
2047       pllvco = 0;
2048       break;
2049   }
2050 
2051   pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) * 2U;
2052   sysclockfreq = pllvco / pllr;
2053 
2054   return sysclockfreq;
2055 }
2056 
2057 /**
2058   * @}
2059   */
2060 
2061 #endif /* HAL_RCC_MODULE_ENABLED */
2062 /**
2063   * @}
2064   */
2065 
2066 /**
2067   * @}
2068   */
2069 
2070