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 __IO uint32_t timeout_cpu_cycles;
186 __IO uint32_t tmpreg;
187
188 /* FPU settings ------------------------------------------------------------*/
189 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
190 SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
191 #endif
192
193 /* Configure the Vector Table location -------------------------------------*/
194 #if defined(USER_VECT_TAB_ADDRESS)
195 SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation */
196 #endif /* USER_VECT_TAB_ADDRESS */
197
198 #if defined(STM32WBAXX_SI_CUT1_0)
199 /* Work-around for ADC peripheral issue possibly impacting system
200 power consumption.
201 Refer to STM32WBA errata sheet item "HSI16 clock cannot be stopped when
202 used as kernel clock by ADC".
203 Actions: Perform a ADC activation sequence in order to update state
204 of internal signals.
205 */
206 /* Enable ADC kernel clock */
207 SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_ADC4EN);
208 /* Delay after an RCC peripheral clock enabling */
209 tmpreg = READ_BIT(RCC->AHB4ENR, RCC_AHB4ENR_ADC4EN);
210 (void)tmpreg;
211
212 /* Enable ADC */
213 SET_BIT(ADC4->CR, ADC_CR_ADEN);
214
215 /* Poll for ADC ready */
216 /* Set timeout 2 ADC clock cycles */
217 /* Note: Approximative computation and timeout execution not taking into
218 account processing CPU cycles */
219 timeout_cpu_cycles = 2;
220 while (READ_BIT(ADC4->ISR, ADC_ISR_ADRDY) == 0U)
221 {
222 timeout_cpu_cycles--;
223 if(timeout_cpu_cycles == 0U)
224 {
225 break;
226 }
227 }
228
229 /* Disable ADC */
230 SET_BIT(ADC4->CR, ADC_CR_ADDIS);
231
232 /* Poll for ADC disable is effective */
233 /* Set timeout 6 ADC clock cycles */
234 /* Note: Approximative computation and timeout execution not taking into
235 account processing CPU cycles */
236 timeout_cpu_cycles = 6;
237 while (READ_BIT(ADC4->CR, ADC_CR_ADEN) != 0U)
238 {
239 timeout_cpu_cycles--;
240 if(timeout_cpu_cycles == 0U)
241 {
242 break;
243 }
244 }
245
246 /* Disable ADC internal voltage regulator */
247 CLEAR_BIT(ADC4->CR, ADC_CR_ADVREGEN);
248
249 /* Disable ADC kernel clock */
250 CLEAR_BIT(RCC->AHB4ENR, RCC_AHB4ENR_ADC4EN);
251 #endif
252 }
253
254 /**
255 * @brief Update SystemCoreClock variable according to Clock Register Values.
256 * The SystemCoreClock variable contains the core clock (HCLK), it can
257 * be used by the user application to setup the SysTick timer or configure
258 * other parameters.
259 *
260 * @note Each time the core clock (HCLK) changes, this function must be called
261 * to update SystemCoreClock variable value. Otherwise, any configuration
262 * based on this variable will be incorrect.
263 *
264 * @note - The system frequency computed by this function is not the real
265 * frequency in the chip. It is calculated based on the predefined
266 * constant and the selected clock source:
267 *
268 * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
269 *
270 * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
271 *
272 * - If SYSCLK source is PLL1, SystemCoreClock will contain the HSE_VALUE(***)
273 * or HSI_VALUE(*) multiplied/divided by the PLL1 factors.
274 *
275 * (**) HSI_VALUE is a constant defined in STM32WBAxx_hal.h file (default value
276 * 16 MHz) but the real value may vary depending on the variations
277 * in voltage and temperature.
278 *
279 * (***) HSE_VALUE is a constant defined in STM32WBAxx_hal.h file (default value
280 * 32 MHz), user has to ensure that HSE_VALUE is same as the real
281 * frequency of the crystal used. Otherwise, this function may
282 * have wrong result.
283 *
284 * - The result of this function could be not correct when using fractional
285 * value for HSE crystal.
286 *
287 * @param None
288 * @retval None
289 */
SystemCoreClockUpdate(void)290 void SystemCoreClockUpdate(void)
291 {
292 uint32_t tmp1;
293 uint32_t tmp2;
294 uint32_t pllsource;
295 uint32_t pllr;
296 uint32_t pllm;
297 uint32_t plln;
298 float_t fracn;
299 float_t pllvco;
300
301 /* Get SYSCLK source -------------------------------------------------------*/
302 switch (RCC->CFGR1 & RCC_CFGR1_SWS)
303 {
304 case RCC_CFGR1_SWS_1: /* HSE used as system clock source */
305 SystemCoreClock = (HSE_VALUE >> ((RCC->CR & RCC_CR_HSEPRE) >> RCC_CR_HSEPRE_Pos));
306 break;
307
308 case (RCC_CFGR1_SWS_0 | RCC_CFGR1_SWS_1): /* PLL1 used as system clock source */
309 /* PLL_VCO = (PLLsource / PLLM) * PLLN * FractionnalPart
310 SYSCLK = PLL_VCO / PLLR */
311 /* Get PLL1 CFGR and DIVR register values */
312 tmp1 = RCC->PLL1CFGR;
313 tmp2 = RCC->PLL1DIVR;
314
315 /* Retrieve PLL1 multiplication factor and divider */
316 pllm = ((tmp1 & RCC_PLL1CFGR_PLL1M) >> RCC_PLL1CFGR_PLL1M_Pos) + 1U;
317 plln = (tmp2 & RCC_PLL1DIVR_PLL1N) + 1U;
318 pllr = ((tmp2 & RCC_PLL1DIVR_PLL1R) >> RCC_PLL1DIVR_PLL1R_Pos) + 1U;
319
320 /* Check if fractional part is enable */
321 if ((tmp1 & RCC_PLL1CFGR_PLL1FRACEN) != 0x00u)
322 {
323 fracn = (float_t)((uint32_t)((RCC->PLL1FRACR & RCC_PLL1FRACR_PLL1FRACN) >> RCC_PLL1FRACR_PLL1FRACN_Pos));
324 }
325 else
326 {
327 fracn = (float_t)0U;
328 }
329
330 /* determine PLL source */
331 pllsource = (tmp1 & RCC_PLL1CFGR_PLL1SRC);
332 switch (pllsource)
333 {
334 /* HSI used as PLL1 clock source */
335 case RCC_PLL1CFGR_PLL1SRC_1:
336 tmp1 = HSI_VALUE;
337 break;
338
339 /* HSE used as PLL1 clock source */
340 case (RCC_PLL1CFGR_PLL1SRC_0 | RCC_PLL1CFGR_PLL1SRC_1):
341 tmp1 = (HSE_VALUE >> ((RCC->CR & RCC_CR_HSEPRE) >> RCC_CR_HSEPRE_Pos));
342 break;
343
344 default:
345 tmp1 = 0U;
346 break;
347 }
348
349 /* Compute VCO output frequency */
350 pllvco = ((float_t) tmp1 / (float_t)pllm) * (((float_t)plln + (float_t)(fracn / (float_t)0x2000U)));
351 SystemCoreClock = (uint32_t)((float_t)(pllvco / (float_t)pllr));
352 break;
353
354 case 0x00u: /* HSI used as system clock source */
355 default:
356 SystemCoreClock = HSI_VALUE;
357 break;
358 }
359
360 /* Compute HCLK clock frequency --------------------------------------------*/
361 /* Get HCLK prescaler */
362 tmp1 = AHBPrescTable[(RCC->CFGR2 & RCC_CFGR2_HPRE)];
363
364 /* HCLK clock frequency */
365 SystemCoreClock >>= tmp1;
366 }
367
368
369 /**
370 * @}
371 */
372
373 /**
374 * @}
375 */
376
377 /**
378 * @}
379 */
380