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