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