1 /**
2   ******************************************************************************
3   * @file    stm32l1xx_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   @verbatim
12   ==============================================================================
13                       ##### RCC specific features #####
14   ==============================================================================
15     [..]
16       After reset the device is running from multispeed internal oscillator clock
17       (MSI 2.097MHz) with Flash 0 wait state and Flash prefetch buffer is disabled,
18       and all peripherals are off except internal SRAM, Flash and JTAG.
19       (+) There is no prescaler on High speed (AHB) and Low speed (APB) buses;
20           all peripherals mapped on these buses are running at MSI speed.
21       (+) The clock for all peripherals is switched off, except the SRAM and FLASH.
22       (+) All GPIOs are in input floating state, except the JTAG pins which
23           are assigned to be used for debug purpose.
24     [..] Once the device started from reset, the user application has to:
25       (+) Configure the clock source to be used to drive the System clock
26           (if the application needs higher frequency/performance)
27       (+) Configure the System clock frequency and Flash settings
28       (+) Configure the AHB and APB buses prescalers
29       (+) Enable the clock for the peripheral(s) to be used
30       (+) Configure the clock source(s) for peripherals whose clocks are not
31           derived from the System clock (I2S, RTC, ADC, USB OTG FS/SDIO/RNG)
32           (*) SDIO only for STM32L1xxxD devices
33 
34                       ##### RCC Limitations #####
35   ==============================================================================
36     [..]
37       A delay between an RCC peripheral clock enable and the effective peripheral
38       enabling should be taken into account in order to manage the peripheral read/write
39       from/to registers.
40       (+) This delay depends on the peripheral mapping.
41         (++) AHB & APB peripherals, 1 dummy read is necessary
42 
43     [..]
44       Workarounds:
45       (#) For AHB & APB peripherals, a dummy read to the peripheral register has been
46           inserted in each __HAL_RCC_PPP_CLK_ENABLE() macro.
47 
48   @endverbatim
49   ******************************************************************************
50   * @attention
51   *
52   * <h2><center>&copy; Copyright(c) 2017 STMicroelectronics.
53   * All rights reserved.</center></h2>
54   *
55   * This software component is licensed by ST under BSD 3-Clause license,
56   * the "License"; You may not use this file except in compliance with the
57   * License. You may obtain a copy of the License at:
58   *                        opensource.org/licenses/BSD-3-Clause
59   *
60   ******************************************************************************
61   */
62 
63 /* Includes ------------------------------------------------------------------*/
64 #include "stm32l1xx_hal.h"
65 
66 /** @addtogroup STM32L1xx_HAL_Driver
67   * @{
68   */
69 
70 /** @defgroup RCC RCC
71 * @brief RCC HAL module driver
72   * @{
73   */
74 
75 #ifdef HAL_RCC_MODULE_ENABLED
76 
77 /* Private typedef -----------------------------------------------------------*/
78 /* Private define ------------------------------------------------------------*/
79 /* Private macro -------------------------------------------------------------*/
80 /** @defgroup RCC_Private_Macros RCC Private Macros
81   * @{
82   */
83 
84 #define MCO1_CLK_ENABLE()     __HAL_RCC_GPIOA_CLK_ENABLE()
85 #define MCO1_GPIO_PORT        GPIOA
86 #define MCO1_PIN              GPIO_PIN_8
87 
88 /**
89   * @}
90   */
91 
92 /* Private variables ---------------------------------------------------------*/
93 /** @defgroup RCC_Private_Variables RCC Private Variables
94   * @{
95   */
96 extern const uint8_t PLLMulTable[];          /* Defined in CMSIS (system_stm32l0xx.c)*/
97 /**
98   * @}
99   */
100 
101 /* Private function prototypes -----------------------------------------------*/
102 /** @defgroup RCC_Private_Functions RCC Private Functions
103   * @{
104   */
105 static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t MSIrange);
106 /**
107   * @}
108   */
109 
110 /* Exported functions ---------------------------------------------------------*/
111 
112 /** @defgroup RCC_Exported_Functions RCC Exported Functions
113   * @{
114   */
115 
116 /** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions
117   *  @brief    Initialization and Configuration functions
118   *
119   @verbatim
120   ===============================================================================
121            ##### Initialization and de-initialization functions #####
122   ===============================================================================
123     [..]
124       This section provides functions allowing to configure the internal/external oscillators
125       (MSI, HSE, HSI, LSE, LSI, PLL, CSS and MCO) and the System buses clocks (SYSCLK, AHB, APB1
126       and APB2).
127 
128     [..] Internal/external clock and PLL configuration
129       (#) MSI (Multispeed internal), Seven frequency ranges are available: 65.536 kHz,
130           131.072 kHz, 262.144 kHz, 524.288 kHz, 1.048 MHz, 2.097 MHz (default value) and 4.194 MHz.
131 
132       (#) HSI (high-speed internal), 16 MHz factory-trimmed RC used directly or through
133           the PLL as System clock source.
134       (#) LSI (low-speed internal), ~37 KHz low consumption RC used as IWDG and/or RTC
135           clock source.
136 
137       (#) HSE (high-speed external), 1 to 24 MHz crystal oscillator used directly or
138           through the PLL as System clock source. Can be used also as RTC clock source.
139 
140       (#) LSE (low-speed external), 32 KHz oscillator used as RTC clock source.
141 
142       (#) PLL (clocked by HSI or HSE), featuring different output clocks:
143         (++) The first output is used to generate the high speed system clock (up to 32 MHz)
144         (++) The second output is used to generate the clock for the USB OTG FS (48 MHz)
145 
146       (#) CSS (Clock security system), once enable using the macro __HAL_RCC_CSS_ENABLE()
147           and if a HSE clock failure occurs(HSE used directly or through PLL as System
148           clock source), the System clocks automatically switched to MSI and an interrupt
149           is generated if enabled. The interrupt is linked to the Cortex-M3 NMI
150           (Non-Maskable Interrupt) exception vector.
151 
152       (#) MCO1 (microcontroller clock output), used to output SYSCLK, HSI, LSI, MSI, LSE,
153           HSE or PLL clock (through a configurable prescaler) on PA8 pin.
154 
155     [..] System, AHB and APB buses clocks configuration
156       (#) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI,
157           HSE and PLL.
158           The AHB clock (HCLK) is derived from System clock through configurable
159           prescaler and used to clock the CPU, memory and peripherals mapped
160           on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived
161           from AHB clock through configurable prescalers and used to clock
162           the peripherals mapped on these buses. You can use
163           "@ref HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks.
164 
165       -@- All the peripheral clocks are derived from the System clock (SYSCLK) except:
166           (+@) RTC: RTC clock can be derived either from the LSI, LSE or HSE clock
167               divided by 2 to 16. You have to use @ref __HAL_RCC_RTC_CONFIG() and @ref __HAL_RCC_RTC_ENABLE()
168               macros to configure this clock.
169           (+@) LCD: LCD clock can be derived either from the LSI, LSE or HSE clock
170               divided by 2 to 16. You have to use @ref __HAL_RCC_LCD_CONFIG()
171               macros to configure this clock.
172           (+@) USB OTG FS: USB OTG FS require a frequency equal to 48 MHz
173               to work correctly. This clock is derived of the main PLL through PLL Multiplier.
174 
175           (+@) IWDG clock which is always the LSI clock.
176 
177       (#) The maximum frequency of the SYSCLK and HCLK is 32 MHz, PCLK2 32 MHz
178           and PCLK1 32 MHz. Depending on the device voltage range, the maximum
179           frequency should be adapted accordingly.
180   @endverbatim
181   * @{
182   */
183 
184 /*
185   Additional consideration on the HCLK based on Latency settings:
186   +----------------------------------------------------------------------+
187   | Latency       |                HCLK clock frequency (MHz)            |
188   |               |------------------------------------------------------|
189   |               | voltage range 1  | voltage range 2 | voltage range 3 |
190   |               |      1.8 V       |     1.5 V       |      1.2 V      |
191   |---------------|------------------|-----------------|-----------------|
192   |0WS(1CPU cycle)| 0 < HCLK <= 16   | 0 < HCLK <= 8   | 0 < HCLK <= 2   |
193   |---------------|------------------|-----------------|-----------------|
194   |1WS(2CPU cycle)| 16 < HCLK <= 32  | 8 < HCLK <= 16  | 2 < HCLK <= 4   |
195   +----------------------------------------------------------------------+
196 
197   The following table gives the different clock source frequencies depending on the product
198   voltage range:
199   +------------------------------------------------------------------------------------------+
200   | Product voltage |                    Clock frequency                                     |
201   |                 |------------------|-----------------------------|-----------------------|
202   |      range      |   MSI   |   HSI  |              HSE            |          PLL          |
203   |-----------------|---------|--------|-----------------------------|-----------------------|
204   | Range 1 (1.8 V) | 4.2 MHz | 16 MHz | HSE 32 MHz (external clock) |         32 MHz        |
205   |                 |         |        |      or 24 MHz (crystal)    | (PLLVCO max = 96 MHz) |
206   |-----------------|---------|--------|-----------------------------|-----------------------|
207   | Range 2 (1.5 V) | 4.2 MHz | 16 MHz |         16 MHz              |         16 MHz        |
208   |                 |         |        |                             | (PLLVCO max = 48 MHz) |
209   |-----------------|---------|--------|-----------------------------|-----------------------|
210   | Range 3 (1.2 V) | 4.2 MHz |   NA   |         8 MHz               |           4 MHz       |
211   |                 |         |        |                             | (PLLVCO max = 24 MHz) |
212   +------------------------------------------------------------------------------------------+
213   */
214 
215 /**
216   * @brief  Resets the RCC clock configuration to the default reset state.
217   * @note   The default reset state of the clock configuration is given below:
218   *            - MSI ON and used as system clock source
219   *            - HSI, HSE and PLL  OFF
220   *            - AHB, APB1 and APB2 prescaler set to 1.
221   *            - CSS and MCO1 OFF
222   *            - All interrupts disabled
223   * @note   This function does not modify the configuration of the
224   *            - Peripheral clocks
225   *            - LSI, LSE and RTC clocks
226   * @retval HAL status
227   */
HAL_RCC_DeInit(void)228 HAL_StatusTypeDef HAL_RCC_DeInit(void)
229 {
230   uint32_t tickstart;
231   HAL_StatusTypeDef status;
232 
233   /* Set MSIClockRange, HSITRIM and MSITRIM bits to the reset values */
234   MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_MSITRIM | RCC_ICSCR_HSITRIM | RCC_ICSCR_MSIRANGE), \
235             ((RCC_MSICALIBRATION_DEFAULT << RCC_ICSCR_MSITRIM_Pos) | (RCC_HSICALIBRATION_DEFAULT << RCC_ICSCR_HSITRIM_Pos) | RCC_ICSCR_MSIRANGE_5));
236 
237   /* Set MSION bit */
238   SET_BIT(RCC->CR, RCC_CR_MSION);
239 
240   /* Get Start Tick*/
241   tickstart = HAL_GetTick();
242 
243   /* Wait till MSI is ready */
244   while (READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
245   {
246     if ((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
247     {
248       return HAL_TIMEOUT;
249     }
250   }
251 
252   /* Switch SYSCLK to MSI*/
253   CLEAR_BIT(RCC->CFGR, RCC_CFGR_SW);
254 
255   /* Wait till MSI as SYSCLK status is ready */
256   while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != 0U)
257   {
258     if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
259     {
260       return HAL_TIMEOUT;
261     }
262   }
263 
264   /* Update the SystemCoreClock global variable */
265   SystemCoreClock = MSI_VALUE;
266 
267   /* Configure the source of time base considering new system clock settings  */
268   status = HAL_InitTick(uwTickPrio);
269   if(status != HAL_OK)
270   {
271     return status;
272   }
273 
274   /* Reset HSION, HSEON, CSSON & PLLON bits */
275   CLEAR_BIT(RCC->CR, RCC_CR_HSION | RCC_CR_HSEON | RCC_CR_CSSON | RCC_CR_PLLON);
276   /* Reset HSEBYP bit */
277   CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
278 
279   /* Get Start Tick*/
280   tickstart = HAL_GetTick();
281 
282   /* Wait till PLL is not ready */
283   while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
284   {
285     if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
286     {
287       return HAL_TIMEOUT;
288     }
289   }
290 
291   /* Reset CFGR register */
292   CLEAR_REG(RCC->CFGR);
293 
294   /* Disable all interrupts */
295   CLEAR_REG(RCC->CIR);
296 
297   /* Clear all flags */
298 #if defined(RCC_LSECSS_SUPPORT)
299   WRITE_REG(RCC->CIR, RCC_CIR_LSIRDYC | RCC_CIR_LSERDYC | RCC_CIR_HSIRDYC | RCC_CIR_HSERDYC | RCC_CIR_PLLRDYC | RCC_CIR_MSIRDYC |  RCC_CIR_LSECSSC | RCC_CIR_CSSC);
300 #else
301   WRITE_REG(RCC->CIR, RCC_CIR_LSIRDYC | RCC_CIR_LSERDYC | RCC_CIR_HSIRDYC | RCC_CIR_HSERDYC | RCC_CIR_PLLRDYC | RCC_CIR_MSIRDYC |  RCC_CIR_CSSC);
302 #endif
303 
304   /* Clear all reset flags */
305   SET_BIT(RCC->CSR, RCC_CSR_RMVF);
306 
307   return HAL_OK;
308 }
309 
310 /**
311   * @brief  Initializes the RCC Oscillators according to the specified parameters in the
312   *         RCC_OscInitTypeDef.
313   * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
314   *         contains the configuration information for the RCC Oscillators.
315   * @note   The PLL is not disabled when used as system clock.
316   * @note   Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
317   *         supported by this macro. User should request a transition to LSE Off
318   *         first and then LSE On or LSE Bypass.
319   * @note   Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
320   *         supported by this macro. User should request a transition to HSE Off
321   *         first and then HSE On or HSE Bypass.
322   * @retval HAL status
323   */
HAL_RCC_OscConfig(RCC_OscInitTypeDef * RCC_OscInitStruct)324 HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
325 {
326   uint32_t tickstart;
327   HAL_StatusTypeDef status;
328   uint32_t sysclk_source, pll_config;
329 
330   /* Check the parameters */
331   if(RCC_OscInitStruct == NULL)
332   {
333     return HAL_ERROR;
334   }
335 
336   assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
337 
338   sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE();
339   pll_config = __HAL_RCC_GET_PLL_OSCSOURCE();
340 
341   /*------------------------------- HSE Configuration ------------------------*/
342   if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
343   {
344     /* Check the parameters */
345     assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
346 
347     /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
348     if((sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSE)
349        || ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_HSE)))
350     {
351       if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != 0U) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
352       {
353         return HAL_ERROR;
354       }
355     }
356     else
357     {
358       /* Set the new HSE configuration ---------------------------------------*/
359       __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
360 
361       /* Check the HSE State */
362       if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
363       {
364         /* Get Start Tick */
365         tickstart = HAL_GetTick();
366 
367         /* Wait till HSE is ready */
368         while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == 0U)
369         {
370           if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
371           {
372             return HAL_TIMEOUT;
373           }
374         }
375       }
376       else
377       {
378         /* Get Start Tick */
379         tickstart = HAL_GetTick();
380 
381         /* Wait till HSE is disabled */
382         while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != 0U)
383         {
384            if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
385           {
386             return HAL_TIMEOUT;
387           }
388         }
389       }
390     }
391   }
392   /*----------------------------- HSI Configuration --------------------------*/
393   if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
394   {
395     /* Check the parameters */
396     assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
397     assert_param(IS_RCC_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
398 
399     /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
400     if((sysclk_source == RCC_SYSCLKSOURCE_STATUS_HSI)
401        || ((sysclk_source == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (pll_config == RCC_PLLSOURCE_HSI)))
402     {
403       /* When HSI is used as system clock it will not disabled */
404       if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != 0U) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON))
405       {
406         return HAL_ERROR;
407       }
408       /* Otherwise, just the calibration is allowed */
409       else
410       {
411         /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
412         __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
413       }
414     }
415     else
416     {
417       /* Check the HSI State */
418       if(RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
419       {
420         /* Enable the Internal High Speed oscillator (HSI). */
421         __HAL_RCC_HSI_ENABLE();
422 
423         /* Get Start Tick */
424         tickstart = HAL_GetTick();
425 
426         /* Wait till HSI is ready */
427         while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == 0U)
428         {
429           if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE)
430           {
431             return HAL_TIMEOUT;
432           }
433         }
434 
435         /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
436         __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
437       }
438       else
439       {
440         /* Disable the Internal High Speed oscillator (HSI). */
441         __HAL_RCC_HSI_DISABLE();
442 
443         /* Get Start Tick */
444         tickstart = HAL_GetTick();
445 
446         /* Wait till HSI is disabled */
447         while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != 0U)
448         {
449           if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE)
450           {
451             return HAL_TIMEOUT;
452           }
453         }
454       }
455     }
456   }
457   /*----------------------------- MSI Configuration --------------------------*/
458   if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
459   {
460     /* When the MSI is used as system clock it will not be disabled */
461     if(sysclk_source == RCC_CFGR_SWS_MSI)
462     {
463       if((__HAL_RCC_GET_FLAG(RCC_FLAG_MSIRDY) != 0U) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF))
464       {
465         return HAL_ERROR;
466       }
467       /* Otherwise, just the calibration and MSI range change are allowed */
468       else
469       {
470        /* Check MSICalibrationValue and MSIClockRange input parameters */
471         assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue));
472         assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange));
473 
474         /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
475            must be correctly programmed according to the frequency of the CPU clock
476            (HCLK) and the supply voltage of the device. */
477         if(RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE())
478         {
479           /* First increase number of wait states update if necessary */
480           if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
481           {
482             return HAL_ERROR;
483           }
484 
485           /* Selects the Multiple Speed oscillator (MSI) clock range .*/
486           __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
487           /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
488           __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
489         }
490         else
491         {
492           /* Else, keep current flash latency while decreasing applies */
493           /* Selects the Multiple Speed oscillator (MSI) clock range .*/
494           __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
495           /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
496           __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
497 
498           /* Decrease number of wait states update if necessary */
499           if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
500           {
501             return HAL_ERROR;
502           }
503         }
504 
505         /* Update the SystemCoreClock global variable */
506         SystemCoreClock =  (32768U * (1UL << ((RCC_OscInitStruct->MSIClockRange >> RCC_ICSCR_MSIRANGE_Pos) + 1U)))
507                            >> AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
508 
509         /* Configure the source of time base considering new system clocks settings*/
510         status = HAL_InitTick(uwTickPrio);
511         if(status != HAL_OK)
512         {
513           return status;
514         }
515       }
516     }
517     else
518     {
519       /* Check MSI State */
520       assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState));
521 
522       /* Check the MSI State */
523       if(RCC_OscInitStruct->MSIState != RCC_MSI_OFF)
524       {
525         /* Enable the Multi Speed oscillator (MSI). */
526         __HAL_RCC_MSI_ENABLE();
527 
528         /* Get Start Tick */
529         tickstart = HAL_GetTick();
530 
531         /* Wait till MSI is ready */
532         while(__HAL_RCC_GET_FLAG(RCC_FLAG_MSIRDY) == 0U)
533         {
534           if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
535           {
536             return HAL_TIMEOUT;
537           }
538         }
539         /* Check MSICalibrationValue and MSIClockRange input parameters */
540         assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue));
541         assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange));
542 
543         /* Selects the Multiple Speed oscillator (MSI) clock range .*/
544         __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
545          /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
546         __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
547 
548       }
549       else
550       {
551         /* Disable the Multi Speed oscillator (MSI). */
552         __HAL_RCC_MSI_DISABLE();
553 
554         /* Get Start Tick */
555         tickstart = HAL_GetTick();
556 
557         /* Wait till MSI is ready */
558         while(__HAL_RCC_GET_FLAG(RCC_FLAG_MSIRDY) != 0U)
559         {
560           if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
561           {
562             return HAL_TIMEOUT;
563           }
564         }
565       }
566     }
567   }
568   /*------------------------------ LSI Configuration -------------------------*/
569   if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
570   {
571     /* Check the parameters */
572     assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
573 
574     /* Check the LSI State */
575     if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
576     {
577       /* Enable the Internal Low Speed oscillator (LSI). */
578       __HAL_RCC_LSI_ENABLE();
579 
580       /* Get Start Tick */
581       tickstart = HAL_GetTick();
582 
583       /* Wait till LSI is ready */
584       while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == 0U)
585       {
586         if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
587         {
588           return HAL_TIMEOUT;
589         }
590       }
591     }
592     else
593     {
594       /* Disable the Internal Low Speed oscillator (LSI). */
595       __HAL_RCC_LSI_DISABLE();
596 
597       /* Get Start Tick */
598       tickstart = HAL_GetTick();
599 
600       /* Wait till LSI is disabled */
601       while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != 0U)
602       {
603         if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
604         {
605           return HAL_TIMEOUT;
606         }
607       }
608     }
609   }
610   /*------------------------------ LSE Configuration -------------------------*/
611   if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
612   {
613     FlagStatus       pwrclkchanged = RESET;
614 
615     /* Check the parameters */
616     assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
617 
618     /* Update LSE configuration in Backup Domain control register    */
619     /* Requires to enable write access to Backup Domain of necessary */
620     if(__HAL_RCC_PWR_IS_CLK_DISABLED())
621     {
622       __HAL_RCC_PWR_CLK_ENABLE();
623       pwrclkchanged = SET;
624     }
625 
626     if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
627     {
628       /* Enable write access to Backup domain */
629       SET_BIT(PWR->CR, PWR_CR_DBP);
630 
631       /* Wait for Backup domain Write protection disable */
632       tickstart = HAL_GetTick();
633 
634       while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
635       {
636         if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
637         {
638           return HAL_TIMEOUT;
639         }
640       }
641     }
642 
643     /* Set the new LSE configuration -----------------------------------------*/
644     __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
645     /* Check the LSE State */
646     if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
647     {
648       /* Get Start Tick */
649       tickstart = HAL_GetTick();
650 
651       /* Wait till LSE is ready */
652       while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == 0U)
653       {
654         if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
655         {
656           return HAL_TIMEOUT;
657         }
658       }
659     }
660     else
661     {
662       /* Get Start Tick */
663       tickstart = HAL_GetTick();
664 
665       /* Wait till LSE is disabled */
666       while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != 0U)
667       {
668         if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
669         {
670           return HAL_TIMEOUT;
671         }
672       }
673     }
674 
675     /* Require to disable power clock if necessary */
676     if(pwrclkchanged == SET)
677     {
678       __HAL_RCC_PWR_CLK_DISABLE();
679     }
680   }
681 
682   /*-------------------------------- PLL Configuration -----------------------*/
683   /* Check the parameters */
684   assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
685   if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
686   {
687     /* Check if the PLL is used as system clock or not */
688     if(sysclk_source != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
689     {
690       if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
691       {
692         /* Check the parameters */
693         assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
694         assert_param(IS_RCC_PLL_MUL(RCC_OscInitStruct->PLL.PLLMUL));
695         assert_param(IS_RCC_PLL_DIV(RCC_OscInitStruct->PLL.PLLDIV));
696 
697         /* Disable the main PLL. */
698         __HAL_RCC_PLL_DISABLE();
699 
700         /* Get Start Tick */
701         tickstart = HAL_GetTick();
702 
703         /* Wait till PLL is disabled */
704         while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != 0U)
705         {
706           if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
707           {
708             return HAL_TIMEOUT;
709           }
710         }
711 
712         /* Configure the main PLL clock source, multiplication and division factors. */
713         __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
714                              RCC_OscInitStruct->PLL.PLLMUL,
715                              RCC_OscInitStruct->PLL.PLLDIV);
716         /* Enable the main PLL. */
717         __HAL_RCC_PLL_ENABLE();
718 
719         /* Get Start Tick */
720         tickstart = HAL_GetTick();
721 
722         /* Wait till PLL is ready */
723         while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == 0U)
724         {
725           if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
726           {
727             return HAL_TIMEOUT;
728           }
729         }
730       }
731       else
732       {
733         /* Disable the main PLL. */
734         __HAL_RCC_PLL_DISABLE();
735 
736         /* Get Start Tick */
737         tickstart = HAL_GetTick();
738 
739         /* Wait till PLL is disabled */
740         while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != 0U)
741         {
742           if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
743           {
744             return HAL_TIMEOUT;
745           }
746         }
747       }
748     }
749     else
750     {
751       /* Check if there is a request to disable the PLL used as System clock source */
752       if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF)
753       {
754         return HAL_ERROR;
755       }
756       else
757       {
758         /* Do not return HAL_ERROR if request repeats the current configuration */
759         pll_config = RCC->CFGR;
760         if((READ_BIT(pll_config, RCC_CFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
761            (READ_BIT(pll_config, RCC_CFGR_PLLMUL) != RCC_OscInitStruct->PLL.PLLMUL) ||
762            (READ_BIT(pll_config, RCC_CFGR_PLLDIV) != RCC_OscInitStruct->PLL.PLLDIV))
763         {
764           return HAL_ERROR;
765         }
766       }
767     }
768   }
769 
770   return HAL_OK;
771 }
772 
773 /**
774   * @brief  Initializes the CPU, AHB and APB buses clocks according to the specified
775   *         parameters in the RCC_ClkInitStruct.
776   * @param  RCC_ClkInitStruct pointer to an RCC_OscInitTypeDef structure that
777   *         contains the configuration information for the RCC peripheral.
778   * @param  FLatency FLASH Latency
779   *          The value of this parameter depend on device used within the same series
780   * @note   The SystemCoreClock CMSIS variable is used to store System Clock Frequency
781   *         and updated by @ref HAL_RCC_GetHCLKFreq() function called within this function
782   *
783   * @note   The MSI is used (enabled by hardware) as system clock source after
784   *         start-up from Reset, wake-up from STOP and STANDBY mode, or in case
785   *         of failure of the HSE used directly or indirectly as system clock
786   *         (if the Clock Security System CSS is enabled).
787   *
788   * @note   A switch from one clock source to another occurs only if the target
789   *         clock source is ready (clock stable after start-up delay or PLL locked).
790   *         If a clock source which is not yet ready is selected, the switch will
791   *         occur when the clock source will be ready.
792   *         You can use @ref HAL_RCC_GetClockConfig() function to know which clock is
793   *         currently used as system clock source.
794   * @note   Depending on the device voltage range, the software has to set correctly
795   *         HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency
796   *         (for more details refer to section above "Initialization/de-initialization functions")
797   * @retval HAL status
798   */
HAL_RCC_ClockConfig(RCC_ClkInitTypeDef * RCC_ClkInitStruct,uint32_t FLatency)799 HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
800 {
801   uint32_t tickstart;
802   HAL_StatusTypeDef status;
803 
804   /* Check the parameters */
805   if(RCC_ClkInitStruct == NULL)
806   {
807     return HAL_ERROR;
808   }
809 
810   assert_param(IS_FLASH_LATENCY(FLatency));
811 
812   /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
813   must be correctly programmed according to the frequency of the CPU clock
814   (HCLK) and the supply voltage of the device. */
815 
816   /* Increasing the number of wait states because of higher CPU frequency */
817   if(FLatency > __HAL_FLASH_GET_LATENCY())
818   {
819     /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
820     __HAL_FLASH_SET_LATENCY(FLatency);
821 
822     /* Check that the new number of wait states is taken into account to access the Flash
823     memory by reading the FLASH_ACR register */
824     if(__HAL_FLASH_GET_LATENCY() != FLatency)
825     {
826       return HAL_ERROR;
827     }
828   }
829 
830   /*-------------------------- HCLK Configuration --------------------------*/
831   if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
832   {
833     assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
834     MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
835   }
836 
837   /*------------------------- SYSCLK Configuration ---------------------------*/
838   if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
839   {
840     assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
841 
842     /* HSE is selected as System Clock Source */
843     if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
844     {
845       /* Check the HSE ready flag */
846       if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == 0U)
847       {
848         return HAL_ERROR;
849       }
850     }
851     /* PLL is selected as System Clock Source */
852     else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
853     {
854       /* Check the PLL ready flag */
855       if(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == 0U)
856       {
857         return HAL_ERROR;
858       }
859     }
860     /* HSI is selected as System Clock Source */
861     else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSI)
862     {
863       /* Check the HSI ready flag */
864       if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == 0U)
865       {
866         return HAL_ERROR;
867       }
868     }
869     /* MSI is selected as System Clock Source */
870     else
871     {
872       /* Check the MSI ready flag */
873       if(__HAL_RCC_GET_FLAG(RCC_FLAG_MSIRDY) == 0U)
874       {
875         return HAL_ERROR;
876       }
877     }
878     __HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
879 
880     /* Get Start Tick */
881     tickstart = HAL_GetTick();
882 
883     if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
884     {
885       while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_HSE)
886       {
887         if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
888         {
889           return HAL_TIMEOUT;
890         }
891       }
892     }
893     else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
894     {
895       while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
896       {
897         if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
898         {
899           return HAL_TIMEOUT;
900         }
901       }
902     }
903     else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSI)
904     {
905       while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_HSI)
906       {
907         if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
908         {
909           return HAL_TIMEOUT;
910         }
911       }
912     }
913     else
914     {
915       while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_MSI)
916       {
917         if((HAL_GetTick() - tickstart ) > CLOCKSWITCH_TIMEOUT_VALUE)
918         {
919           return HAL_TIMEOUT;
920         }
921       }
922     }
923   }
924   /* Decreasing the number of wait states because of lower CPU frequency */
925   if(FLatency < __HAL_FLASH_GET_LATENCY())
926   {
927     /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
928     __HAL_FLASH_SET_LATENCY(FLatency);
929 
930     /* Check that the new number of wait states is taken into account to access the Flash
931     memory by reading the FLASH_ACR register */
932     if(__HAL_FLASH_GET_LATENCY() != FLatency)
933     {
934       return HAL_ERROR;
935     }
936   }
937 
938   /*-------------------------- PCLK1 Configuration ---------------------------*/
939   if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
940   {
941     assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
942     MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
943   }
944 
945   /*-------------------------- PCLK2 Configuration ---------------------------*/
946   if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
947   {
948     assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
949     MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
950   }
951 
952   /* Update the SystemCoreClock global variable */
953   SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> RCC_CFGR_HPRE_Pos];
954 
955   /* Configure the source of time base considering new system clocks settings*/
956   status = HAL_InitTick(uwTickPrio);
957 
958   return status;
959 }
960 
961 /**
962   * @}
963   */
964 
965 /** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions
966   *  @brief   RCC clocks control functions
967   *
968   @verbatim
969   ===============================================================================
970                   ##### Peripheral Control functions #####
971   ===============================================================================
972     [..]
973     This subsection provides a set of functions allowing to control the RCC Clocks
974     frequencies.
975 
976   @endverbatim
977   * @{
978   */
979 
980 /**
981   * @brief  Selects the clock source to output on MCO pin.
982   * @note   MCO pin should be configured in alternate function mode.
983   * @param  RCC_MCOx specifies the output direction for the clock source.
984   *          This parameter can be one of the following values:
985   *            @arg @ref RCC_MCO1 Clock source to output on MCO1 pin(PA8).
986   * @param  RCC_MCOSource specifies the clock source to output.
987   *          This parameter can be one of the following values:
988   *            @arg @ref RCC_MCO1SOURCE_NOCLOCK     No clock selected as MCO clock
989   *            @arg @ref RCC_MCO1SOURCE_SYSCLK      System clock selected as MCO clock
990   *            @arg @ref RCC_MCO1SOURCE_HSI         HSI selected as MCO clock
991   *            @arg @ref RCC_MCO1SOURCE_HSE         HSE selected as MCO clock
992   *            @arg @ref RCC_MCO1SOURCE_MSI         MSI oscillator clock selected as MCO clock
993   *            @arg @ref RCC_MCO1SOURCE_PLLCLK      PLL clock selected as MCO clock
994   *            @arg @ref RCC_MCO1SOURCE_LSI         LSI clock selected as MCO clock
995   *            @arg @ref RCC_MCO1SOURCE_LSE         LSE clock selected as MCO clock
996   * @param  RCC_MCODiv specifies the MCO DIV.
997   *          This parameter can be one of the following values:
998   *            @arg @ref RCC_MCODIV_1 no division applied to MCO clock
999   *            @arg @ref RCC_MCODIV_2  division by 2 applied to MCO clock
1000   *            @arg @ref RCC_MCODIV_4  division by 4 applied to MCO clock
1001   *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
1002   *            @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock
1003   * @retval None
1004   */
HAL_RCC_MCOConfig(uint32_t RCC_MCOx,uint32_t RCC_MCOSource,uint32_t RCC_MCODiv)1005 void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
1006 {
1007   GPIO_InitTypeDef gpio;
1008 
1009   /* Check the parameters */
1010   assert_param(IS_RCC_MCO(RCC_MCOx));
1011   assert_param(IS_RCC_MCODIV(RCC_MCODiv));
1012   assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
1013 
1014   /* Configure the MCO1 pin in alternate function mode */
1015   gpio.Mode      = GPIO_MODE_AF_PP;
1016   gpio.Speed     = GPIO_SPEED_FREQ_HIGH;
1017   gpio.Pull      = GPIO_NOPULL;
1018   gpio.Pin       = MCO1_PIN;
1019   gpio.Alternate = GPIO_AF0_MCO;
1020 
1021   /* MCO1 Clock Enable */
1022   MCO1_CLK_ENABLE();
1023 
1024   HAL_GPIO_Init(MCO1_GPIO_PORT, &gpio);
1025 
1026   /* Configure the MCO clock source */
1027   __HAL_RCC_MCO1_CONFIG(RCC_MCOSource, RCC_MCODiv);
1028 }
1029 
1030 /**
1031   * @brief  Enables the Clock Security System.
1032   * @note   If a failure is detected on the HSE oscillator clock, this oscillator
1033   *         is automatically disabled and an interrupt is generated to inform the
1034   *         software about the failure (Clock Security System Interrupt, CSSI),
1035   *         allowing the MCU to perform rescue operations. The CSSI is linked to
1036   *         the Cortex-M3 NMI (Non-Maskable Interrupt) exception vector.
1037   * @retval None
1038   */
HAL_RCC_EnableCSS(void)1039 void HAL_RCC_EnableCSS(void)
1040 {
1041   *(__IO uint32_t *) RCC_CR_CSSON_BB = (uint32_t)ENABLE;
1042 }
1043 
1044 /**
1045   * @brief  Disables the Clock Security System.
1046   * @retval None
1047   */
HAL_RCC_DisableCSS(void)1048 void HAL_RCC_DisableCSS(void)
1049 {
1050   *(__IO uint32_t *) RCC_CR_CSSON_BB = (uint32_t)DISABLE;
1051 }
1052 
1053 /**
1054   * @brief  Returns the SYSCLK frequency
1055   * @note   The system frequency computed by this function is not the real
1056   *         frequency in the chip. It is calculated based on the predefined
1057   *         constant and the selected clock source:
1058   * @note     If SYSCLK source is MSI, function returns a value based on MSI
1059   *             Value as defined by the MSI range.
1060   * @note     If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
1061   * @note     If SYSCLK source is HSE, function returns a value based on HSE_VALUE(**)
1062   * @note     If SYSCLK source is PLL, function returns a value based on HSE_VALUE(**)
1063   *           or HSI_VALUE(*) multiplied/divided by the PLL factors.
1064   * @note     (*) HSI_VALUE is a constant defined in stm32l1xx_hal_conf.h file (default value
1065   *               16 MHz) but the real value may vary depending on the variations
1066   *               in voltage and temperature.
1067   * @note     (**) HSE_VALUE is a constant defined in stm32l1xx_hal_conf.h file (default value
1068   *                8 MHz), user has to ensure that HSE_VALUE is same as the real
1069   *                frequency of the crystal used. Otherwise, this function may
1070   *                have wrong result.
1071   *
1072   * @note   The result of this function could be not correct when using fractional
1073   *         value for HSE crystal.
1074   *
1075   * @note   This function can be used by the user application to compute the
1076   *         baud-rate for the communication peripherals or configure other parameters.
1077   *
1078   * @note   Each time SYSCLK changes, this function must be called to update the
1079   *         right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
1080   *
1081   * @retval SYSCLK frequency
1082   */
HAL_RCC_GetSysClockFreq(void)1083 uint32_t HAL_RCC_GetSysClockFreq(void)
1084 {
1085   uint32_t tmpreg, pllm, plld, pllvco, msiclkrange, sysclockfreq;
1086 
1087   tmpreg = RCC->CFGR;
1088 
1089   /* Get SYSCLK source -------------------------------------------------------*/
1090   switch (tmpreg & RCC_CFGR_SWS)
1091   {
1092     case RCC_SYSCLKSOURCE_STATUS_HSI:  /* HSI used as system clock source */
1093     {
1094       sysclockfreq = HSI_VALUE;
1095       break;
1096     }
1097     case RCC_SYSCLKSOURCE_STATUS_HSE:  /* HSE used as system clock */
1098     {
1099       sysclockfreq = HSE_VALUE;
1100       break;
1101     }
1102     case RCC_SYSCLKSOURCE_STATUS_PLLCLK:  /* PLL used as system clock */
1103     {
1104       pllm = PLLMulTable[(uint32_t)(tmpreg & RCC_CFGR_PLLMUL) >> RCC_CFGR_PLLMUL_Pos];
1105       plld = ((uint32_t)(tmpreg & RCC_CFGR_PLLDIV) >> RCC_CFGR_PLLDIV_Pos) + 1U;
1106       if (__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_HSI)
1107       {
1108         /* HSE used as PLL clock source */
1109         pllvco = (uint32_t)(((uint64_t)HSE_VALUE * (uint64_t)pllm) / (uint64_t)plld);
1110       }
1111       else
1112       {
1113         /* HSI used as PLL clock source */
1114         pllvco = (uint32_t)(((uint64_t)HSI_VALUE * (uint64_t)pllm) / (uint64_t)plld);
1115       }
1116       sysclockfreq = pllvco;
1117       break;
1118     }
1119     case RCC_SYSCLKSOURCE_STATUS_MSI:  /* MSI used as system clock source */
1120     default: /* MSI used as system clock */
1121     {
1122       msiclkrange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> RCC_ICSCR_MSIRANGE_Pos;
1123       sysclockfreq = (32768U * (1UL << (msiclkrange + 1U)));
1124       break;
1125     }
1126   }
1127   return sysclockfreq;
1128 }
1129 
1130 /**
1131   * @brief  Returns the HCLK frequency
1132   * @note   Each time HCLK changes, this function must be called to update the
1133   *         right HCLK value. Otherwise, any configuration based on this function will be incorrect.
1134   *
1135   * @note   The SystemCoreClock CMSIS variable is used to store System Clock Frequency
1136   *         and updated within this function
1137   * @retval HCLK frequency
1138   */
HAL_RCC_GetHCLKFreq(void)1139 uint32_t HAL_RCC_GetHCLKFreq(void)
1140 {
1141   return SystemCoreClock;
1142 }
1143 
1144 /**
1145   * @brief  Returns the PCLK1 frequency
1146   * @note   Each time PCLK1 changes, this function must be called to update the
1147   *         right PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
1148   * @retval PCLK1 frequency
1149   */
HAL_RCC_GetPCLK1Freq(void)1150 uint32_t HAL_RCC_GetPCLK1Freq(void)
1151 {
1152   /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
1153   return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]);
1154 }
1155 
1156 /**
1157   * @brief  Returns the PCLK2 frequency
1158   * @note   Each time PCLK2 changes, this function must be called to update the
1159   *         right PCLK2 value. Otherwise, any configuration based on this function will be incorrect.
1160   * @retval PCLK2 frequency
1161   */
HAL_RCC_GetPCLK2Freq(void)1162 uint32_t HAL_RCC_GetPCLK2Freq(void)
1163 {
1164   /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
1165   return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]);
1166 }
1167 
1168 /**
1169   * @brief  Configures the RCC_OscInitStruct according to the internal
1170   * RCC configuration registers.
1171   * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
1172   * will be configured.
1173   * @retval None
1174   */
HAL_RCC_GetOscConfig(RCC_OscInitTypeDef * RCC_OscInitStruct)1175 void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
1176 {
1177   /* Check the parameters */
1178   assert_param(RCC_OscInitStruct != (void *)NULL);
1179 
1180   /* Set all possible values for the Oscillator type parameter ---------------*/
1181   RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI  \
1182                   | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_MSI;
1183 
1184 
1185   /* Get the HSE configuration -----------------------------------------------*/
1186   if((RCC->CR &RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
1187   {
1188     RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
1189   }
1190   else if((RCC->CR &RCC_CR_HSEON) == RCC_CR_HSEON)
1191   {
1192     RCC_OscInitStruct->HSEState = RCC_HSE_ON;
1193   }
1194   else
1195   {
1196     RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
1197   }
1198 
1199   /* Get the HSI configuration -----------------------------------------------*/
1200   if((RCC->CR &RCC_CR_HSION) == RCC_CR_HSION)
1201   {
1202     RCC_OscInitStruct->HSIState = RCC_HSI_ON;
1203   }
1204   else
1205   {
1206     RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
1207   }
1208 
1209   RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos);
1210 
1211   /* Get the MSI configuration -----------------------------------------------*/
1212   if((RCC->CR &RCC_CR_MSION) == RCC_CR_MSION)
1213   {
1214     RCC_OscInitStruct->MSIState = RCC_MSI_ON;
1215   }
1216   else
1217   {
1218     RCC_OscInitStruct->MSIState = RCC_MSI_OFF;
1219   }
1220 
1221   RCC_OscInitStruct->MSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos);
1222   RCC_OscInitStruct->MSIClockRange = (uint32_t)((RCC->ICSCR & RCC_ICSCR_MSIRANGE));
1223 
1224   /* Get the LSE configuration -----------------------------------------------*/
1225   if((RCC->CSR &RCC_CSR_LSEBYP) == RCC_CSR_LSEBYP)
1226   {
1227     RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
1228   }
1229   else if((RCC->CSR &RCC_CSR_LSEON) == RCC_CSR_LSEON)
1230   {
1231     RCC_OscInitStruct->LSEState = RCC_LSE_ON;
1232   }
1233   else
1234   {
1235     RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
1236   }
1237 
1238   /* Get the LSI configuration -----------------------------------------------*/
1239   if((RCC->CSR &RCC_CSR_LSION) == RCC_CSR_LSION)
1240   {
1241     RCC_OscInitStruct->LSIState = RCC_LSI_ON;
1242   }
1243   else
1244   {
1245     RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
1246   }
1247 
1248 
1249   /* Get the PLL configuration -----------------------------------------------*/
1250   if((RCC->CR &RCC_CR_PLLON) == RCC_CR_PLLON)
1251   {
1252     RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
1253   }
1254   else
1255   {
1256     RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
1257   }
1258   RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->CFGR & RCC_CFGR_PLLSRC);
1259   RCC_OscInitStruct->PLL.PLLMUL = (uint32_t)(RCC->CFGR & RCC_CFGR_PLLMUL);
1260   RCC_OscInitStruct->PLL.PLLDIV = (uint32_t)(RCC->CFGR & RCC_CFGR_PLLDIV);
1261 }
1262 
1263 /**
1264   * @brief  Get the RCC_ClkInitStruct according to the internal
1265   * RCC configuration registers.
1266   * @param  RCC_ClkInitStruct pointer to an RCC_ClkInitTypeDef structure that
1267   * contains the current clock configuration.
1268   * @param  pFLatency Pointer on the Flash Latency.
1269   * @retval None
1270   */
HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef * RCC_ClkInitStruct,uint32_t * pFLatency)1271 void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t *pFLatency)
1272 {
1273   /* Check the parameters */
1274   assert_param(RCC_ClkInitStruct != (void *)NULL);
1275   assert_param(pFLatency != (void *)NULL);
1276 
1277   /* Set all possible values for the Clock type parameter --------------------*/
1278   RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
1279 
1280   /* Get the SYSCLK configuration --------------------------------------------*/
1281   RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW);
1282 
1283   /* Get the HCLK configuration ----------------------------------------------*/
1284   RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE);
1285 
1286   /* Get the APB1 configuration ----------------------------------------------*/
1287   RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1);
1288 
1289   /* Get the APB2 configuration ----------------------------------------------*/
1290   RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3U);
1291 
1292   /* Get the Flash Wait State (Latency) configuration ------------------------*/
1293   *pFLatency = __HAL_FLASH_GET_LATENCY();
1294 }
1295 
1296 /**
1297   * @brief This function handles the RCC CSS interrupt request.
1298   * @note This API should be called under the NMI_Handler().
1299   * @retval None
1300   */
HAL_RCC_NMI_IRQHandler(void)1301 void HAL_RCC_NMI_IRQHandler(void)
1302 {
1303   /* Check RCC CSSF flag  */
1304   if(__HAL_RCC_GET_IT(RCC_IT_CSS))
1305   {
1306     /* RCC Clock Security System interrupt user callback */
1307     HAL_RCC_CSSCallback();
1308 
1309     /* Clear RCC CSS pending bit */
1310     __HAL_RCC_CLEAR_IT(RCC_IT_CSS);
1311   }
1312 }
1313 
1314 /**
1315   * @brief  RCC Clock Security System interrupt callback
1316   * @retval none
1317   */
HAL_RCC_CSSCallback(void)1318 __weak void HAL_RCC_CSSCallback(void)
1319 {
1320   /* NOTE : This function Should not be modified, when the callback is needed,
1321     the HAL_RCC_CSSCallback could be implemented in the user file
1322     */
1323 }
1324 
1325 /**
1326   * @}
1327   */
1328 
1329 /**
1330   * @}
1331   */
1332 
1333 /* Private function prototypes -----------------------------------------------*/
1334 /** @addtogroup RCC_Private_Functions
1335   * @{
1336   */
1337 /**
1338   * @brief  Update number of Flash wait states in line with MSI range and current
1339             voltage range
1340   * @param  MSIrange  MSI range value from RCC_MSIRANGE_0 to RCC_MSIRANGE_6
1341   * @retval HAL status
1342   */
RCC_SetFlashLatencyFromMSIRange(uint32_t MSIrange)1343 static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t MSIrange)
1344 {
1345   uint32_t vos;
1346   uint32_t latency = FLASH_LATENCY_0;  /* default value 0WS */
1347 
1348   /* HCLK can reach 4 MHz only if AHB prescaler = 1 */
1349   if (READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)
1350   {
1351     if(__HAL_RCC_PWR_IS_CLK_ENABLED())
1352     {
1353       vos = READ_BIT(PWR->CR, PWR_CR_VOS);
1354     }
1355     else
1356     {
1357       __HAL_RCC_PWR_CLK_ENABLE();
1358       vos = READ_BIT(PWR->CR, PWR_CR_VOS);
1359       __HAL_RCC_PWR_CLK_DISABLE();
1360     }
1361 
1362     /* Check if need to set latency 1 only for Range 3 & HCLK = 4MHz */
1363     if((vos == PWR_REGULATOR_VOLTAGE_SCALE3) && (MSIrange == RCC_MSIRANGE_6))
1364     {
1365       latency = FLASH_LATENCY_1; /* 1WS */
1366     }
1367   }
1368 
1369   __HAL_FLASH_SET_LATENCY(latency);
1370 
1371   /* Check that the new number of wait states is taken into account to access the Flash
1372      memory by reading the FLASH_ACR register */
1373   if(__HAL_FLASH_GET_LATENCY() != latency)
1374   {
1375     return HAL_ERROR;
1376   }
1377 
1378   return HAL_OK;
1379 }
1380 
1381 /**
1382   * @}
1383   */
1384 
1385 #endif /* HAL_RCC_MODULE_ENABLED */
1386 /**
1387   * @}
1388   */
1389 
1390 /**
1391   * @}
1392   */
1393 
1394 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1395