1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_ll_rcc.c
4   * @author  MCD Application Team
5   * @brief   RCC LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * Copyright (c) 2022 STMicroelectronics.
10   * All rights reserved.
11   *
12   * This software is licensed under terms that can be found in the LICENSE file
13   * in the root directory of this software component.
14   * If no LICENSE file comes with this software, it is provided AS-IS.
15   *
16   ******************************************************************************
17   */
18 #if defined(USE_FULL_LL_DRIVER)
19 
20 /* Includes ------------------------------------------------------------------*/
21 #include "stm32c0xx_ll_rcc.h"
22 #ifdef  USE_FULL_ASSERT
23 #include "stm32_assert.h"
24 #else
25 #define assert_param(expr) ((void)0U)
26 #endif /* USE_FULL_ASSERT */
27 /** @addtogroup STM32C0xx_LL_Driver
28   * @{
29   */
30 
31 #if defined(RCC)
32 
33 /** @addtogroup RCC_LL
34   * @{
35   */
36 
37 /* Private types -------------------------------------------------------------*/
38 /* Private variables ---------------------------------------------------------*/
39 /* Private constants ---------------------------------------------------------*/
40 /* Private macros ------------------------------------------------------------*/
41 /** @addtogroup RCC_LL_Private_Macros
42   * @{
43   */
44 
45 #define IS_LL_RCC_USART_CLKSOURCE(__VALUE__)  ((__VALUE__) == LL_RCC_USART1_CLKSOURCE)
46 #define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__)    ((__VALUE__) == LL_RCC_I2C1_CLKSOURCE)
47 #define IS_LL_RCC_ADC_CLKSOURCE(__VALUE__)    ((__VALUE__) == LL_RCC_ADC_CLKSOURCE)
48 #define IS_LL_RCC_I2S_CLKSOURCE(__VALUE__)    ((__VALUE__) == LL_RCC_I2S1_CLKSOURCE)
49 #if defined (USB_DRD_FS)
50 #define IS_LL_RCC_USB_CLKSOURCE(__VALUE__)    ((__VALUE__) == LL_RCC_USB_CLKSOURCE)
51 #endif /* USB_DRD_FS */
52 
53 /**
54   * @}
55   */
56 
57 /* Private function prototypes -----------------------------------------------*/
58 /** @defgroup RCC_LL_Private_Functions RCC Private functions
59   * @{
60   */
61 uint32_t RCC_GetSystemClockFreq(void);
62 uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency);
63 uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency);
64 /**
65   * @}
66   */
67 
68 
69 /* Exported functions --------------------------------------------------------*/
70 /** @addtogroup RCC_LL_Exported_Functions
71   * @{
72   */
73 
74 /** @addtogroup RCC_LL_EF_Init
75   * @{
76   */
77 
78 /**
79   * @brief  Reset the RCC clock configuration to the default reset state.
80   * @note   The default reset state of the clock configuration is given below:
81   *         - HSI ON and used as system clock source
82   *         - HSE OFF
83   *         - AHB and APB1 prescaler set to 1.
84   *         - CSS, MCO OFF
85   *         - All interrupts disabled
86   * @note   This function does not modify the configuration of the
87   *         - Peripheral clocks
88   *         - LSI, LSE and RTC clocks
89   * @retval An ErrorStatus enumeration value:
90   *          - SUCCESS: RCC registers are de-initialized
91   *          - ERROR: not applicable
92   */
LL_RCC_DeInit(void)93 ErrorStatus LL_RCC_DeInit(void)
94 {
95   /* Set HSION bit and wait for HSI READY bit */
96   LL_RCC_HSI_Enable();
97   while (LL_RCC_HSI_IsReady() != 1U)
98   {}
99 
100   /* Set HSITRIM bits to reset value*/
101   LL_RCC_HSI_SetCalibTrimming(0x40U);
102 
103   /* Reset CFGR register */
104   LL_RCC_WriteReg(CFGR, 0x00000000U);
105 
106   /* Reset whole CR register but HSI in 2 steps in case HSEBYP is set */
107   LL_RCC_WriteReg(CR, RCC_CR_HSION);
108   while (LL_RCC_HSE_IsReady() != 0U)
109   {}
110   LL_RCC_WriteReg(CR, RCC_CR_HSION);
111 
112   /* Disable all interrupts */
113   LL_RCC_WriteReg(CIER, 0x00000000U);
114 
115   /* Clear all interrupts flags */
116   LL_RCC_WriteReg(CICR, 0xFFFFFFFFU);
117 
118   return SUCCESS;
119 }
120 
121 /**
122   * @}
123   */
124 
125 /** @addtogroup RCC_LL_EF_Get_Freq
126   * @brief  Return the frequencies of different on chip clocks;  System, AHB and APB1 buses clocks
127   *         and different peripheral clocks available on the device.
128   * @note   If SYSCLK source is HSI, function returns values based on HSI_VALUE divided by HSI division factor(**)
129   * @note   If SYSCLK source is HSE, function returns values based on HSE_VALUE(***)
130   * @note   (**) HSI_VALUE is a constant defined in this file (default value
131   *              48 MHz) but the real value may vary depending on the variations
132   *              in voltage and temperature.
133   * @note   (***) HSE_VALUE is a constant defined in this file (default value
134   *               48 MHz), user has to ensure that HSE_VALUE is same as the real
135   *               frequency of the crystal used. Otherwise, this function may
136   *               have wrong result.
137   * @note   The result of this function could be incorrect when using fractional
138   *         value for HSE crystal.
139   * @note   This function can be used by the user application to compute the
140   *         baud-rate for the communication peripherals or configure other parameters.
141   * @{
142   */
143 
144 /**
145   * @brief  Return the frequencies of different on chip clocks;  System, AHB and APB1 buses clocks
146   * @note   Each time SYSCLK, HCLK and/or PCLK1 clock changes, this function
147   *         must be called to update structure fields. Otherwise, any
148   *         configuration based on this function will be incorrect.
149   * @param  RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies
150   * @retval None
151   */
LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef * RCC_Clocks)152 void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks)
153 {
154   /* Get SYSCLK frequency */
155   RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq();
156 
157   /* HCLK clock frequency */
158   RCC_Clocks->HCLK_Frequency   = RCC_GetHCLKClockFreq(RCC_Clocks->SYSCLK_Frequency);
159 
160   /* PCLK1 clock frequency */
161   RCC_Clocks->PCLK1_Frequency  = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK_Frequency);
162 }
163 
164 /**
165   * @brief  Return USARTx clock frequency
166   * @param  USARTxSource This parameter can be one of the following values:
167   *         @arg @ref LL_RCC_USART1_CLKSOURCE
168   * @retval USART clock frequency (in Hz)
169   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
170   */
LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource)171 uint32_t LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource)
172 {
173   uint32_t usart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
174 
175   /* Check parameter */
176   assert_param(IS_LL_RCC_USART_CLKSOURCE(USARTxSource));
177 
178   if (USARTxSource == LL_RCC_USART1_CLKSOURCE)
179   {
180     /* USART1CLK clock frequency */
181     switch (LL_RCC_GetUSARTClockSource(USARTxSource))
182     {
183       case LL_RCC_USART1_CLKSOURCE_SYSCLK: /* USART1 Clock is System Clock */
184         usart_frequency = RCC_GetSystemClockFreq();
185         break;
186 
187       case LL_RCC_USART1_CLKSOURCE_HSIKER:    /* USART1 Clock is HSI Kernel */
188         if (LL_RCC_HSI_IsReady() == 1U)
189         {
190           usart_frequency = (HSI_VALUE / ((LL_RCC_HSIKER_GetDivider() >> RCC_CR_HSIKERDIV_Pos) + 1U));
191         }
192         break;
193 
194       case LL_RCC_USART1_CLKSOURCE_LSE:    /* USART1 Clock is LSE Osc. */
195         if (LL_RCC_LSE_IsReady() == 1U)
196         {
197           usart_frequency = LSE_VALUE;
198         }
199         break;
200 
201       case LL_RCC_USART1_CLKSOURCE_PCLK1:  /* USART1 Clock is PCLK1 */
202       default:
203         usart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
204         break;
205     }
206   }
207   else
208   {
209   }
210   return usart_frequency;
211 }
212 
213 /**
214   * @brief  Return I2Cx clock frequency
215   * @param  I2CxSource This parameter can be one of the following values:
216   *         @arg @ref LL_RCC_I2C1_CLKSOURCE
217   *         @arg @ref LL_RCC_I2C2_CLKSOURCE (*)
218   * @retval I2C clock frequency (in Hz)
219   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NO indicates that HSI oscillator is not ready
220   * @note (*) peripheral not available on all devices
221   */
LL_RCC_GetI2CClockFreq(uint32_t I2CxSource)222 uint32_t LL_RCC_GetI2CClockFreq(uint32_t I2CxSource)
223 {
224   uint32_t i2c_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
225 
226   /* Check parameter */
227   assert_param(IS_LL_RCC_I2C_CLKSOURCE(I2CxSource));
228 
229   if (I2CxSource == LL_RCC_I2C1_CLKSOURCE)
230   {
231     /* I2C1 CLK clock frequency */
232     switch (LL_RCC_GetI2CClockSource(I2CxSource))
233     {
234       case LL_RCC_I2C1_CLKSOURCE_SYSCLK: /* I2C1 Clock is System Clock */
235         i2c_frequency = RCC_GetSystemClockFreq();
236         break;
237 
238       case LL_RCC_I2C1_CLKSOURCE_HSIKER:    /* I2C1 Clock is HSI Kernel */
239         if (LL_RCC_HSI_IsReady() == 1U)
240         {
241           i2c_frequency = (HSI_VALUE / ((LL_RCC_HSIKER_GetDivider() >> RCC_CR_HSIKERDIV_Pos) + 1U));
242         }
243         break;
244 
245       case LL_RCC_I2C1_CLKSOURCE_PCLK1:  /* I2C1 Clock is PCLK1 */
246       default:
247         i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
248         break;
249     }
250   }
251 #if defined(I2C2)
252   else if (I2CxSource == LL_RCC_I2C2_CLKSOURCE)
253   {
254     /* I2C2 CLK clock frequency */
255     switch (LL_RCC_GetI2CClockSource(I2CxSource))
256     {
257       case LL_RCC_I2C2_CLKSOURCE_SYSCLK: /* I2C2 Clock is System Clock */
258         i2c_frequency = RCC_GetSystemClockFreq();
259         break;
260 
261       case LL_RCC_I2C2_CLKSOURCE_HSIKER:    /* I2C2 Clock is HSI Kernel */
262         if (LL_RCC_HSI_IsReady() == 1U)
263         {
264           i2c_frequency = (HSI_VALUE / ((LL_RCC_HSIKER_GetDivider() >> RCC_CR_HSIKERDIV_Pos) + 1U));
265         }
266         break;
267 
268       case LL_RCC_I2C2_CLKSOURCE_PCLK1:  /* I2C2 Clock is PCLK1 */
269       default:
270         i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
271         break;
272     }
273   }
274 #endif /* I2C2 */
275 
276   return i2c_frequency;
277 }
278 
279 /**
280   * @brief  Return I2Sx clock frequency
281   * @param  I2SxSource This parameter can be one of the following values:
282   *         @arg @ref LL_RCC_I2S1_CLKSOURCE
283   * @retval I2S clock frequency (in Hz)
284   *         @arg @ref  LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
285   */
LL_RCC_GetI2SClockFreq(uint32_t I2SxSource)286 uint32_t LL_RCC_GetI2SClockFreq(uint32_t I2SxSource)
287 {
288   uint32_t i2s_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
289 
290   /* Check parameter */
291   assert_param(IS_LL_RCC_I2S_CLKSOURCE(I2SxSource));
292 
293   if (I2SxSource == LL_RCC_I2S1_CLKSOURCE)
294   {
295     /* I2S1 CLK clock frequency */
296     switch (LL_RCC_GetI2SClockSource(I2SxSource))
297     {
298       case LL_RCC_I2S1_CLKSOURCE_HSIKER:    /* I2S1 Clock is HSI Kernel */
299         if (LL_RCC_HSI_IsReady() == 1U)
300         {
301           i2s_frequency = (HSI_VALUE / ((LL_RCC_HSIKER_GetDivider() >> RCC_CR_HSIKERDIV_Pos) + 1U));
302         }
303         break;
304 
305       case LL_RCC_I2S1_CLKSOURCE_PIN:          /* I2S1 Clock is External clock */
306         i2s_frequency = EXTERNAL_CLOCK_VALUE;
307         break;
308 
309       case LL_RCC_I2S1_CLKSOURCE_SYSCLK: /* I2S1 Clock is System Clock */
310       default:
311         i2s_frequency = RCC_GetSystemClockFreq();
312         break;
313     }
314   }
315 
316   return i2s_frequency;
317 }
318 
319 /**
320   * @brief  Return ADCx clock frequency
321   * @param  ADCxSource This parameter can be one of the following values:
322   *         @arg @ref LL_RCC_ADC_CLKSOURCE
323   * @retval ADC clock frequency (in Hz)
324   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI) is not ready
325   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
326   */
LL_RCC_GetADCClockFreq(uint32_t ADCxSource)327 uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource)
328 {
329   uint32_t adc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
330 
331   /* Check parameter */
332   assert_param(IS_LL_RCC_ADC_CLKSOURCE(ADCxSource));
333 
334   /* ADCCLK clock frequency */
335   switch (LL_RCC_GetADCClockSource(ADCxSource))
336   {
337     case LL_RCC_ADC_CLKSOURCE_SYSCLK:        /* SYSCLK clock used as ADC clock source */
338       adc_frequency = RCC_GetSystemClockFreq();
339       break;
340     case LL_RCC_ADC_CLKSOURCE_HSIKER  :        /* HSI clock Kernel used as ADC clock source */
341       if (LL_RCC_HSI_IsReady() == 1U)
342       {
343         adc_frequency = (HSI_VALUE / ((LL_RCC_HSIKER_GetDivider() >> RCC_CR_HSIKERDIV_Pos) + 1U));
344       }
345       break;
346     default:
347       adc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
348       break;
349   }
350 
351   return adc_frequency;
352 }
353 
354 /**
355   * @brief  Return RTC clock frequency
356   * @retval RTC clock frequency (in Hz)
357   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillators (LSI, LSE or HSE) are not ready
358   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
359   */
LL_RCC_GetRTCClockFreq(void)360 uint32_t LL_RCC_GetRTCClockFreq(void)
361 {
362   uint32_t rtc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
363 
364   /* RTCCLK clock frequency */
365   switch (LL_RCC_GetRTCClockSource())
366   {
367     case LL_RCC_RTC_CLKSOURCE_LSE:       /* LSE clock used as RTC clock source */
368       if (LL_RCC_LSE_IsReady() == 1U)
369       {
370         rtc_frequency = LSE_VALUE;
371       }
372       break;
373 
374     case LL_RCC_RTC_CLKSOURCE_LSI:       /* LSI clock used as RTC clock source */
375       if (LL_RCC_LSI_IsReady() == 1U)
376       {
377         rtc_frequency = LSI_VALUE;
378       }
379       break;
380 
381     case LL_RCC_RTC_CLKSOURCE_HSE_DIV32:        /* HSE clock used as ADC clock source */
382       rtc_frequency = HSE_VALUE / 32U;
383       break;
384 
385     case LL_RCC_RTC_CLKSOURCE_NONE:          /* No clock used as RTC clock source */
386     default:
387       rtc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
388       break;
389   }
390 
391   return rtc_frequency;
392 }
393 
394 #if defined(USB_DRD_FS)
395 /**
396   * @brief  Return USBx clock frequency
397   * @param  USBxSource This parameter can be one of the following values:
398   *         @arg @ref LL_RCC_USB_CLKSOURCE
399   * @retval USB clock frequency (in Hz)
400   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI48) is not ready
401   *         - @ref  LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
402   */
LL_RCC_GetUSBClockFreq(uint32_t USBxSource)403 uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource)
404 {
405   uint32_t usb_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
406 
407   /* Check parameter */
408   assert_param(IS_LL_RCC_USB_CLKSOURCE(USBxSource));
409 
410   /* USBCLK clock frequency */
411   switch (LL_RCC_GetUSBClockSource(USBxSource))
412   {
413 #if defined(RCC_HSI48_SUPPORT)
414     case LL_RCC_USB_CLKSOURCE_HSI48:         /* HSI48 used as USB clock source */
415       if (LL_RCC_HSI48_IsReady() != 0U)
416       {
417         usb_frequency = HSI48_VALUE;
418       }
419       break;
420 #endif /* RCC_HSI48_SUPPORT */
421 
422     case LL_RCC_USB_CLKSOURCE_HSE:         /* HSE used as USB clock source */
423       if (LL_RCC_HSE_IsReady() != 0U)
424       {
425         usb_frequency = HSE_VALUE;
426       }
427       break;
428 
429     default:
430       usb_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
431       break;
432   }
433 
434   return usb_frequency;
435 }
436 #endif /* USB_DRD_FS */
437 
438 /**
439   * @}
440   */
441 
442 /**
443   * @}
444   */
445 
446 /** @addtogroup RCC_LL_Private_Functions
447   * @{
448   */
449 
450 /**
451   * @brief  Return SYSTEM clock frequency
452   * @retval SYSTEM clock frequency (in Hz)
453   */
RCC_GetSystemClockFreq(void)454 uint32_t RCC_GetSystemClockFreq(void)
455 {
456   uint32_t frequency;
457   uint32_t hsidiv;
458 #if defined(RCC_CR_SYSDIV)
459   uint32_t sysdiv = (uint32_t)(((RCC->CR & RCC_CR_SYSDIV) >> RCC_CR_SYSDIV_Pos) + 1U);
460 #endif /* RCC_CR_SYSDIV */
461 
462   /* Get SYSCLK source -------------------------------------------------------*/
463   switch (LL_RCC_GetSysClkSource())
464   {
465     case LL_RCC_SYS_CLKSOURCE_STATUS_HSE:  /* HSE used as system clock  source */
466       frequency = HSE_VALUE;
467       break;
468 
469     case LL_RCC_SYS_CLKSOURCE_STATUS_HSI:  /* HSI used as system clock  source */
470       hsidiv = (1UL << ((READ_BIT(RCC->CR, RCC_CR_HSIDIV)) >> RCC_CR_HSIDIV_Pos));
471       frequency = (HSI_VALUE / hsidiv);
472       break;
473 
474     case LL_RCC_SYS_CLKSOURCE_STATUS_LSE:  /* LSE used as system clock  source */
475       frequency = LSE_VALUE;
476       break;
477 
478     case LL_RCC_SYS_CLKSOURCE_STATUS_LSI:  /* LSI used as system clock  source */
479       frequency = LSI_VALUE;
480       break;
481 
482 #if defined(RCC_HSI48_SUPPORT)
483     case LL_RCC_SYS_CLKSOURCE_STATUS_HSIUSB48:  /* HSIUSB48 used as system clock  source */
484       frequency = HSI48_VALUE;
485       break;
486 #endif /* RCC_HSI48_SUPPORT */
487 
488     default:
489       hsidiv = (1UL << ((READ_BIT(RCC->CR, RCC_CR_HSIDIV)) >> RCC_CR_HSIDIV_Pos));
490       frequency = (HSI_VALUE / hsidiv);
491       break;
492   }
493 #if defined(RCC_CR_SYSDIV)
494   frequency = frequency / sysdiv;
495 #endif /* RCC_CR_SYSDIV */
496 
497   return frequency;
498 }
499 
500 /**
501   * @brief  Return HCLK clock frequency
502   * @param  SYSCLK_Frequency SYSCLK clock frequency
503   * @retval HCLK clock frequency (in Hz)
504   */
RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)505 uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)
506 {
507   /* HCLK clock frequency */
508   return __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler());
509 }
510 
511 /**
512   * @brief  Return PCLK1 clock frequency
513   * @param  HCLK_Frequency HCLK clock frequency
514   * @retval PCLK1 clock frequency (in Hz)
515   */
RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)516 uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)
517 {
518   /* PCLK1 clock frequency */
519   return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler());
520 }
521 
522 /**
523   * @}
524   */
525 
526 /**
527   * @}
528   */
529 
530 #endif /* defined(RCC) */
531 
532 /**
533   * @}
534   */
535 
536 #endif /* USE_FULL_LL_DRIVER */
537