1 /**
2   ******************************************************************************
3   * @file    stm32l1xx_ll_rcc.c
4   * @author  MCD Application Team
5   * @brief   RCC LL module driver.
6   ******************************************************************************
7   * @attention
8   *
9   * <h2><center>&copy; Copyright(c) 2017 STMicroelectronics.
10   * All rights reserved.</center></h2>
11   *
12   * This software component is licensed by ST under BSD 3-Clause license,
13   * the "License"; You may not use this file except in compliance with the
14   * License. You may obtain a copy of the License at:
15   *                        opensource.org/licenses/BSD-3-Clause
16   *
17   ******************************************************************************
18   */
19 #if defined(USE_FULL_LL_DRIVER)
20 
21 /* Includes ------------------------------------------------------------------*/
22 #include "stm32l1xx_ll_rcc.h"
23 /** @addtogroup STM32L1xx_LL_Driver
24   * @{
25   */
26 
27 #if defined(RCC)
28 
29 /** @defgroup RCC_LL RCC
30   * @{
31   */
32 
33 /* Private types -------------------------------------------------------------*/
34 /* Private variables ---------------------------------------------------------*/
35 
36 /* Private constants ---------------------------------------------------------*/
37 /* Private macros ------------------------------------------------------------*/
38 /* Private function prototypes -----------------------------------------------*/
39 /** @defgroup RCC_LL_Private_Functions RCC Private functions
40   * @{
41   */
42 static uint32_t RCC_GetSystemClockFreq(void);
43 static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency);
44 static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency);
45 static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency);
46 static uint32_t RCC_PLL_GetFreqDomain_SYS(void);
47 /**
48   * @}
49   */
50 
51 
52 /* Exported functions --------------------------------------------------------*/
53 /** @addtogroup RCC_LL_Exported_Functions
54   * @{
55   */
56 
57 /** @addtogroup RCC_LL_EF_Init
58   * @{
59   */
60 
61 /**
62   * @brief  Reset the RCC clock configuration to the default reset state.
63   * @note   The default reset state of the clock configuration is given below:
64   *         - MSI  ON and used as system clock source
65   *         - HSE, HSI and PLL OFF
66   *         - AHB, APB1 and APB2 prescaler set to 1.
67   *         - CSS, MCO OFF
68   *         - All interrupts disabled
69   * @note   This function doesn't modify the configuration of the
70   *         - Peripheral clocks
71   *         - LSI, LSE and RTC clocks
72   * @retval An ErrorStatus enumeration value:
73   *          - SUCCESS: RCC registers are de-initialized
74   *          - ERROR: not applicable
75   */
LL_RCC_DeInit(void)76 ErrorStatus LL_RCC_DeInit(void)
77 {
78   __IO uint32_t vl_mask;
79 
80   /* Set MSION bit */
81   LL_RCC_MSI_Enable();
82 
83   /* Insure MSIRDY bit is set before writing default MSIRANGE value */
84   while (LL_RCC_MSI_IsReady() == 0U)
85   {
86     __NOP();
87   }
88 
89   /* Set MSIRANGE default value */
90   LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_5);
91   /* Set MSITRIM bits to the reset value*/
92   LL_RCC_MSI_SetCalibTrimming(0U);
93 
94   /* Set HSITRIM bits to the reset value*/
95   LL_RCC_HSI_SetCalibTrimming(0x10U);
96 
97   /* Reset SW, HPRE, PPRE and MCOSEL bits */
98   vl_mask = 0xFFFFFFFFU;
99   CLEAR_BIT(vl_mask, (RCC_CFGR_SW | RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2 | RCC_CFGR_MCOSEL));
100   LL_RCC_WriteReg(CFGR, vl_mask);
101 
102   /* Read CR register */
103   vl_mask = LL_RCC_ReadReg(CR);
104 
105   /* Reset HSION, HSEON, CSSON, PLLON bits */
106   CLEAR_BIT(vl_mask, (RCC_CR_PLLON | RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_HSION));
107   LL_RCC_WriteReg(CR, vl_mask);
108 
109   /* Reset HSEBYP bit */
110   LL_RCC_HSE_DisableBypass();
111 
112   /* Insure PLL is disabled before to reset PLLSRC/PLLMUL/PLLDIV in CFGR register */
113   while(LL_RCC_PLL_IsReady() != 0U) {};
114 
115   /* Reset CFGR register */
116   LL_RCC_WriteReg(CFGR, 0x00000000U);
117 
118   /* Disable all interrupts */
119   LL_RCC_WriteReg(CIR, 0x00000000U);
120 
121   /* Clear pending flags */
122 #if defined(RCC_LSECSS_SUPPORT)
123   vl_mask = (LL_RCC_CIR_LSIRDYC | LL_RCC_CIR_LSERDYC | LL_RCC_CIR_HSIRDYC | LL_RCC_CIR_HSERDYC | \
124              LL_RCC_CIR_PLLRDYC | LL_RCC_CIR_MSIRDYC | LL_RCC_CIR_LSECSSC | LL_RCC_CIR_CSSC);
125 #else
126   vl_mask = (LL_RCC_CIR_LSIRDYC | LL_RCC_CIR_LSERDYC | LL_RCC_CIR_HSIRDYC | LL_RCC_CIR_HSERDYC | \
127              LL_RCC_CIR_PLLRDYC | LL_RCC_CIR_MSIRDYC | LL_RCC_CIR_CSSC);
128 #endif /* RCC_LSECSS_SUPPORT */
129   LL_RCC_WriteReg(CIR, vl_mask);
130 
131   /* Clear reset flags */
132   LL_RCC_ClearResetFlags();
133 
134   return SUCCESS;
135 }
136 
137 /**
138   * @}
139   */
140 
141 /** @addtogroup RCC_LL_EF_Get_Freq
142   * @brief  Return the frequencies of different on chip clocks;  System, AHB, APB1 and APB2 buses clocks
143   *         and different peripheral clocks available on the device.
144   * @note   If SYSCLK source is MSI, function returns values based on MSI clock(*)
145   * @note   If SYSCLK source is HSI, function returns values based on HSI_VALUE(**)
146   * @note   If SYSCLK source is HSE, function returns values based on HSE_VALUE(***)
147   * @note   If SYSCLK source is PLL, function returns values based on
148   *         HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
149   * @note   (*) MSI clock depends on the selected MSI range but the real value
150   *             may vary depending on the variations in voltage and temperature.
151   * @note   (**) HSI_VALUE is a defined constant but the real value may vary
152   *              depending on the variations in voltage and temperature.
153   * @note   (***) HSE_VALUE is a defined constant, user has to ensure that
154   *               HSE_VALUE is same as the real frequency of the crystal used.
155   *               Otherwise, this function may have wrong result.
156   * @note   The result of this function could be incorrect when using fractional
157   *         value for HSE crystal.
158   * @note   This function can be used by the user application to compute the
159   *         baud-rate for the communication peripherals or configure other parameters.
160   * @{
161   */
162 
163 /**
164   * @brief  Return the frequencies of different on chip clocks;  System, AHB, APB1 and APB2 buses clocks
165   * @note   Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function
166   *         must be called to update structure fields. Otherwise, any
167   *         configuration based on this function will be incorrect.
168   * @param  RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies
169   * @retval None
170   */
LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef * RCC_Clocks)171 void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks)
172 {
173   /* Get SYSCLK frequency */
174   RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq();
175 
176   /* HCLK clock frequency */
177   RCC_Clocks->HCLK_Frequency   = RCC_GetHCLKClockFreq(RCC_Clocks->SYSCLK_Frequency);
178 
179   /* PCLK1 clock frequency */
180   RCC_Clocks->PCLK1_Frequency  = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK_Frequency);
181 
182   /* PCLK2 clock frequency */
183   RCC_Clocks->PCLK2_Frequency  = RCC_GetPCLK2ClockFreq(RCC_Clocks->HCLK_Frequency);
184 }
185 
186 /**
187   * @}
188   */
189 
190 /**
191   * @}
192   */
193 
194 /** @addtogroup RCC_LL_Private_Functions
195   * @{
196   */
197 
198 /**
199   * @brief  Return SYSTEM clock frequency
200   * @retval SYSTEM clock frequency (in Hz)
201   */
RCC_GetSystemClockFreq(void)202 static uint32_t RCC_GetSystemClockFreq(void)
203 {
204   uint32_t frequency;
205 
206   /* Get SYSCLK source -------------------------------------------------------*/
207   switch (LL_RCC_GetSysClkSource())
208   {
209     case LL_RCC_SYS_CLKSOURCE_STATUS_MSI:  /* MSI used as system clock source */
210       frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
211       break;
212 
213     case LL_RCC_SYS_CLKSOURCE_STATUS_HSI:  /* HSI used as system clock  source */
214       frequency = HSI_VALUE;
215       break;
216 
217     case LL_RCC_SYS_CLKSOURCE_STATUS_HSE:  /* HSE used as system clock  source */
218       frequency = HSE_VALUE;
219       break;
220 
221     case LL_RCC_SYS_CLKSOURCE_STATUS_PLL:  /* PLL used as system clock  source */
222       frequency = RCC_PLL_GetFreqDomain_SYS();
223       break;
224 
225     default:
226       frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_GetRange());
227       break;
228   }
229 
230   return frequency;
231 }
232 
233 /**
234   * @brief  Return HCLK clock frequency
235   * @param  SYSCLK_Frequency SYSCLK clock frequency
236   * @retval HCLK clock frequency (in Hz)
237   */
RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)238 static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)
239 {
240   /* HCLK clock frequency */
241   return __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler());
242 }
243 
244 /**
245   * @brief  Return PCLK1 clock frequency
246   * @param  HCLK_Frequency HCLK clock frequency
247   * @retval PCLK1 clock frequency (in Hz)
248   */
RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)249 static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)
250 {
251   /* PCLK1 clock frequency */
252   return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler());
253 }
254 
255 /**
256   * @brief  Return PCLK2 clock frequency
257   * @param  HCLK_Frequency HCLK clock frequency
258   * @retval PCLK2 clock frequency (in Hz)
259   */
RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency)260 static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency)
261 {
262   /* PCLK2 clock frequency */
263   return __LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler());
264 }
265 
266 /**
267   * @brief  Return PLL clock frequency used for system domain
268   * @retval PLL clock frequency (in Hz)
269   */
RCC_PLL_GetFreqDomain_SYS(void)270 static uint32_t RCC_PLL_GetFreqDomain_SYS(void)
271 {
272   uint32_t pllsource, pllinputfreq;
273 
274   /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL divider) * PLL Multiplicator */
275 
276   /* Get PLL source */
277   pllsource = LL_RCC_PLL_GetMainSource();
278 
279   switch (pllsource)
280   {
281     case LL_RCC_PLLSOURCE_HSI:       /* HSI used as PLL clock source */
282       pllinputfreq = HSI_VALUE;
283       break;
284 
285     case LL_RCC_PLLSOURCE_HSE:       /* HSE used as PLL clock source */
286       pllinputfreq = HSE_VALUE;
287       break;
288 
289     default:
290       pllinputfreq = HSI_VALUE;
291       break;
292   }
293   return __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetMultiplicator(), LL_RCC_PLL_GetDivider());
294 }
295 /**
296   * @}
297   */
298 
299 /**
300   * @}
301   */
302 
303 #endif /* defined(RCC) */
304 
305 /**
306   * @}
307   */
308 
309 #endif /* USE_FULL_LL_DRIVER */
310 
311 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
312