1 /**
2 ******************************************************************************
3 * @file system_stm32h7xx.c
4 * @author MCD Application Team
5 * @brief CMSIS Cortex-Mx Device Peripheral Access Layer System Source File.
6 *
7 * This file provides two functions and one global variable to be called from
8 * user application:
9 * - SystemInit(): This function is called at startup just after reset and
10 * before branch to main program. This call is made inside
11 * the "startup_stm32h7xx.s" file.
12 *
13 * - SystemCoreClock variable: Contains the core clock, it can be used
14 * by the user application to setup the SysTick
15 * timer or configure other parameters.
16 *
17 * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
18 * be called whenever the core clock is changed
19 * during program execution.
20 *
21 *
22 ******************************************************************************
23 * @attention
24 *
25 * Copyright (c) 2017 STMicroelectronics.
26 * All rights reserved.
27 *
28 * This software is licensed under terms that can be found in the LICENSE file
29 * in the root directory of this software component.
30 * If no LICENSE file comes with this software, it is provided AS-IS.
31 *
32 ******************************************************************************
33 */
34
35 /** @addtogroup CMSIS
36 * @{
37 */
38
39 /** @addtogroup stm32h7xx_system
40 * @{
41 */
42
43 /** @addtogroup STM32H7xx_System_Private_Includes
44 * @{
45 */
46
47 #include "stm32h7xx.h"
48 #include <math.h>
49
50 #if !defined (HSE_VALUE)
51 #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
52 #endif /* HSE_VALUE */
53
54 #if !defined (CSI_VALUE)
55 #define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
56 #endif /* CSI_VALUE */
57
58 #if !defined (HSI_VALUE)
59 #define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/
60 #endif /* HSI_VALUE */
61
62
63 /**
64 * @}
65 */
66
67 /** @addtogroup STM32H7xx_System_Private_TypesDefinitions
68 * @{
69 */
70
71 /**
72 * @}
73 */
74
75 /** @addtogroup STM32H7xx_System_Private_Defines
76 * @{
77 */
78
79 /************************* Miscellaneous Configuration ************************/
80 /*!< Uncomment the following line if you need to use initialized data in D2 domain SRAM (AHB SRAM) */
81 /* #define DATA_IN_D2_SRAM */
82
83 /* Note: Following vector table addresses must be defined in line with linker
84 configuration. */
85 /*!< Uncomment the following line if you need to relocate the vector table
86 anywhere in FLASH BANK1 or AXI SRAM, else the vector table is kept at the automatic
87 remap of boot address selected */
88 /* #define USER_VECT_TAB_ADDRESS */
89
90 #if defined(USER_VECT_TAB_ADDRESS)
91 #if defined(DUAL_CORE) && defined(CORE_CM4)
92 /*!< Uncomment the following line if you need to relocate your vector Table
93 in D2 AXI SRAM else user remap will be done in FLASH BANK2. */
94 /* #define VECT_TAB_SRAM */
95 #if defined(VECT_TAB_SRAM)
96 #define VECT_TAB_BASE_ADDRESS D2_AXISRAM_BASE /*!< Vector Table base address field.
97 This value must be a multiple of 0x400. */
98 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
99 This value must be a multiple of 0x400. */
100 #else
101 #define VECT_TAB_BASE_ADDRESS FLASH_BANK2_BASE /*!< Vector Table base address field.
102 This value must be a multiple of 0x400. */
103 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
104 This value must be a multiple of 0x400. */
105 #endif /* VECT_TAB_SRAM */
106 #else
107 /*!< Uncomment the following line if you need to relocate your vector Table
108 in D1 AXI SRAM else user remap will be done in FLASH BANK1. */
109 /* #define VECT_TAB_SRAM */
110 #if defined(VECT_TAB_SRAM)
111 #define VECT_TAB_BASE_ADDRESS D1_AXISRAM_BASE /*!< Vector Table base address field.
112 This value must be a multiple of 0x400. */
113 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
114 This value must be a multiple of 0x400. */
115 #else
116 #define VECT_TAB_BASE_ADDRESS FLASH_BANK1_BASE /*!< Vector Table base address field.
117 This value must be a multiple of 0x400. */
118 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
119 This value must be a multiple of 0x400. */
120 #endif /* VECT_TAB_SRAM */
121 #endif /* DUAL_CORE && CORE_CM4 */
122 #endif /* USER_VECT_TAB_ADDRESS */
123 /******************************************************************************/
124
125 /**
126 * @}
127 */
128
129 /** @addtogroup STM32H7xx_System_Private_Macros
130 * @{
131 */
132
133 /**
134 * @}
135 */
136
137 /** @addtogroup STM32H7xx_System_Private_Variables
138 * @{
139 */
140 /* This variable is updated in three ways:
141 1) by calling CMSIS function SystemCoreClockUpdate()
142 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
143 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
144 Note: If you use this function to configure the system clock; then there
145 is no need to call the 2 first functions listed above, since SystemCoreClock
146 variable is updated automatically.
147 */
148 uint32_t SystemCoreClock = 64000000;
149 uint32_t SystemD2Clock = 64000000;
150 const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
151
152 /**
153 * @}
154 */
155
156 /** @addtogroup STM32H7xx_System_Private_FunctionPrototypes
157 * @{
158 */
159
160 /**
161 * @}
162 */
163
164 /** @addtogroup STM32H7xx_System_Private_Functions
165 * @{
166 */
167
168 /**
169 * @brief Setup the microcontroller system
170 * Initialize the FPU setting and vector table location
171 * configuration.
172 * @param None
173 * @retval None
174 */
SystemInit(void)175 void SystemInit (void)
176 {
177 #if defined (DATA_IN_D2_SRAM)
178 __IO uint32_t tmpreg;
179 #endif /* DATA_IN_D2_SRAM */
180
181 /* FPU settings ------------------------------------------------------------*/
182 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
183 SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2))); /* set CP10 and CP11 Full Access */
184 #endif
185 /* Reset the RCC clock configuration to the default reset state ------------*/
186
187 /* Increasing the CPU frequency */
188 if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
189 {
190 /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
191 MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
192 }
193
194 /* Set HSION bit */
195 RCC->CR |= RCC_CR_HSION;
196
197 /* Reset CFGR register */
198 RCC->CFGR = 0x00000000;
199
200 /* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
201 RCC->CR &= 0xEAF6ED7FU;
202
203 /* Decreasing the number of wait states because of lower CPU frequency */
204 if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
205 {
206 /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
207 MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
208 }
209
210 #if defined(D3_SRAM_BASE)
211 /* Reset D1CFGR register */
212 RCC->D1CFGR = 0x00000000;
213
214 /* Reset D2CFGR register */
215 RCC->D2CFGR = 0x00000000;
216
217 /* Reset D3CFGR register */
218 RCC->D3CFGR = 0x00000000;
219 #else
220 /* Reset CDCFGR1 register */
221 RCC->CDCFGR1 = 0x00000000;
222
223 /* Reset CDCFGR2 register */
224 RCC->CDCFGR2 = 0x00000000;
225
226 /* Reset SRDCFGR register */
227 RCC->SRDCFGR = 0x00000000;
228 #endif
229 /* Reset PLLCKSELR register */
230 RCC->PLLCKSELR = 0x02020200;
231
232 /* Reset PLLCFGR register */
233 RCC->PLLCFGR = 0x01FF0000;
234 /* Reset PLL1DIVR register */
235 RCC->PLL1DIVR = 0x01010280;
236 /* Reset PLL1FRACR register */
237 RCC->PLL1FRACR = 0x00000000;
238
239 /* Reset PLL2DIVR register */
240 RCC->PLL2DIVR = 0x01010280;
241
242 /* Reset PLL2FRACR register */
243
244 RCC->PLL2FRACR = 0x00000000;
245 /* Reset PLL3DIVR register */
246 RCC->PLL3DIVR = 0x01010280;
247
248 /* Reset PLL3FRACR register */
249 RCC->PLL3FRACR = 0x00000000;
250
251 /* Reset HSEBYP bit */
252 RCC->CR &= 0xFFFBFFFFU;
253
254 /* Disable all interrupts */
255 RCC->CIER = 0x00000000;
256
257 #if (STM32H7_DEV_ID == 0x450UL)
258 /* dual core CM7 or single core line */
259 if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
260 {
261 /* if stm32h7 revY*/
262 /* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
263 *((__IO uint32_t*)0x51008108) = 0x000000001U;
264 }
265 #endif /* STM32H7_DEV_ID */
266
267 #if defined(DATA_IN_D2_SRAM)
268 /* in case of initialized data in D2 SRAM (AHB SRAM), enable the D2 SRAM clock (AHB SRAM clock) */
269 #if defined(RCC_AHB2ENR_D2SRAM3EN)
270 RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
271 #elif defined(RCC_AHB2ENR_D2SRAM2EN)
272 RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN);
273 #else
274 RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
275 #endif /* RCC_AHB2ENR_D2SRAM3EN */
276
277 tmpreg = RCC->AHB2ENR;
278 (void) tmpreg;
279 #endif /* DATA_IN_D2_SRAM */
280
281 #if defined(DUAL_CORE) && defined(CORE_CM4)
282 /* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
283 #if defined(USER_VECT_TAB_ADDRESS)
284 SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
285 #endif /* USER_VECT_TAB_ADDRESS */
286
287 #else
288 /*
289 * Disable the FMC bank1 (enabled after reset).
290 * This, prevents CPU speculation access on this bank which blocks the use of FMC during
291 * 24us. During this time the others FMC master (such as LTDC) cannot use it!
292 */
293 FMC_Bank1_R->BTCR[0] = 0x000030D2;
294
295 /* Configure the Vector Table location -------------------------------------*/
296 #if defined(USER_VECT_TAB_ADDRESS)
297 SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
298 #endif /* USER_VECT_TAB_ADDRESS */
299
300 #endif /*DUAL_CORE && CORE_CM4*/
301 }
302
303 /**
304 * @brief Update SystemCoreClock variable according to Clock Register Values.
305 * The SystemCoreClock variable contains the core clock , it can
306 * be used by the user application to setup the SysTick timer or configure
307 * other parameters.
308 *
309 * @note Each time the core clock changes, this function must be called
310 * to update SystemCoreClock variable value. Otherwise, any configuration
311 * based on this variable will be incorrect.
312 *
313 * @note - The system frequency computed by this function is not the real
314 * frequency in the chip. It is calculated based on the predefined
315 * constant and the selected clock source:
316 *
317 * - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(*)
318 * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
319 * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
320 * - If SYSCLK source is PLL, SystemCoreClock will contain the CSI_VALUE(*),
321 * HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
322 *
323 * (*) CSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
324 * 4 MHz) but the real value may vary depending on the variations
325 * in voltage and temperature.
326 * (**) HSI_VALUE is a constant defined in stm32h7xx_hal.h file (default value
327 * 64 MHz) but the real value may vary depending on the variations
328 * in voltage and temperature.
329 *
330 * (***)HSE_VALUE is a constant defined in stm32h7xx_hal.h file (default value
331 * 25 MHz), user has to ensure that HSE_VALUE is same as the real
332 * frequency of the crystal used. Otherwise, this function may
333 * have wrong result.
334 *
335 * - The result of this function could be not correct when using fractional
336 * value for HSE crystal.
337 * @param None
338 * @retval None
339 */
SystemCoreClockUpdate(void)340 void SystemCoreClockUpdate (void)
341 {
342 uint32_t pllp, pllsource, pllm, pllfracen, hsivalue, tmp;
343 uint32_t common_system_clock;
344 float_t fracn1, pllvco;
345
346
347 /* Get SYSCLK source -------------------------------------------------------*/
348
349 switch (RCC->CFGR & RCC_CFGR_SWS)
350 {
351 case RCC_CFGR_SWS_HSI: /* HSI used as system clock source */
352 common_system_clock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
353 break;
354
355 case RCC_CFGR_SWS_CSI: /* CSI used as system clock source */
356 common_system_clock = CSI_VALUE;
357 break;
358
359 case RCC_CFGR_SWS_HSE: /* HSE used as system clock source */
360 common_system_clock = HSE_VALUE;
361 break;
362
363 case RCC_CFGR_SWS_PLL1: /* PLL1 used as system clock source */
364
365 /* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
366 SYSCLK = PLL_VCO / PLLR
367 */
368 pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
369 pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1)>> 4) ;
370 pllfracen = ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN)>>RCC_PLLCFGR_PLL1FRACEN_Pos);
371 fracn1 = (float_t)(uint32_t)(pllfracen* ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1)>> 3));
372
373 if (pllm != 0U)
374 {
375 switch (pllsource)
376 {
377 case RCC_PLLCKSELR_PLLSRC_HSI: /* HSI used as PLL clock source */
378
379 hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
380 pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
381
382 break;
383
384 case RCC_PLLCKSELR_PLLSRC_CSI: /* CSI used as PLL clock source */
385 pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
386 break;
387
388 case RCC_PLLCKSELR_PLLSRC_HSE: /* HSE used as PLL clock source */
389 pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
390 break;
391
392 default:
393 hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
394 pllvco = ((float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1/(float_t)0x2000) +(float_t)1 );
395 break;
396 }
397 pllp = (((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >>9) + 1U ) ;
398 common_system_clock = (uint32_t)(float_t)(pllvco/(float_t)pllp);
399 }
400 else
401 {
402 common_system_clock = 0U;
403 }
404 break;
405
406 default:
407 common_system_clock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
408 break;
409 }
410
411 /* Compute SystemClock frequency --------------------------------------------------*/
412 #if defined (RCC_D1CFGR_D1CPRE)
413 tmp = D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos];
414
415 /* common_system_clock frequency : CM7 CPU frequency */
416 common_system_clock >>= tmp;
417
418 /* SystemD2Clock frequency : CM4 CPU, AXI and AHBs Clock frequency */
419 SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
420
421 #else
422 tmp = D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE)>> RCC_CDCFGR1_CDCPRE_Pos];
423
424 /* common_system_clock frequency : CM7 CPU frequency */
425 common_system_clock >>= tmp;
426
427 /* SystemD2Clock frequency : AXI and AHBs Clock frequency */
428 SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
429
430 #endif
431
432 #if defined(DUAL_CORE) && defined(CORE_CM4)
433 SystemCoreClock = SystemD2Clock;
434 #else
435 SystemCoreClock = common_system_clock;
436 #endif /* DUAL_CORE && CORE_CM4 */
437 }
438
439
440 /**
441 * @}
442 */
443
444 /**
445 * @}
446 */
447
448 /**
449 * @}
450 */
451