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