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