source: trunk/firmware/FSBL/SES/STM32N6xx/Device/Source/system_stm32n6xx_s.c

Last change on this file was 16, checked in by Zed, 5 weeks ago
File size: 16.0 KB
Line 
1/**
2 ******************************************************************************
3 * @file system_stm32n6xx_s.c
4 * @author MCD Application Team
5 * @brief CMSIS Cortex-M55 Device Peripheral Access Layer System Source File
6 * to be used in secure application.
7 *
8 * This file provides two functions and one global variable to be called from
9 * user application:
10 * - SystemInit(): This function is called at secure startup just after reset
11 * and before branch to secure main program.
12 * This call is made inside the "startup_stm32n6xx.s" file.
13 *
14 * - SystemCoreClock variable: Contains the CPU core clock, it can be used
15 * by the user application to setup the SysTick
16 * timer or configure other parameters.
17 *
18 * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
19 * be called whenever the core clock is changed
20 * during program execution.
21 *
22 * - SECURE_SystemCoreClockUpdate(): Non-secure callable function to update
23 * the variable SystemCoreClock and return
24 * its value to the non-secure calling
25 * application. It must be called whenever
26 * the core clock is changed during program
27 * execution.
28 *
29 * After each device reset the HSI (64 MHz) is used as system clock source.
30 * Then SystemInit() function is called, in "startup_stm32n6xx.s" file, to
31 * configure the system before to branch to main program.
32 *
33 ******************************************************************************
34 * @attention
35 *
36 * Copyright (c) 2023 STMicroelectronics.
37 * All rights reserved.
38 *
39 * This software is licensed under terms that can be found in the LICENSE file
40 * in the root directory of this software component.
41 * If no LICENSE file comes with this software, it is provided AS-IS.
42 *
43 ******************************************************************************
44 */
45
46/** @addtogroup CMSIS
47 * @{
48 */
49
50/** @addtogroup STM32N6xx_System
51 * @{
52 */
53
54/** @addtogroup STM32N6xx_System_Private_Includes
55 * @{
56 */
57
58#include "stm32n6xx.h"
59#include "partition_stm32n6xx.h" /* Trustzone-M core secure attributes */
60#include <math.h>
61
62/**
63 * @}
64 */
65
66/** @addtogroup STM32N6xx_System_Private_TypesDefinitions
67 * @{
68 */
69
70#if defined ( __ICCARM__ )
71# define CMSE_NS_ENTRY __cmse_nonsecure_entry
72#else
73# define CMSE_NS_ENTRY __attribute((cmse_nonsecure_entry))
74#endif
75
76/**
77 * @}
78 */
79
80/** @addtogroup STM32N6xx_System_Private_Defines
81 * @{
82 */
83#if !defined (HSE_VALUE)
84#define HSE_VALUE 48000000UL /*!< Value of the High-Speed External oscillator in Hz */
85#endif /* HSE_VALUE */
86
87#if !defined (HSI_VALUE)
88#define HSI_VALUE 64000000UL /*!< Value of the High-Speed Internal oscillator in Hz */
89#endif /* HSI_VALUE */
90
91#if !defined (MSI_VALUE)
92 #define MSI_VALUE 4000000UL /*!< Minimum value of the Low-power Internal oscillator in Hz */
93#endif /* MSI_VALUE */
94
95#if !defined (EXTERNAL_I2S_CLOCK_VALUE)
96 #define EXTERNAL_I2S_CLOCK_VALUE 12288000UL /*!< Value of the External clock for I2S_CKIN in Hz */
97#endif /* EXTERNAL_I2S_CLOCK_VALUE */
98
99
100/* Note: Following vector table addresses must be defined in line with linker
101 configuration. */
102/*!< Uncomment the following line if you need to relocate the vector table
103 anywhere in memory, else the vector table is kept at the automatic
104 selected boot address */
105/* #define USER_VECT_TAB_ADDRESS */
106
107#if defined(USER_VECT_TAB_ADDRESS)
108#if !defined(VECT_TAB_BASE_ADDRESS)
109#define VECT_TAB_BASE_ADDRESS SRAM1_AXI_BASE_S /*!< Vector Table base address field.
110 This value must be a multiple of 0x400. */
111#endif
112
113#if !defined(VECT_TAB_OFFSET)
114#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
115 This value must be a multiple of 0x400. */
116#endif
117#endif /* USER_VECT_TAB_ADDRESS */
118
119/******************************************************************************/
120/**
121 * @}
122 */
123
124/** @addtogroup STM32N6xx_System_Private_Macros
125 * @{
126 */
127
128/**
129 * @}
130 */
131
132/** @addtogroup STM32N6xx_System_Private_Variables
133 * @{
134 */
135 /* The SystemCoreClock variable is updated in three ways:
136 1) by calling CMSIS function SystemCoreClockUpdate()
137 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
138 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
139 Note: If you use this function to configure the system clock; then there
140 is no need to call the 2 first functions listed above, since SystemCoreClock
141 variable is updated automatically.
142 */
143uint32_t SystemCoreClock = HSI_VALUE;
144/**
145 * @}
146 */
147
148/** @addtogroup STM32N6xx_System_Private_FunctionPrototypes
149 * @{
150 */
151
152/**
153 * @}
154 */
155
156/** @addtogroup STM32N6xx_System_Private_Functions
157 * @{
158 */
159
160#if defined(__ICCARM__)
161extern uint32_t __vector_table;
162#define INTVECT_START ((uint32_t)&__vector_table)
163#elif defined(__ARMCC_VERSION)
164extern void *__Vectors;
165#define INTVECT_START ((uint32_t)&__Vectors)
166#elif defined(__GNUC__)
167extern void *g_pfnVectors;
168#define INTVECT_START ((uint32_t)&g_pfnVectors)
169#endif
170
171/**
172 * @brief Setup the microcontroller system.
173 * @retval None
174 */
175
176void SystemInit(void)
177{
178 /* SAU/IDAU, FPU and Interrupts secure/non-secure allocation settings */
179 TZ_SAU_Setup();
180
181 /* Configure the Vector Table location -------------------------------------*/
182#if defined(USER_VECT_TAB_ADDRESS)
183 SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
184#else
185 SCB->VTOR = INTVECT_START;
186#endif /* USER_VECT_TAB_ADDRESS */
187
188 /* System configuration setup */
189 RCC->APB4ENSR2 = RCC_APB4ENSR2_SYSCFGENS;
190 /* Delay after an RCC peripheral clock enabling */
191 (void)RCC->APB4ENR2;
192
193 /* Set default Vector Table location after system reset or return from Standby */
194 SYSCFG->INITSVTORCR = SCB->VTOR;
195 /* Read back the value to make sure it is written before deactivating SYSCFG */
196 (void) SYSCFG->INITSVTORCR;
197 /* Deactivate SYSCFG clock */
198 RCC->APB4ENCR2 = RCC_APB4ENCR2_SYSCFGENC;
199 /* FPU settings ------------------------------------------------------------*/
200#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
201 SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
202
203 SCB_NS->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
204#endif /* __FPU_PRESENT && __FPU_USED */
205
206}
207
208/**
209 * @brief Update SystemCoreClock variable according to Clock Register Values.
210 * The SystemCoreClock variable contains the core clock (HCLK), it can
211 * be used by the user application to setup the SysTick timer or configure
212 * other parameters.
213 *
214 * @note Depending on secure or non-secure compilation, the adequate RCC peripheral
215 * memory are is accessed thanks to RCC alias defined in stm32n6xxxx.h device file
216 * so either from RCC_S peripheral register mapped memory in secure or from
217 * RCC_NS peripheral register mapped memory in non-secure.
218 *
219 * @note Each time the CPU core clock changes, this function must be called
220 * to update SystemCoreClock variable value. Otherwise, any configuration
221 * based on this variable will be incorrect.
222 *
223 * @note - The system frequency computed by this function is not the real
224 * frequency in the chip. It is calculated based on the predefined
225 * constant and the selected clock source:
226 *
227 * - If CPUCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
228 *
229 * - If CPUCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(**)
230 *
231 * - If CPUCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
232 *
233 * - If CPUCLK source is IC1, SystemCoreClock will contain the HSI_VALUE(*)
234 * or MSI_VALUE(**) or HSE_VALUE(***) or EXTERNAL_I2S_CLOCK_VALUE (****)
235 * multiplied/divided by the PLL factors.
236 *
237 * (*) HSI_VALUE default value is 64 MHz.
238 * With the HAL, HSI_VALUE is a constant defined in stm32n6xx_hal_conf.h file
239 * but the real value may vary depending on the variations in voltage and temperature.
240 *
241 * (**) MSI_VALUE default value is 4 MHz.
242 * With the HAL, MSI_VALUE is a constant defined in stm32n6xx_hal_conf.h file
243 * but the real value may vary depending on the variations in voltage and temperature.
244 *
245 * (***) HSE_VALUE default value is 30 MHz.
246 * With the HAL, HSE_VALUE is a constant defined in stm32n6xx_hal_conf.h file.
247 * User has to ensure that HSE_VALUE is same as the real frequency of the crystal used.
248 * Otherwise, this function may have wrong result.
249 *
250 * (****) EXTERNAL_I2S_CLOCK_VALUE default value is 12.288 MHz.
251 * With the HAL, EXTERNAL_I2S_CLOCK_VALUE is a constant defined in stm32n6xx_hal_conf.h file.
252 * User has to ensure that EXTERNAL_I2S_CLOCK_VALUE is same as the real I2S_CKIN
253 * pin frequency. Otherwise, this function may have wrong result.
254 *
255 * - The result of this function could be not correct when using fractional
256 * value for HSE crystal.
257 *
258 * @retval None
259 */
260void SystemCoreClockUpdate(void)
261{
262 uint32_t sysclk = 0;
263 uint32_t pllm = 0;
264 uint32_t plln = 0;
265 uint32_t pllfracn = 0;
266 uint32_t pllp1 = 0;
267 uint32_t pllp2 = 0;
268 uint32_t pllcfgr, pllsource, pllbypass, ic_divider;
269 float_t pllvco;
270
271 /* Get CPUCLK source -------------------------------------------------------*/
272 switch (RCC->CFGR1 & RCC_CFGR1_CPUSWS)
273 {
274 case 0: /* HSI used as system clock source (default after reset) */
275 sysclk = HSI_VALUE >> ((RCC->HSICFGR & RCC_HSICFGR_HSIDIV) >> RCC_HSICFGR_HSIDIV_Pos);
276 break;
277
278 case RCC_CFGR1_CPUSWS_0: /* MSI used as system clock source */
279 if (READ_BIT(RCC->MSICFGR, RCC_MSICFGR_MSIFREQSEL) == 0UL)
280 {
281 sysclk = MSI_VALUE;
282 }
283 else
284 {
285 sysclk = 16000000UL;
286 }
287 break;
288
289 case RCC_CFGR1_CPUSWS_1: /* HSE used as system clock source */
290 sysclk = HSE_VALUE;
291 break;
292
293 case (RCC_CFGR1_CPUSWS_1 | RCC_CFGR1_CPUSWS_0): /* IC1 used as system clock source */
294 /* Get IC1 clock source parameters */
295 switch (READ_BIT(RCC->IC1CFGR, RCC_IC1CFGR_IC1SEL))
296 {
297 case 0: /* PLL1 selected at IC1 clock source */
298 pllcfgr = READ_REG(RCC->PLL1CFGR1);
299 pllsource = pllcfgr & RCC_PLL1CFGR1_PLL1SEL;
300 pllbypass = pllcfgr & RCC_PLL1CFGR1_PLL1BYP;
301 if (pllbypass == 0U)
302 {
303 pllm = (pllcfgr & RCC_PLL1CFGR1_PLL1DIVM) >> RCC_PLL1CFGR1_PLL1DIVM_Pos;
304 plln = (pllcfgr & RCC_PLL1CFGR1_PLL1DIVN) >> RCC_PLL1CFGR1_PLL1DIVN_Pos;
305 pllfracn = READ_BIT(RCC->PLL1CFGR2, RCC_PLL1CFGR2_PLL1DIVNFRAC) >> RCC_PLL1CFGR2_PLL1DIVNFRAC_Pos;
306 pllcfgr = READ_REG(RCC->PLL1CFGR3);
307 pllp1 = (pllcfgr & RCC_PLL1CFGR3_PLL1PDIV1) >> RCC_PLL1CFGR3_PLL1PDIV1_Pos;
308 pllp2 = (pllcfgr & RCC_PLL1CFGR3_PLL1PDIV2) >> RCC_PLL1CFGR3_PLL1PDIV2_Pos;
309 }
310 break;
311 case RCC_IC1CFGR_IC1SEL_0: /* PLL2 selected at IC1 clock source */
312 pllcfgr = READ_REG(RCC->PLL2CFGR1);
313 pllsource = pllcfgr & RCC_PLL2CFGR1_PLL2SEL;
314 pllbypass = pllcfgr & RCC_PLL2CFGR1_PLL2BYP;
315 if (pllbypass == 0U)
316 {
317 pllm = (pllcfgr & RCC_PLL2CFGR1_PLL2DIVM) >> RCC_PLL2CFGR1_PLL2DIVM_Pos;
318 plln = (pllcfgr & RCC_PLL2CFGR1_PLL2DIVN) >> RCC_PLL2CFGR1_PLL2DIVN_Pos;
319 pllfracn = READ_BIT(RCC->PLL2CFGR2, RCC_PLL2CFGR2_PLL2DIVNFRAC) >> RCC_PLL2CFGR2_PLL2DIVNFRAC_Pos;
320 pllcfgr = READ_REG(RCC->PLL2CFGR3);
321 pllp1 = (pllcfgr & RCC_PLL2CFGR3_PLL2PDIV1) >> RCC_PLL2CFGR3_PLL2PDIV1_Pos;
322 pllp2 = (pllcfgr & RCC_PLL2CFGR3_PLL2PDIV2) >> RCC_PLL2CFGR3_PLL2PDIV2_Pos;
323 }
324 break;
325
326 case RCC_IC1CFGR_IC1SEL_1: /* PLL3 selected at IC1 clock source */
327 pllcfgr = READ_REG(RCC->PLL3CFGR1);
328 pllsource = pllcfgr & RCC_PLL3CFGR1_PLL3SEL;
329 pllbypass = pllcfgr & RCC_PLL3CFGR1_PLL3BYP;
330 if (pllbypass == 0U)
331 {
332 pllm = (pllcfgr & RCC_PLL3CFGR1_PLL3DIVM) >> RCC_PLL3CFGR1_PLL3DIVM_Pos;
333 plln = (pllcfgr & RCC_PLL3CFGR1_PLL3DIVN) >> RCC_PLL3CFGR1_PLL3DIVN_Pos;
334 pllfracn = READ_BIT(RCC->PLL3CFGR2, RCC_PLL3CFGR2_PLL3DIVNFRAC) >> RCC_PLL3CFGR2_PLL3DIVNFRAC_Pos;
335 pllcfgr = READ_REG(RCC->PLL3CFGR3);
336 pllp1 = (pllcfgr & RCC_PLL3CFGR3_PLL3PDIV1) >> RCC_PLL3CFGR3_PLL3PDIV1_Pos;
337 pllp2 = (pllcfgr & RCC_PLL3CFGR3_PLL3PDIV2) >> RCC_PLL3CFGR3_PLL3PDIV2_Pos;
338 }
339 break;
340
341 default: /* RCC_IC1CFGR_IC1SEL_1 | RCC_IC1CFGR_IC1SEL_0 */ /* PLL4 selected at IC1 clock source */
342 pllcfgr = READ_REG(RCC->PLL4CFGR1);
343 pllsource = pllcfgr & RCC_PLL4CFGR1_PLL4SEL;
344 pllbypass = pllcfgr & RCC_PLL4CFGR1_PLL4BYP;
345 if (pllbypass == 0U)
346 {
347 pllm = (pllcfgr & RCC_PLL4CFGR1_PLL4DIVM) >> RCC_PLL4CFGR1_PLL4DIVM_Pos;
348 plln = (pllcfgr & RCC_PLL4CFGR1_PLL4DIVN) >> RCC_PLL4CFGR1_PLL4DIVN_Pos;
349 pllfracn = READ_BIT(RCC->PLL4CFGR2, RCC_PLL4CFGR2_PLL4DIVNFRAC) >> RCC_PLL4CFGR2_PLL4DIVNFRAC_Pos;
350 pllcfgr = READ_REG(RCC->PLL4CFGR3);
351 pllp1 = (pllcfgr & RCC_PLL4CFGR3_PLL4PDIV1) >> RCC_PLL4CFGR3_PLL4PDIV1_Pos;
352 pllp2 = (pllcfgr & RCC_PLL4CFGR3_PLL4PDIV2) >> RCC_PLL4CFGR3_PLL4PDIV2_Pos;
353 }
354 break;
355 }
356
357 /* Get oscillator frequency used as PLL clock source */
358 switch (pllsource)
359 {
360 case 0: /* HSI selected as PLL clock source */
361 sysclk = HSI_VALUE >> ((RCC->HSICFGR & RCC_HSICFGR_HSIDIV) >> RCC_HSICFGR_HSIDIV_Pos);
362 break;
363 case RCC_PLL1CFGR1_PLL1SEL_0: /* MSI selected as PLL clock source */
364 if (READ_BIT(RCC->MSICFGR, RCC_MSICFGR_MSIFREQSEL) == 0UL)
365 {
366 sysclk = MSI_VALUE;
367 }
368 else
369 {
370 sysclk = 16000000UL;
371 }
372 break;
373 case RCC_PLL1CFGR1_PLL1SEL_1: /* HSE selected as PLL clock source */
374 sysclk = HSE_VALUE;
375 break;
376 case (RCC_PLL1CFGR1_PLL1SEL_1 | RCC_PLL1CFGR1_PLL1SEL_0): /* I2S_CKIN selected as PLL clock source */
377 sysclk = EXTERNAL_I2S_CLOCK_VALUE;
378 break;
379 default:
380 /* Nothing to do, should not occur */
381 break;
382 }
383
384 /* Check whether PLL is in bypass mode or not */
385 if (pllbypass == 0U)
386 {
387 /* Compte PLL output frequency (Integer and fractional modes) */
388 /* PLLVCO = (Freq * (DIVN + (FRACN / 0x1000000) / DIVM) / (DIVP1 * DIVP2)) */
389 pllvco = ((float_t)sysclk * ((float_t)plln + ((float_t)pllfracn/(float_t)0x1000000UL))) / (float_t)pllm;
390 sysclk = (uint32_t)((float_t)(pllvco/(((float_t)pllp1) * ((float_t)pllp2))));
391 }
392 /* Apply IC1 divider */
393 ic_divider = (READ_BIT(RCC->IC1CFGR, RCC_IC1CFGR_IC1INT) >> RCC_IC1CFGR_IC1INT_Pos) + 1UL;
394 sysclk = sysclk / ic_divider;
395 break;
396 default:
397 /* Nothing to do, should not occur */
398 break;
399 }
400
401 /* Return system clock frequency (CPU frequency) */
402 SystemCoreClock = sysclk;
403}
404
405/**
406 * @brief Secure Non-Secure-Callable function to return the current
407 * SystemCoreClock value after SystemCoreClock update.
408 * The SystemCoreClock variable contains the CPU core clock, it can
409 * be used by the user application to setup the SysTick timer or configure
410 * other parameters.
411 * @retval SystemCoreClock value
412 */
413CMSE_NS_ENTRY uint32_t SECURE_SystemCoreClockUpdate(void)
414{
415 SystemCoreClockUpdate();
416
417 return SystemCoreClock;
418}
419
420/**
421 * @}
422 */
423
424/**
425 * @}
426 */
427
428/**
429 * @}
430 */
Note: See TracBrowser for help on using the repository browser.