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