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