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