1 /**
2 ******************************************************************************
3 * @file system_stm32u0xx.c
4 * @author MCD Application Team
5 * @brief CMSIS Cortex-M0+ Device Peripheral Access Layer System Source File
6 *
7 ******************************************************************************
8 * @attention
9 *
10 * Copyright (c) 2023 STMicroelectronics.
11 * All rights reserved.
12 *
13 * This software is licensed under terms that can be found in the LICENSE file
14 * in the root directory of this software component.
15 * If no LICENSE file comes with this software, it is provided AS-IS.
16 *
17 ******************************************************************************
18 * This file provides two functions and one global variable to be called from
19 * user application:
20 * - SystemInit(): This function is called at startup just after reset and
21 * before branch to main program. This call is made inside
22 * the "startup_stm32u0xx.s" file.
23 *
24 * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
25 * by the user application to setup the SysTick
26 * timer or configure other parameters.
27 *
28 * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
29 * be called whenever the core clock is changed
30 * during program execution.
31 *
32 * After each device reset the MSI (4 MHz) is used as system clock source.
33 * Then SystemInit() function is called, in "startup_stm32u0xx.s" file, to
34 * configure the system clock before to branch to main program.
35 *
36 * This file configures the system clock as follows:
37 *=============================================================================
38 *-----------------------------------------------------------------------------
39 * System Clock source | MSI
40 *-----------------------------------------------------------------------------
41 * SYSCLK(Hz) | 4000000
42 *-----------------------------------------------------------------------------
43 * HCLK(Hz) | 4000000
44 *-----------------------------------------------------------------------------
45 * AHB Prescaler | 1
46 *-----------------------------------------------------------------------------
47 * APB Prescaler | 1
48 *-----------------------------------------------------------------------------
49 * HSI Division factor | 1
50 *-----------------------------------------------------------------------------
51 * PLL_M | 1
52 *-----------------------------------------------------------------------------
53 * PLL_N | 8
54 *-----------------------------------------------------------------------------
55 * PLL_P | 7
56 *-----------------------------------------------------------------------------
57 * PLL_Q | 2
58 *-----------------------------------------------------------------------------
59 * PLL_R | 2
60 *-----------------------------------------------------------------------------
61 * Require 48MHz for RNG | Disabled
62 *-----------------------------------------------------------------------------
63 *=============================================================================
64 */
65
66 /** @addtogroup CMSIS
67 * @{
68 */
69
70 /** @addtogroup stm32u0xx_system
71 * @{
72 */
73
74 /** @addtogroup STM32U0xx_System_Private_Includes
75 * @{
76 */
77
78 #include "stm32u0xx.h"
79
80 #if !defined (HSE_VALUE)
81 #define HSE_VALUE (32000000U) /*!< Value of the External oscillator in Hz */
82 #endif /* HSE_VALUE */
83
84 #if !defined (HSI_VALUE)
85 #define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/
86 #endif /* HSI_VALUE */
87
88 #if !defined (MSI_VALUE)
89 #define MSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/
90 #endif /* MSI_VALUE */
91
92 #if !defined (LSI_VALUE)
93 #define LSI_VALUE (32000UL) /*!< Value of the Internal oscillator in Hz */
94 #endif /* LSI_VALUE */
95
96 #if !defined (LSE_VALUE)
97 #define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz */
98 #endif /* LSE_VALUE */
99
100 /**
101 * @}
102 */
103
104 /** @addtogroup STM32U0xx_System_Private_TypesDefinitions
105 * @{
106 */
107
108 /**
109 * @}
110 */
111
112 /** @addtogroup STM32U0xx_System_Private_Defines
113 * @{
114 */
115
116 /************************* Miscellaneous Configuration ************************/
117 /*!< Uncomment the following line if you need to relocate your vector Table in
118 Internal SRAM. */
119 //#define VECT_TAB_SRAM
120 #define VECT_TAB_OFFSET 0x0U /*!< Vector Table base offset field.
121 This value must be a multiple of 0x200. */
122
123 /*!< Comment the following line if you would like to disable the software
124 workaround related to debug access in case RDP=1 and Boot_Lock=1 */
125 #define ENABLE_DBG_SWEN /*!< Enable the debugger read access. */
126 /******************************************************************************/
127 /**
128 * @}
129 */
130
131 /** @addtogroup STM32U0xx_System_Private_Macros
132 * @{
133 */
134
135 /**
136 * @}
137 */
138
139 /** @addtogroup STM32U0xx_System_Private_Variables
140 * @{
141 */
142 /* The SystemCoreClock variable is updated in three ways:
143 1) by calling CMSIS function SystemCoreClockUpdate()
144 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
145 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
146 Note: If you use this function to configure the system clock; then there
147 is no need to call the 2 first functions listed above, since SystemCoreClock
148 variable is updated automatically.
149 */
150 uint32_t SystemCoreClock = 4000000U;
151
152 const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
153 const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
154 const uint32_t MSIRangeTable[12] = {100000U, 200000U, 400000U, 800000U, 1000000U, 2000000U, \
155 4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U
156 };
157
158 /**
159 * @}
160 */
161
162 /** @addtogroup STM32U0xx_System_Private_FunctionPrototypes
163 * @{
164 */
165
166 /**
167 * @}
168 */
169
170 /** @addtogroup STM32U0xx_System_Private_Functions
171 * @{
172 */
173
174 /**
175 * @brief Setup the microcontroller system.
176 * @param None
177 * @retval None
178 */
179
SystemInit(void)180 void SystemInit(void)
181 {
182 #ifdef ENABLE_DBG_SWEN
183 uint32_t tmp_seccr;
184 uint32_t tmp_optr;
185 #endif /* ENABLE_DBG_SWEN */
186 /* Configure the Vector Table location add offset address ------------------*/
187 #ifdef VECT_TAB_SRAM
188 SCB->VTOR = SRAM1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
189 #else
190 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
191 #endif /* VECT_TAB_SRAM */
192
193 /* Software workaround added to keep Debug enabled after Boot_Lock activation and RDP=1 */
194 #ifdef ENABLE_DBG_SWEN
195 tmp_seccr = FLASH->SECR;
196 tmp_optr = FLASH->OPTR;
197 if (((tmp_seccr & FLASH_SECR_BOOT_LOCK) == FLASH_SECR_BOOT_LOCK) \
198 && (((tmp_optr & FLASH_OPTR_RDP) != 0xCCU) \
199 && ((tmp_optr & FLASH_OPTR_RDP) != 0xAAU)))
200 {
201 FLASH->ACR |= FLASH_ACR_DBG_SWEN; /* Debug access software enabled to avoid the chip
202 to be locked when RDP=1 and Boot_Lock=1 */
203 }
204 #endif /* ENABLE_DBG_SWEN */
205 }
206
207 /**
208 * @brief Update SystemCoreClock variable according to Clock Register Values.
209 * The SystemCoreClock variable contains the core clock (HCLK), it can
210 * be used by the user application to setup the SysTick timer or configure
211 * other parameters.
212 *
213 * @note Each time the core clock (HCLK) changes, this function must be called
214 * to update SystemCoreClock variable value. Otherwise, any configuration
215 * based on this variable will be incorrect.
216 *
217 * @note - The system frequency computed by this function is not the real
218 * frequency in the chip. It is calculated based on the predefined
219 * constant and the selected clock source:
220 *
221 * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*)
222 *
223 * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
224 *
225 * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
226 *
227 * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***)
228 * or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
229 *
230 * (*) MSI_VALUE is a constant defined in stm32u0xx_hal.h file (default value
231 * 4 MHz) but the real value may vary depending on the variations
232 * in voltage and temperature.
233 *
234 * (**) HSI_VALUE is a constant defined in stm32u0xx_hal.h file (default value
235 * 16 MHz) but the real value may vary depending on the variations
236 * in voltage and temperature.
237 *
238 * (***) HSE_VALUE is a constant defined in stm32u0xx_hal.h file (default value
239 * 8 MHz), user has to ensure that HSE_VALUE is same as the real
240 * frequency of the crystal used. Otherwise, this function may
241 * have wrong result.
242 *
243 * - The result of this function could be not correct when using fractional
244 * value for HSE crystal.
245 *
246 * @param None
247 * @retval None
248 */
SystemCoreClockUpdate(void)249 void SystemCoreClockUpdate(void)
250 {
251 uint32_t tmp, msirange, pllvco, pllsource, pllm, pllr;
252
253 /* Get MSI Range frequency--------------------------------------------------*/
254 if ((RCC->CR & RCC_CR_MSIRGSEL) == 0U)
255 {
256 /* MSISRANGE from RCC_CSR applies */
257 msirange = (RCC->CSR & RCC_CSR_MSISTBYRG) >> 8U;
258 }
259 else
260 {
261 /* MSIRANGE from RCC_CR applies */
262 msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U;
263 }
264 /* MSI frequency range in HZ*/
265 if (msirange > 11U)
266 {
267 msirange = 0U;
268 }
269 msirange = MSIRangeTable[msirange];
270
271 /* Get SYSCLK source -------------------------------------------------------*/
272 switch (RCC->CFGR & RCC_CFGR_SWS)
273 {
274 case 0x00: /* MSI used as system clock source */
275 SystemCoreClock = msirange;
276 break;
277
278 case RCC_CFGR_SWS_0: /* HSI used as system clock source */
279 SystemCoreClock = HSI_VALUE;
280 break;
281
282 case RCC_CFGR_SWS_1: /* HSE used as system clock source */
283 SystemCoreClock = HSE_VALUE;
284 break;
285
286 case RCC_CFGR_SWS_2: /* LSI used as system clock */
287 SystemCoreClock = LSI_VALUE;
288 break;
289
290 case (RCC_CFGR_SWS_2 | RCC_CFGR_SWS_0): /* LSE used as system clock */
291 SystemCoreClock = LSE_VALUE;
292 break;
293
294 case (RCC_CFGR_SWS_1 | RCC_CFGR_SWS_0): /* PLL used as system clock source */
295 /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
296 SYSCLK = PLL_VCO / PLLR
297 */
298 pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
299 pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
300
301 switch (pllsource)
302 {
303 case RCC_PLLCFGR_PLLSRC_0: /* MSI used as PLL clock source */
304 pllvco = (msirange / pllm);
305 break;
306
307 case RCC_PLLCFGR_PLLSRC_1: /* HSI used as PLL clock source */
308 pllvco = (HSI_VALUE / pllm);
309 break;
310
311 case (RCC_PLLCFGR_PLLSRC_1 | RCC_PLLCFGR_PLLSRC_0): /* HSE used as PLL clock source */
312 pllvco = (HSE_VALUE / pllm);
313 break;
314
315 default: /* no clock used as PLL clock source */
316 pllvco = 0x0U;
317 break;
318 }
319 pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
320 pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1UL);
321 SystemCoreClock = pllvco / pllr;
322 break;
323
324 default:
325 SystemCoreClock = msirange;
326 break;
327 }
328 /* Compute HCLK clock frequency --------------------------------------------*/
329 /* Get HCLK prescaler */
330 tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos) & 0xFU];
331 /* HCLK clock frequency */
332 SystemCoreClock >>= tmp;
333 }
334
335 /**
336 * @}
337 */
338
339 /**
340 * @}
341 */
342
343 /**
344 * @}
345 */
346
347