1 | /**
|
2 | ******************************************************************************
|
3 | * @file system_stm32l1xx.c
|
4 | * @author MCD Application Team
|
5 | * @version V1.2.0
|
6 | * @date 6-August-2015
|
7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
|
8 | * This file contains the system clock configuration for STM32L1xx Ultra
|
9 | * Low power devices, and is generated by the clock configuration
|
10 | * tool STM32L1xx_Clock_Configuration_V1.2.0.xls
|
11 | *
|
12 | * 1. This file provides two functions and one global variable to be called from
|
13 | * user application:
|
14 | * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
|
15 | * and Divider factors, AHB/APBx prescalers and Flash settings),
|
16 | * depending on the configuration made in the clock xls tool.
|
17 | * This function is called at startup just after reset and
|
18 | * before branch to main program. This call is made inside
|
19 | * the "startup_stm32l1xx_xx.s" file.
|
20 | *
|
21 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
|
22 | * by the user application to setup the SysTick
|
23 | * timer or configure other parameters.
|
24 | *
|
25 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
|
26 | * be called whenever the core clock is changed
|
27 | * during program execution.
|
28 | *
|
29 | * 2. After each device reset the MSI (2.1 MHz Range) is used as system clock source.
|
30 | * Then SystemInit() function is called, in "startup_stm32l1xx_xx.s" file, to
|
31 | * configure the system clock before to branch to main program.
|
32 | *
|
33 | * 3. If the system clock source selected by user fails to startup, the SystemInit()
|
34 | * function will do nothing and MSI still used as system clock source. User can
|
35 | * add some code to deal with this issue inside the SetSysClock() function.
|
36 | *
|
37 | * 4. The default value of HSE crystal is set to 8MHz, refer to "HSE_VALUE" define
|
38 | * in "stm32l1xx.h" file. When HSE is used as system clock source, directly or
|
39 | * through PLL, and you are using different crystal you have to adapt the HSE
|
40 | * value to your own configuration.
|
41 | *
|
42 | * 5. This file configures the system clock as follows:
|
43 | *=============================================================================
|
44 | * System Clock Configuration
|
45 | *=============================================================================
|
46 | * System Clock source | PLL(HSE)
|
47 | *-----------------------------------------------------------------------------
|
48 | * SYSCLK | 24000000 Hz
|
49 | *-----------------------------------------------------------------------------
|
50 | * HCLK | 12000000 Hz
|
51 | *-----------------------------------------------------------------------------
|
52 | * AHB Prescaler | 2
|
53 | *-----------------------------------------------------------------------------
|
54 | * APB1 Prescaler | 1
|
55 | *-----------------------------------------------------------------------------
|
56 | * APB2 Prescaler | 1
|
57 | *-----------------------------------------------------------------------------
|
58 | * HSE Frequency | 12000000 Hz
|
59 | *-----------------------------------------------------------------------------
|
60 | * PLL DIV | 2
|
61 | *-----------------------------------------------------------------------------
|
62 | * PLL MUL | 4
|
63 | *-----------------------------------------------------------------------------
|
64 | * VDD | 1.8 V
|
65 | *-----------------------------------------------------------------------------
|
66 | * Vcore | 1.5 V (Range 2)
|
67 | *-----------------------------------------------------------------------------
|
68 | * Flash Latency | 1 WS
|
69 | *-----------------------------------------------------------------------------
|
70 | * Require 48MHz for USB clock | Disabled
|
71 | *-----------------------------------------------------------------------------
|
72 | *=============================================================================
|
73 | * @attention
|
74 | *
|
75 | * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
76 | *
|
77 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
78 | * You may not use this file except in compliance with the License.
|
79 | * You may obtain a copy of the License at:
|
80 | *
|
81 | * http://www.st.com/software_license_agreement_liberty_v2
|
82 | *
|
83 | * Unless required by applicable law or agreed to in writing, software
|
84 | * distributed under the License is distributed on an "AS IS" BASIS,
|
85 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
86 | * See the License for the specific language governing permissions and
|
87 | * limitations under the License.
|
88 | *
|
89 | ******************************************************************************
|
90 | */
|
91 |
|
92 | /** @addtogroup CMSIS
|
93 | * @{
|
94 | */
|
95 |
|
96 | /** @addtogroup stm32l1xx_system
|
97 | * @{
|
98 | */
|
99 |
|
100 | /** @addtogroup STM32L1xx_System_Private_Includes
|
101 | * @{
|
102 | */
|
103 |
|
104 | #include "stm32l1xx.h"
|
105 |
|
106 | /**
|
107 | * @}
|
108 | */
|
109 |
|
110 | /** @addtogroup STM32L1xx_System_Private_TypesDefinitions
|
111 | * @{
|
112 | */
|
113 |
|
114 | /**
|
115 | * @}
|
116 | */
|
117 |
|
118 | /** @addtogroup STM32L1xx_System_Private_Defines
|
119 | * @{
|
120 | */
|
121 |
|
122 | /*!< Uncomment the following line if you need to relocate your vector Table in
|
123 | Internal SRAM. */
|
124 | /* #define VECT_TAB_SRAM */
|
125 | #define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field.
|
126 | This value must be a multiple of 0x200. */
|
127 | /**
|
128 | * @}
|
129 | */
|
130 |
|
131 | /** @addtogroup STM32L1xx_System_Private_Macros
|
132 | * @{
|
133 | */
|
134 |
|
135 | /**
|
136 | * @}
|
137 | */
|
138 |
|
139 | /** @addtogroup STM32L1xx_System_Private_Variables
|
140 | * @{
|
141 | */
|
142 | uint32_t SystemCoreClock = 24000000;
|
143 | __I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};
|
144 | __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
145 |
|
146 | /**
|
147 | * @}
|
148 | */
|
149 |
|
150 | /** @addtogroup STM32L1xx_System_Private_FunctionPrototypes
|
151 | * @{
|
152 | */
|
153 |
|
154 | static void SetSysClock(void);
|
155 |
|
156 | /**
|
157 | * @}
|
158 | */
|
159 |
|
160 | /** @addtogroup STM32L1xx_System_Private_Functions
|
161 | * @{
|
162 | */
|
163 |
|
164 | /**
|
165 | * @brief Setup the microcontroller system.
|
166 | * Initialize the Embedded Flash Interface, the PLL and update the
|
167 | * SystemCoreClock variable.
|
168 | * @param None
|
169 | * @retval None
|
170 | */
|
171 | void SystemInit (void)
|
172 | {
|
173 | /*!< Set MSION bit */
|
174 | RCC->CR |= (uint32_t)0x00000100;
|
175 |
|
176 | /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
|
177 | RCC->CFGR &= (uint32_t)0x88FFC00C;
|
178 |
|
179 | /*!< Reset HSION, HSEON, CSSON and PLLON bits */
|
180 | RCC->CR &= (uint32_t)0xEEFEFFFE;
|
181 |
|
182 | /*!< Reset HSEBYP bit */
|
183 | RCC->CR &= (uint32_t)0xFFFBFFFF;
|
184 |
|
185 | /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
|
186 | RCC->CFGR &= (uint32_t)0xFF02FFFF;
|
187 |
|
188 | /*!< Disable all interrupts */
|
189 | RCC->CIR = 0x00000000;
|
190 |
|
191 | /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
|
192 | SetSysClock();
|
193 |
|
194 | #ifdef VECT_TAB_SRAM
|
195 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
|
196 | #else
|
197 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
|
198 | #endif
|
199 | }
|
200 |
|
201 | /**
|
202 | * @brief Update SystemCoreClock according to Clock Register Values
|
203 | * The SystemCoreClock variable contains the core clock (HCLK), it can
|
204 | * be used by the user application to setup the SysTick timer or configure
|
205 | * other parameters.
|
206 | *
|
207 | * @note Each time the core clock (HCLK) changes, this function must be called
|
208 | * to update SystemCoreClock variable value. Otherwise, any configuration
|
209 | * based on this variable will be incorrect.
|
210 | *
|
211 | * @note - The system frequency computed by this function is not the real
|
212 | * frequency in the chip. It is calculated based on the predefined
|
213 | * constant and the selected clock source:
|
214 | *
|
215 | * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI
|
216 | * value as defined by the MSI range.
|
217 | *
|
218 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
|
219 | *
|
220 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
|
221 | *
|
222 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
|
223 | * or HSI_VALUE(*) multiplied/divided by the PLL factors.
|
224 | *
|
225 | * (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value
|
226 | * 16 MHz) but the real value may vary depending on the variations
|
227 | * in voltage and temperature.
|
228 | *
|
229 | * (**) HSE_VALUE is a constant defined in stm32l1xx.h file (default value
|
230 | * 8 MHz), user has to ensure that HSE_VALUE is same as the real
|
231 | * frequency of the crystal used. Otherwise, this function may
|
232 | * have wrong result.
|
233 | *
|
234 | * - The result of this function could be not correct when using fractional
|
235 | * value for HSE crystal.
|
236 | * @param None
|
237 | * @retval None
|
238 | */
|
239 | void SystemCoreClockUpdate (void)
|
240 | {
|
241 | uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, msirange = 0;
|
242 |
|
243 | /* Get SYSCLK source -------------------------------------------------------*/
|
244 | tmp = RCC->CFGR & RCC_CFGR_SWS;
|
245 |
|
246 | switch (tmp)
|
247 | {
|
248 | case 0x00: /* MSI used as system clock */
|
249 | msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;
|
250 | SystemCoreClock = (32768 * (1 << (msirange + 1)));
|
251 | break;
|
252 | case 0x04: /* HSI used as system clock */
|
253 | SystemCoreClock = HSI_VALUE;
|
254 | break;
|
255 | case 0x08: /* HSE used as system clock */
|
256 | SystemCoreClock = HSE_VALUE;
|
257 | break;
|
258 | case 0x0C: /* PLL used as system clock */
|
259 | /* Get PLL clock source and multiplication factor ----------------------*/
|
260 | pllmul = RCC->CFGR & RCC_CFGR_PLLMUL;
|
261 | plldiv = RCC->CFGR & RCC_CFGR_PLLDIV;
|
262 | pllmul = PLLMulTable[(pllmul >> 18)];
|
263 | plldiv = (plldiv >> 22) + 1;
|
264 |
|
265 | pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
|
266 |
|
267 | if (pllsource == 0x00)
|
268 | {
|
269 | /* HSI oscillator clock selected as PLL clock entry */
|
270 | SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv);
|
271 | }
|
272 | else
|
273 | {
|
274 | /* HSE selected as PLL clock entry */
|
275 | SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv);
|
276 | }
|
277 | break;
|
278 | default: /* MSI used as system clock */
|
279 | msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;
|
280 | SystemCoreClock = (32768 * (1 << (msirange + 1)));
|
281 | break;
|
282 | }
|
283 | /* Compute HCLK clock frequency --------------------------------------------*/
|
284 | /* Get HCLK prescaler */
|
285 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
|
286 | /* HCLK clock frequency */
|
287 | SystemCoreClock >>= tmp;
|
288 | }
|
289 |
|
290 | /**
|
291 | * @brief Configures the System clock frequency, AHB/APBx prescalers and Flash
|
292 | * settings.
|
293 | * @note This function should be called only once the RCC clock configuration
|
294 | * is reset to the default reset state (done in SystemInit() function).
|
295 | * @param None
|
296 | * @retval None
|
297 | */
|
298 | static void SetSysClock(void)
|
299 | {
|
300 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
301 |
|
302 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
|
303 | /* Enable HSE */
|
304 | RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
305 |
|
306 | /* Wait till HSE is ready and if Time out is reached exit */
|
307 | do
|
308 | {
|
309 | HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
310 | StartUpCounter++;
|
311 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
312 |
|
313 | if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
314 | {
|
315 | HSEStatus = (uint32_t)0x01;
|
316 | }
|
317 | else
|
318 | {
|
319 | HSEStatus = (uint32_t)0x00;
|
320 | }
|
321 |
|
322 | if (HSEStatus == (uint32_t)0x01)
|
323 | {
|
324 | /* Enable 64-bit access */
|
325 | FLASH->ACR |= FLASH_ACR_ACC64;
|
326 |
|
327 | /* Enable Prefetch Buffer */
|
328 | FLASH->ACR |= FLASH_ACR_PRFTEN;
|
329 |
|
330 | /* Flash 1 wait state */
|
331 | FLASH->ACR |= FLASH_ACR_LATENCY;
|
332 |
|
333 | /* Power enable */
|
334 | RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
335 |
|
336 | /* Select the Voltage Range 2 (1.5 V) */
|
337 | PWR->CR = PWR_CR_VOS_1;
|
338 |
|
339 | /* Wait Until the Voltage Regulator is ready */
|
340 | while((PWR->CSR & PWR_CSR_VOSF) != RESET)
|
341 | {
|
342 | }
|
343 |
|
344 | /* HCLK = SYSCLK /2*/
|
345 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV2;
|
346 |
|
347 | /* PCLK2 = HCLK /1*/
|
348 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
349 |
|
350 | /* PCLK1 = HCLK /1*/
|
351 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
|
352 |
|
353 | /* PLL configuration */
|
354 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |
|
355 | RCC_CFGR_PLLDIV));
|
356 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL4 | RCC_CFGR_PLLDIV2);
|
357 |
|
358 | /* Enable PLL */
|
359 | RCC->CR |= RCC_CR_PLLON;
|
360 |
|
361 | /* Wait till PLL is ready */
|
362 | while((RCC->CR & RCC_CR_PLLRDY) == 0)
|
363 | {
|
364 | }
|
365 |
|
366 | /* Select PLL as system clock source */
|
367 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
368 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
369 |
|
370 | /* Wait till PLL is used as system clock source */
|
371 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
|
372 | {
|
373 | }
|
374 | }
|
375 | else
|
376 | {
|
377 | /* If HSE fails to start-up, the application will have wrong clock
|
378 | configuration. User can add here some code to deal with this error */
|
379 | }
|
380 | }
|
381 |
|
382 | /**
|
383 | * @}
|
384 | */
|
385 |
|
386 | /**
|
387 | * @}
|
388 | */
|
389 |
|
390 | /**
|
391 | * @}
|
392 | */
|
393 |
|
394 | /******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/
|