1 /**
2 ******************************************************************************
3 * @file system_stm32h5xx.c
4 * @author MCD Application Team
5 * @brief CMSIS Cortex-M33 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_stm32h5xx.s" file.
12 *
13 * - SystemCoreClock variable: Contains the core clock (HCLK), 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 * After each device reset the HSI (64 MHz) is used as system clock source.
22 * Then SystemInit() function is called, in "startup_stm32h5xx.s" file, to
23 * configure the system clock before to branch to main program.
24 *
25 ******************************************************************************
26 * @attention
27 *
28 * Copyright (c) 2023 STMicroelectronics.
29 * All rights reserved.
30 *
31 * This software component is licensed by ST under BSD 3-Clause license,
32 * the "License"; You may not use this file except in compliance with the
33 * License. You may obtain a copy of the License at:
34 * opensource.org/licenses/BSD-3-Clause
35 *
36 ******************************************************************************
37 */
38
39 /** @addtogroup CMSIS
40 * @{
41 */
42
43 /** @addtogroup STM32H5xx_system
44 * @{
45 */
46
47 /** @addtogroup STM32H5xx_System_Private_Includes
48 * @{
49 */
50
51 #include "stm32h5xx.h"
52
53 /**
54 * @}
55 */
56
57 /** @addtogroup STM32H5xx_System_Private_TypesDefinitions
58 * @{
59 */
60
61 /**
62 * @}
63 */
64
65 /** @addtogroup STM32H5xx_System_Private_Defines
66 * @{
67 */
68
69 #if !defined (HSE_VALUE)
70 #define HSE_VALUE (25000000U) /*!< Value of the External oscillator in Hz */
71 #endif /* HSE_VALUE */
72
73 #if !defined (CSI_VALUE)
74 #define CSI_VALUE (4000000U) /*!< Value of the Internal oscillator in Hz*/
75 #endif /* CSI_VALUE */
76
77 #if !defined (HSI_VALUE)
78 #define HSI_VALUE (64000000U) /*!< Value of the Internal oscillator in Hz */
79 #endif /* HSI_VALUE */
80
81 /************************* Miscellaneous Configuration ************************/
82 /*!< Uncomment the following line if you need to relocate your vector Table in
83 Internal SRAM. */
84 /* #define VECT_TAB_SRAM */
85 #define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
86 This value must be a multiple of 0x200. */
87 /******************************************************************************/
88
89 /**
90 * @}
91 */
92
93 /** @addtogroup STM32H5xx_System_Private_Macros
94 * @{
95 */
96
97 /**
98 * @}
99 */
100
101 /** @addtogroup STM32H5xx_System_Private_Variables
102 * @{
103 */
104 /* The SystemCoreClock variable is updated in three ways:
105 1) by calling CMSIS function SystemCoreClockUpdate()
106 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
107 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
108 Note: If you use this function to configure the system clock; then there
109 is no need to call the 2 first functions listed above, since SystemCoreClock
110 variable is updated automatically.
111 */
112 uint32_t SystemCoreClock = 64000000U;
113
114 const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
115 const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
116 /**
117 * @}
118 */
119
120 /** @addtogroup STM32H5xx_System_Private_FunctionPrototypes
121 * @{
122 */
123 static void SetSysClock(void);
124
125 /**
126 * @}
127 */
128
129 /** @addtogroup STM32H5xx_System_Private_Functions
130 * @{
131 */
132
133 /**
134 * @brief Setup the microcontroller system.
135 * @param None
136 * @retval None
137 */
138
SystemInit(void)139 void SystemInit(void)
140 {
141 /* FPU settings ------------------------------------------------------------*/
142 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
143 SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
144 #endif
145
146 /* Configure the System clock source, PLL Multiplier and Divider factors,
147 AHB/APBx prescalers and Flash settings for System clock 250 MHz */
148 SetSysClock();
149 }
150
151 /**
152 * @brief Update SystemCoreClock variable according to Clock Register Values.
153 * The SystemCoreClock variable contains the core clock (HCLK), it can
154 * be used by the user application to setup the SysTick timer or configure
155 * other parameters.
156 *
157 * @note Each time the core clock (HCLK) changes, this function must be called
158 * to update SystemCoreClock variable value. Otherwise, any configuration
159 * based on this variable will be incorrect.
160 *
161 * @note - The system frequency computed by this function is not the real
162 * frequency in the chip. It is calculated based on the predefined
163 * constant and the selected clock source:
164 *
165 * - If SYSCLK source is CSI, SystemCoreClock will contain the CSI_VALUE(*)
166 *
167 * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
168 *
169 * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
170 *
171 * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***)
172 * or HSI_VALUE(**) or CSI_VALUE(*) multiplied/divided by the PLL factors.
173 *
174 * (*) CSI_VALUE is a constant defined in stm32h5xx_hal.h file (default value
175 * 4 MHz) but the real value may vary depending on the variations
176 * in voltage and temperature.
177 *
178 * (**) HSI_VALUE is a constant defined in stm32h5xx_hal.h file (default value
179 * 64 MHz) but the real value may vary depending on the variations
180 * in voltage and temperature.
181 *
182 * (***) HSE_VALUE is a constant defined in stm32h5xx_hal.h file (default value
183 * 25 MHz), user has to ensure that HSE_VALUE is same as the real
184 * frequency of the crystal used. Otherwise, this function may
185 * have wrong result.
186 *
187 * - The result of this function could be not correct when using fractional
188 * value for HSE crystal.
189 *
190 * @param None
191 * @retval None
192 */
SystemCoreClockUpdate(void)193 void SystemCoreClockUpdate(void)
194 {
195 uint32_t pllp, pllsource, pllm, pllfracen, hsivalue, tmp;
196 float_t fracn1, pllvco;
197
198 /* Get SYSCLK source -------------------------------------------------------*/
199 switch (RCC->CFGR1 & RCC_CFGR1_SWS)
200 {
201 case 0x00: /* HSI used as system clock source */
202 SystemCoreClock = (uint32_t) (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3));
203 break;
204
205 case 0x08: /* CSI used as system clock source */
206 SystemCoreClock = CSI_VALUE;
207 break;
208
209 case 0x10: /* HSE used as system clock source */
210 SystemCoreClock = HSE_VALUE;
211 break;
212
213 case 0x18: /* PLL1 used as system clock source */
214 /* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
215 SYSCLK = PLL_VCO / PLLR
216 */
217 pllsource = (RCC->PLL1CFGR & RCC_PLL1CFGR_PLL1SRC);
218 pllm = ((RCC->PLL1CFGR & RCC_PLL1CFGR_PLL1M)>> RCC_PLL1CFGR_PLL1M_Pos);
219 pllfracen = ((RCC->PLL1CFGR & RCC_PLL1CFGR_PLL1FRACEN)>>RCC_PLL1CFGR_PLL1FRACEN_Pos);
220 fracn1 = (float_t)(uint32_t)(pllfracen* ((RCC->PLL1FRACR & RCC_PLL1FRACR_PLL1FRACN)>> RCC_PLL1FRACR_PLL1FRACN_Pos));
221
222 switch (pllsource)
223 {
224 case 0x00: /* No clock sent to PLL*/
225 pllvco = 0U;
226 break;
227
228 case 0x01: /* HSI used as PLL clock source */
229 hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV)>> 3)) ;
230 pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_PLL1N) + (fracn1/(float_t)0x2000) +(float_t)1 );
231 break;
232
233 case 0x02: /* CSI used as PLL clock source */
234 pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_PLL1N) + (fracn1/(float_t)0x2000) +(float_t)1 );
235 break;
236
237 case 0x03: /* HSE used as PLL clock source */
238 pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_PLL1N) + (fracn1/(float_t)0x2000) +(float_t)1 );
239 break;
240
241 default: /* No clock sent to PLL*/
242 pllvco = 0U;
243
244 break;
245 }
246
247 pllp = (((RCC->PLL1DIVR & RCC_PLL1DIVR_PLL1P) >>RCC_PLL1DIVR_PLL1P_Pos) + 1U ) ;
248 SystemCoreClock = (uint32_t)(float_t)(pllvco/(float_t)pllp);
249
250 break;
251
252 default:
253 SystemCoreClock = HSI_VALUE;
254 break;
255 }
256 /* Compute HCLK clock frequency --------------------------------------------*/
257 /* Get HCLK prescaler */
258 tmp = AHBPrescTable[((RCC->CFGR2 & RCC_CFGR2_HPRE) >> RCC_CFGR2_HPRE_Pos)];
259 /* HCLK clock frequency */
260 SystemCoreClock >>= tmp;
261 }
262
263 /**
264 * @brief Configures the System clock source, PLL Multiplier and Divider factors,
265 * AHB/APBx prescalers and Flash settings for System clock 250 MHz
266 * @retval None
267 */
SetSysClock(void)268 static void SetSysClock(void)
269 {
270 /* Set the regulator supply output voltage */
271 MODIFY_REG(PWR->SCCR, (PWR_SCCR_BYPASS), PWR_SCCR_LDOEN);
272 MODIFY_REG(PWR->VOSCR, PWR_VOSCR_VOS, PWR_VOSCR_VOS);
273 while ((PWR->VOSSR & PWR_VOSSR_VOSRDY) != PWR_VOSSR_VOSRDY)
274 {
275 }
276
277 /* HSI Calibration with default value */
278 MODIFY_REG(RCC->HSICFGR, RCC_HSICFGR_HSITRIM, 0x40 << RCC_HSICFGR_HSITRIM_Pos);
279 MODIFY_REG(RCC->CR, RCC_CR_HSIDIV, RCC_HSI_DIV1);
280 /* Enable HSI oscillator */
281 SET_BIT(RCC->CR, RCC_CR_HSION);
282 while((RCC->CR & RCC_CR_HSIRDY) != RCC_CR_HSIRDY)
283 {
284 }
285
286 /* Set FLASH latency */
287 MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, FLASH_ACR_LATENCY_5WS);
288
289 /* Configure PLL clock source */
290 MODIFY_REG(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1SRC, RCC_PLL1CFGR_PLL1SRC_0);
291
292 /* Main PLL configuration and activation */
293 SET_BIT(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1PEN);
294 SET_BIT(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1QEN);
295 SET_BIT(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1REN);
296 CLEAR_BIT(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1FRACEN);
297 MODIFY_REG(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1RGE, RCC_PLL1CFGR_PLL1SRC_1 << RCC_PLL1CFGR_PLL1RGE_Pos);
298 MODIFY_REG(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1VCOSEL, RCC_PLL1VCOWIDE << RCC_PLL1CFGR_PLL1VCOSEL_Pos);
299 MODIFY_REG(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1M, RCC_PLL1CFGR_PLL1M_Pos << RCC_PLL1CFGR_PLL1M_Pos);
300 MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_PLL1N, (60U - 1UL) << RCC_PLL1DIVR_PLL1N_Pos);
301 MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_PLL1P, (2U - 1UL) << RCC_PLL1DIVR_PLL1P_Pos);
302 MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_PLL1Q, (2U - 1UL) << RCC_PLL1DIVR_PLL1Q_Pos);
303 MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_PLL1R, (2U - 1UL) << RCC_PLL1DIVR_PLL1R_Pos);
304
305 SET_BIT(RCC->CR, RCC_CR_PLL1ON);
306 while((RCC->CR & RCC_CR_PLL1RDY) != RCC_CR_PLL1RDY)
307 {
308 }
309
310 /* Set AHB, APB1, APB2 and APB3 prescalers */
311 MODIFY_REG(RCC->CFGR2, RCC_CFGR2_HPRE, RCC_SYSCLK_DIV1);
312 MODIFY_REG(RCC->CFGR2, RCC_CFGR2_PPRE1, RCC_HCLK_DIV1);
313 MODIFY_REG(RCC->CFGR2, RCC_CFGR2_PPRE2, RCC_HCLK_DIV1);
314 MODIFY_REG(RCC->CFGR2, RCC_CFGR2_PPRE3, RCC_HCLK_DIV1);
315
316 /* Set PLL1 as System Clock Source */
317 MODIFY_REG(RCC->CFGR1, RCC_CFGR1_SW, (RCC_CFGR1_SW_1 | RCC_CFGR1_SW_0));
318
319 while((RCC->CFGR1 & RCC_CFGR1_SWS) != (RCC_CFGR1_SWS_1 | RCC_CFGR1_SWS_0))
320 {
321 }
322
323 /* Enable the HSI48 oscillator (HSI48) for RNG peripheral */
324 RCC->CR |= RCC_CR_HSI48ON;
325 }
326
327 /**
328 * @}
329 */
330
331 /**
332 * @}
333 */
334
335 /**
336 * @}
337 */
338
339