1 /**
2 ******************************************************************************
3 * @file system_stm32wbaxx_s.c
4 * @author MCD Application Team
5 * @brief CMSIS Cortex-M33 Device Peripheral Access Layer System Source File
6 * to be used in secure application when the system implements
7 * the TrustZone-M security.
8 *
9 ******************************************************************************
10 * @attention
11 *
12 * Copyright (c) 2022 STMicroelectronics.
13 * All rights reserved.
14 *
15 * This software is licensed under terms that can be found in the LICENSE file
16 * in the root directory of this software component.
17 * If no LICENSE file comes with this software, it is provided AS-IS.
18 *
19 ******************************************************************************
20 * This file provides two functions and one global variable to be called from
21 * user application:
22 * - SystemInit(): This function is called at secure startup just after reset
23 * and before branch to secure main program.
24 * This call is made inside the "startup_stm32wbaxx.s" file.
25 *
26 * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
27 * by the user application to setup the SysTick
28 * timer or configure other parameters.
29 *
30 * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
31 * be called whenever the core clock is changed
32 * during program execution.
33 *
34 * - SECURE_SystemCoreClockUpdate(): Non-secure callable function to update
35 * the variable SystemCoreClock and return
36 * its value to the non-secure calling
37 * application. It must be called whenever
38 * the core clock is changed during program
39 * execution.
40 *
41 * After each device reset the HSI (16 MHz) is used as system clock source.
42 * Then SystemInit() function is called, in "startup_stm32wbaxx.s" file, to
43 * configure the system clock before to branch to main program.
44 *
45 * This file configures the system clock as follows:
46 *=============================================================================
47 *-----------------------------------------------------------------------------
48 * System Clock source | HSI
49 *-----------------------------------------------------------------------------
50 * SYSCLK(Hz) | 16000000
51 *-----------------------------------------------------------------------------
52 * HCLK(Hz) | 16000000
53 *-----------------------------------------------------------------------------
54 * AHB Prescaler | 1
55 *-----------------------------------------------------------------------------
56 * APB1 Prescaler | 1
57 *-----------------------------------------------------------------------------
58 * APB2 Prescaler | 1
59 *-----------------------------------------------------------------------------
60 * PLL1_SRC | No clock
61 *-----------------------------------------------------------------------------
62 * PLL1_M | 1
63 *-----------------------------------------------------------------------------
64 * PLL1_N | 128
65 *-----------------------------------------------------------------------------
66 * PLL1_P | 1
67 *-----------------------------------------------------------------------------
68 * PLL1_Q | 1
69 *-----------------------------------------------------------------------------
70 * PLL1_R | 1
71 *-----------------------------------------------------------------------------
72 * Require 48MHz for | Disabled
73 * SDIO and RNG clock |
74 *-----------------------------------------------------------------------------
75 *=============================================================================
76 */
77
78 /** @addtogroup CMSIS
79 * @{
80 */
81
82 /** @addtogroup STM32WBAxx_system
83 * @{
84 */
85
86 /** @addtogroup STM32WBAxx_System_Private_Includes
87 * @{
88 */
89
90 #include "stm32wbaxx.h"
91 #include "partition_stm32wbaxx.h" /* Trustzone-M core secure attributes */
92 #include <math.h>
93
94 /**
95 * @}
96 */
97
98 /** @addtogroup STM32WBAxx_System_Private_TypesDefinitions
99 * @{
100 */
101 #if defined ( __ICCARM__ )
102 # define CMSE_NS_ENTRY __cmse_nonsecure_entry
103 #else
104 # define CMSE_NS_ENTRY __attribute((cmse_nonsecure_entry))
105 #endif
106 /**
107 * @}
108 */
109
110 /** @addtogroup STM32WBAxx_System_Private_Defines
111 * @{
112 */
113 #if !defined (HSE_VALUE)
114 #define HSE_VALUE (32000000U) /*!< Value of the External oscillator in Hz */
115 #endif /* HSE_VALUE */
116
117 #if !defined (HSI_VALUE)
118 #define HSI_VALUE (16000000U) /*!< Value of the Internal oscillator in Hz*/
119 #endif /* HSI_VALUE */
120
121 /* Note: Following vector table addresses must be defined in line with linker
122 configuration. */
123 /*!< Uncomment the following line if you need to relocate the vector table
124 anywhere in Flash or Sram, else the vector table is kept at the automatic
125 remap of boot address selected */
126 /* #define USER_VECT_TAB_ADDRESS */
127
128 #if defined(USER_VECT_TAB_ADDRESS)
129 /*!< Uncomment the following line if you need to relocate your vector Table
130 in Sram else user remap will be done in Flash. */
131 /* #define VECT_TAB_SRAM */
132 #if defined(VECT_TAB_SRAM)
133 #define VECT_TAB_BASE_ADDRESS SRAM1_BASE /*!< Vector Table base address field.
134 This value must be a multiple of 0x200. */
135 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
136 This value must be a multiple of 0x200. */
137 #else
138 #define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
139 This value must be a multiple of 0x200. */
140 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
141 This value must be a multiple of 0x200. */
142 #endif /* VECT_TAB_SRAM */
143 #endif /* USER_VECT_TAB_ADDRESS */
144
145 /******************************************************************************/
146
147 /**
148 * @}
149 */
150
151 /** @addtogroup STM32WBAxx_System_Private_Macros
152 * @{
153 */
154
155 /**
156 * @}
157 */
158
159 /** @addtogroup STM32WBAxx_System_Private_Variables
160 * @{
161 */
162 /* The SystemCoreClock variable is updated in three ways:
163 1) by calling CMSIS function SystemCoreClockUpdate()
164 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
165 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
166 Note: If you use this function to configure the system clock; then there
167 is no need to call the 2 first functions listed above, since SystemCoreClock
168 variable is updated automatically.
169 */
170 uint32_t SystemCoreClock = 16000000U; /* The HSI16 is used as system clock source after startup from reset, configured at 16 MHz. */
171
172 const uint8_t AHBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
173 const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
174 const uint8_t AHB5PrescTable[8] = {1U, 1U, 1U, 1U, 2U, 3U, 4U, 6U};
175 /**
176 * @}
177 */
178
179 /** @addtogroup STM32WBAxx_System_Private_FunctionPrototypes
180 * @{
181 */
182
183 /**
184 * @}
185 */
186
187 /** @addtogroup STM32WBAxx_System_Private_Functions
188 * @{
189 */
190
191 /**
192 * @brief Setup the microcontroller system.
193 * @param None
194 * @retval None
195 */
196
SystemInit(void)197 void SystemInit(void)
198 {
199 #if defined(STM32WBAXX_SI_CUT1_0)
200 __IO uint32_t timeout_cpu_cycles;
201 __IO uint32_t tmpreg;
202 #endif
203
204 /* SAU/IDAU, FPU and Interrupts secure/non-secure allocation settings */
205 TZ_SAU_Setup();
206
207 /* FPU settings ------------------------------------------------------------*/
208 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
209 SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
210 #endif
211
212 /* Configure the Vector Table location -------------------------------------*/
213 #if defined(USER_VECT_TAB_ADDRESS)
214 SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation */
215 #endif /* USER_VECT_TAB_ADDRESS */
216
217 #if defined(STM32WBAXX_SI_CUT1_0)
218 /* Work-around for ADC peripheral issue possibly impacting system
219 power consumption.
220 Refer to STM32WBA errata sheet item "HSI16 clock cannot be stopped when
221 used as kernel clock by ADC".
222 Actions: Perform a ADC activation sequence in order to update state
223 of internal signals.
224 */
225 /* Enable ADC kernel clock */
226 SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_ADC4EN);
227 /* Delay after an RCC peripheral clock enabling */
228 tmpreg = READ_BIT(RCC->AHB4ENR, RCC_AHB4ENR_ADC4EN);
229 (void)tmpreg;
230
231 /* Enable ADC */
232 SET_BIT(ADC4->CR, ADC_CR_ADEN);
233
234 /* Poll for ADC ready */
235 /* Set timeout 2 ADC clock cycles */
236 /* Note: Approximative computation and timeout execution not taking into
237 account processing CPU cycles */
238 timeout_cpu_cycles = 2;
239 while (READ_BIT(ADC4->ISR, ADC_ISR_ADRDY) == 0U)
240 {
241 timeout_cpu_cycles--;
242 if(timeout_cpu_cycles == 0U)
243 {
244 break;
245 }
246 }
247
248 /* Disable ADC */
249 SET_BIT(ADC4->CR, ADC_CR_ADDIS);
250
251 /* Poll for ADC disable is effective */
252 /* Set timeout 6 ADC clock cycles */
253 /* Note: Approximative computation and timeout execution not taking into
254 account processing CPU cycles */
255 timeout_cpu_cycles = 6;
256 while (READ_BIT(ADC4->CR, ADC_CR_ADEN) != 0U)
257 {
258 timeout_cpu_cycles--;
259 if(timeout_cpu_cycles == 0U)
260 {
261 break;
262 }
263 }
264
265 /* Disable ADC internal voltage regulator */
266 CLEAR_BIT(ADC4->CR, ADC_CR_ADVREGEN);
267
268 /* Disable ADC kernel clock */
269 CLEAR_BIT(RCC->AHB4ENR, RCC_AHB4ENR_ADC4EN);
270 #endif
271 }
272
273 /**
274 * @brief Update SystemCoreClock variable according to Clock Register Values.
275 * The SystemCoreClock variable contains the core clock (HCLK), it can
276 * be used by the user application to setup the SysTick timer or configure
277 * other parameters.
278 *
279 * @note Depending on secure or non-secure compilation, the adequate RCC peripheral
280 * memory are is accessed thanks to RCC alias defined in stm32wbxxxx.h device file
281 * so either from RCC_S peripheral register mapped memory in secure or from
282 * RCC_NS peripheral register mapped memory in non-secure.
283 *
284 * @note Each time the core clock (HCLK) changes, this function must be called
285 * to update SystemCoreClock variable value. Otherwise, any configuration
286 * based on this variable will be incorrect.
287 *
288 * @note - The system frequency computed by this function is not the real
289 * frequency in the chip. It is calculated based on the predefined
290 * constant and the selected clock source:
291 *
292 * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
293 *
294 * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
295 *
296 * - If SYSCLK source is PLL1, SystemCoreClock will contain the HSE_VALUE(***)
297 * or HSI_VALUE(*) multiplied/divided by the PLL1 factors.
298 *
299 * (**) HSI_VALUE is a constant defined in STM32WBAxx_hal.h file (default value
300 * 16 MHz) but the real value may vary depending on the variations
301 * in voltage and temperature.
302 *
303 * (***) HSE_VALUE is a constant defined in STM32WBAxx_hal.h file (default value
304 * 32 MHz), user has to ensure that HSE_VALUE is same as the real
305 * frequency of the crystal used. Otherwise, this function may
306 * have wrong result.
307 *
308 * - The result of this function could be not correct when using fractional
309 * value for HSE crystal.
310 *
311 * @param None
312 * @retval None
313 */
SystemCoreClockUpdate(void)314 void SystemCoreClockUpdate(void)
315 {
316 uint32_t tmp1;
317 uint32_t tmp2;
318 uint32_t pllsource;
319 uint32_t pllr;
320 uint32_t pllm;
321 uint32_t plln;
322 float_t fracn;
323 float_t pllvco;
324
325 /* Get SYSCLK source -------------------------------------------------------*/
326 switch (RCC->CFGR1 & RCC_CFGR1_SWS)
327 {
328 case RCC_CFGR1_SWS_1: /* HSE used as system clock source */
329 SystemCoreClock = (HSE_VALUE >> ((RCC->CR & RCC_CR_HSEPRE) >> RCC_CR_HSEPRE_Pos));
330 break;
331
332 case (RCC_CFGR1_SWS_0 | RCC_CFGR1_SWS_1): /* PLL1 used as system clock source */
333 /* PLL_VCO = (PLLsource / PLLM) * PLLN * FractionnalPart
334 SYSCLK = PLL_VCO / PLLR */
335 /* Get PLL1 CFGR and DIVR register values */
336 tmp1 = RCC->PLL1CFGR;
337 tmp2 = RCC->PLL1DIVR;
338
339 /* Retrieve PLL1 multiplication factor and divider */
340 pllm = ((tmp1 & RCC_PLL1CFGR_PLL1M) >> RCC_PLL1CFGR_PLL1M_Pos) + 1U;
341 plln = (tmp2 & RCC_PLL1DIVR_PLL1N) + 1U;
342 pllr = ((tmp2 & RCC_PLL1DIVR_PLL1R) >> RCC_PLL1DIVR_PLL1R_Pos) + 1U;
343
344 /* Check if fractional part is enable */
345 if ((tmp1 & RCC_PLL1CFGR_PLL1FRACEN) != 0x00u)
346 {
347 fracn = (float_t)((uint32_t)((RCC->PLL1FRACR & RCC_PLL1FRACR_PLL1FRACN) >> RCC_PLL1FRACR_PLL1FRACN_Pos));
348 }
349 else
350 {
351 fracn = (float_t)0U;
352 }
353
354 /* determine PLL source */
355 pllsource = (tmp1 & RCC_PLL1CFGR_PLL1SRC);
356 switch (pllsource)
357 {
358 /* HSI used as PLL1 clock source */
359 case RCC_PLL1CFGR_PLL1SRC_1:
360 tmp1 = HSI_VALUE;
361 break;
362
363 /* HSE used as PLL1 clock source */
364 case (RCC_PLL1CFGR_PLL1SRC_0 | RCC_PLL1CFGR_PLL1SRC_1):
365 tmp1 = (HSE_VALUE >> ((RCC->CR & RCC_CR_HSEPRE) >> RCC_CR_HSEPRE_Pos));
366 break;
367
368 default:
369 tmp1 = 0U;
370 break;
371 }
372
373 /* Compute VCO output frequency */
374 pllvco = ((float_t) tmp1 / (float_t)pllm) * (((float_t)plln + (float_t)(fracn / (float_t)0x2000U)));
375 SystemCoreClock = (uint32_t)((float_t)(pllvco / (float_t)pllr));
376 break;
377
378 case 0x00u: /* HSI used as system clock source */
379 default:
380 SystemCoreClock = HSI_VALUE;
381 break;
382 }
383
384 /* Compute HCLK clock frequency --------------------------------------------*/
385 /* Get HCLK prescaler */
386 tmp1 = AHBPrescTable[(RCC->CFGR2 & RCC_CFGR2_HPRE)];
387
388 /* HCLK clock frequency */
389 SystemCoreClock >>= tmp1;
390 }
391
392 /**
393 * @brief Secure Non-Secure-Callable function to return the current
394 * SystemCoreClock value after SystemCoreClock update.
395 * The SystemCoreClock variable contains the core clock (HCLK), it can
396 * be used by the user application to setup the SysTick timer or configure
397 * other parameters.
398 * @retval SystemCoreClock value (HCLK)
399 */
SECURE_SystemCoreClockUpdate(void)400 CMSE_NS_ENTRY uint32_t SECURE_SystemCoreClockUpdate(void)
401 {
402 SystemCoreClockUpdate();
403
404 return SystemCoreClock;
405 }
406
407
408 /**
409 * @}
410 */
411
412 /**
413 * @}
414 */
415
416 /**
417 * @}
418 */
419