1 /**
2 ******************************************************************************
3 * @file system_stm32wlxx.c
4 * @author MCD Application Team
5 * @brief CMSIS Cortex Device Peripheral Access Layer System Source File
6 *
7 ******************************************************************************
8 * @attention
9 *
10 * Copyright (c) 2020-2021 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_stm32wlxx.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_stm32wlxx.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 * APB1 Prescaler | 1
48 *-----------------------------------------------------------------------------
49 * APB2 Prescaler | 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 * PLLSAI1_P | NA
62 *-----------------------------------------------------------------------------
63 * PLLSAI1_Q | NA
64 *-----------------------------------------------------------------------------
65 * PLLSAI1_R | NA
66 *-----------------------------------------------------------------------------
67 * Require 48MHz for USB OTG FS, | Disabled
68 * SDIO and RNG clock |
69 *-----------------------------------------------------------------------------
70 *=============================================================================
71 */
72
73 /** @addtogroup CMSIS
74 * @{
75 */
76
77 /** @addtogroup stm32WLxx_system
78 * @{
79 */
80
81 /** @addtogroup stm32WLxx_System_Private_Includes
82 * @{
83 */
84
85 #include "stm32wlxx.h"
86
87 #if !defined (HSE_VALUE)
88 #define HSE_VALUE (32000000UL) /*!< Value of the External oscillator in Hz */
89 #endif /* HSE_VALUE */
90
91 #if !defined (MSI_VALUE)
92 #define MSI_VALUE (4000000UL) /*!< Value of the Internal oscillator in Hz*/
93 #endif /* MSI_VALUE */
94
95 #if !defined (HSI_VALUE)
96 #define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/
97 #endif /* HSI_VALUE */
98
99 #if !defined (LSI_VALUE)
100 #define LSI_VALUE (32000UL) /*!< Value of LSI in Hz*/
101 #endif /* LSI_VALUE */
102
103 #if !defined (LSE_VALUE)
104 #define LSE_VALUE (32768UL) /*!< Value of LSE in Hz*/
105 #endif /* LSE_VALUE */
106
107 /**
108 * @}
109 */
110
111 /** @addtogroup STM32WLxx_System_Private_TypesDefinitions
112 * @{
113 */
114
115 /**
116 * @}
117 */
118
119 /** @addtogroup STM32WLxx_System_Private_Defines
120 * @{
121 */
122
123 /* Note: Following vector table addresses must be defined in line with linker
124 configuration. */
125 /*!< Uncomment the following line if you need to relocate CPU1 CM4 and/or CPU2
126 CM0+ vector table anywhere in Sram or Flash. Else vector table will be kept
127 at address 0x00 which correspond to automatic remap of boot address selected */
128 /* #define USER_VECT_TAB_ADDRESS */
129 #if defined(USER_VECT_TAB_ADDRESS)
130 #ifdef CORE_CM0PLUS
131 /*!< Uncomment this line for user vector table remap in Sram else user remap
132 will be done in Flash. */
133 /* #define VECT_TAB_SRAM */
134 #if defined(VECT_TAB_SRAM)
135 #define VECT_TAB_BASE_ADDRESS SRAM2_BASE /*!< Vector Table base address field.
136 This value must be a multiple of 0x100. */
137 #define VECT_TAB_OFFSET 0x00008000U /*!< Vector Table base offset field.
138 This value must be a multiple of 0x100. */
139 #else
140 #define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
141 This value must be a multiple of 0x100. */
142 #define VECT_TAB_OFFSET 0x00020000U /*!< Vector Table base offset field.
143 This value must be a multiple of 0x100. */
144 #endif
145 #else /* CORE_CM4 */
146 /*!< Uncomment this line for user vector table remap in Sram else user remap
147 will be done in Flash. */
148 /* #define VECT_TAB_SRAM */
149 #if defined(VECT_TAB_SRAM)
150 #define VECT_TAB_BASE_ADDRESS SRAM1_BASE /*!< Vector Table base address field.
151 This value must be a multiple of 0x200. */
152 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
153 This value must be a multiple of 0x200. */
154 #else
155 #define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field.
156 This value must be a multiple of 0x200. */
157 #define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field.
158 This value must be a multiple of 0x200. */
159 #endif
160 #endif
161 #endif
162
163 /**
164 * @}
165 */
166
167 /** @addtogroup STM32WLxx_System_Private_Macros
168 * @{
169 */
170
171 /**
172 * @}
173 */
174
175 /** @addtogroup STM32WLxx_System_Private_Variables
176 * @{
177 */
178 /* The SystemCoreClock variable is updated in three ways:
179 1) from within HAL_Init()
180 2) by calling CMSIS function SystemCoreClockUpdate()
181 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
182 */
183 uint32_t SystemCoreClock = 4000000UL; /*CPU1: M4 on MSI clock after startup (4MHz)*/
184
185 const uint32_t AHBPrescTable[16UL] = {1UL, 3UL, 5UL, 1UL, 1UL, 6UL, 10UL, 32UL, 2UL, 4UL, 8UL, 16UL, 64UL, 128UL, 256UL, 512UL};
186
187 const uint32_t APBPrescTable[8UL] = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
188
189 const uint32_t MSIRangeTable[16UL] = {100000UL, 200000UL, 400000UL, 800000UL, 1000000UL, 2000000UL, \
190 4000000UL, 8000000UL, 16000000UL, 24000000UL, 32000000UL, 48000000UL, 0UL, 0UL, 0UL, 0UL}; /* 0UL values are incorrect cases */
191 /**
192 * @}
193 */
194
195 /** @addtogroup STM32WLxx_System_Private_FunctionPrototypes
196 * @{
197 */
198 /**
199 * @}
200 */
201
202 /** @addtogroup STM32WLxx_System_Private_Functions
203 * @{
204 */
205
206 /**
207 * @brief Setup the microcontroller system.
208 * @param None
209 * @retval None
210 */
SystemInit(void)211 void SystemInit(void)
212 {
213 #if defined(USER_VECT_TAB_ADDRESS)
214 /* Configure the Vector Table location add offset address ------------------*/
215 SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
216 #endif
217
218 /* FPU settings ------------------------------------------------------------*/
219 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
220 SCB->CPACR |= ((3UL << (10UL*2UL))|(3UL << (11UL*2UL))); /* set CP10 and CP11 Full Access */
221 #endif
222 }
223
224 /**
225 * @brief Update SystemCoreClock variable according to Clock Register Values.
226 * The SystemCoreClock variable contains the core clock (HCLK), it can
227 * be used by the user application to setup the SysTick timer or configure
228 * other parameters.
229 *
230 * @note Each time the core clock (HCLK) changes, this function must be called
231 * to update SystemCoreClock variable value. Otherwise, any configuration
232 * based on this variable will be incorrect.
233 *
234 * @note - The system frequency computed by this function is not the real
235 * frequency in the chip. It is calculated based on the predefined
236 * constant and the selected clock source:
237 *
238 * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*)
239 *
240 * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
241 *
242 * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
243 *
244 * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***)
245 * or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
246 *
247 * (*) MSI_VALUE is a constant defined in stm32wlxx_hal.h file (default value
248 * 4 MHz) but the real value may vary depending on the variations
249 * in voltage and temperature.
250 *
251 * (**) HSI_VALUE is a constant defined in stm32wlxx_hal_conf.h file (default value
252 * 16 MHz) but the real value may vary depending on the variations
253 * in voltage and temperature.
254 *
255 * (***) HSE_VALUE is a constant defined in stm32wlxx_hal_conf.h file (default value
256 * 32 MHz), user has to ensure that HSE_VALUE is same as the real
257 * frequency of the crystal used. Otherwise, this function may
258 * have wrong result.
259 *
260 * - The result of this function could be not correct when using fractional
261 * value for HSE crystal.
262 *
263 * @param None
264 * @retval None
265 */
SystemCoreClockUpdate(void)266 void SystemCoreClockUpdate(void)
267 {
268 uint32_t tmp, msirange, pllvco, pllr, pllsource , pllm;
269
270 /* Get MSI Range frequency--------------------------------------------------*/
271
272 /* Get MSI Range frequency--------------------------------------------------*/
273 if((RCC->CR & RCC_CR_MSIRGSEL) == 0U)
274 { /* MSISRANGE from RCC_CSR applies */
275 msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U;
276 }
277 else
278 { /* MSIRANGE from RCC_CR applies */
279 msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U;
280 }
281 /*MSI frequency range in HZ*/
282 msirange = MSIRangeTable[msirange];
283
284
285 /*SystemCoreClock=HAL_RCC_GetSysClockFreq();*/
286 /* Get SYSCLK source -------------------------------------------------------*/
287 switch (RCC->CFGR & RCC_CFGR_SWS)
288 {
289 case 0x00: /* MSI used as system clock source */
290 SystemCoreClock = msirange;
291 break;
292
293 case 0x04: /* HSI used as system clock source */
294 /* HSI used as system clock source */
295 SystemCoreClock = HSI_VALUE;
296 break;
297
298 case 0x08: /* HSE used as system clock source */
299 SystemCoreClock = HSE_VALUE;
300 break;
301
302 case 0x0C: /* PLL used as system clock source */
303 /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
304 SYSCLK = PLL_VCO / PLLR
305 */
306 pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
307 pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1UL ;
308
309 switch (pllsource)
310 {
311 case 0x02: /* HSI used as PLL clock source */
312 pllvco = (HSI_VALUE / pllm);
313 break;
314
315 case 0x03: /* HSE used as PLL clock source */
316 pllvco = (HSE_VALUE / pllm);
317 break;
318
319 default: /* MSI used as PLL clock source */
320 pllvco = (msirange / pllm);
321 break;
322 }
323
324 pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
325 pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1UL);
326
327 SystemCoreClock = pllvco/pllr;
328 break;
329
330 default:
331 SystemCoreClock = msirange;
332 break;
333 }
334
335 /* Compute HCLK clock frequency --------------------------------------------*/
336 #if defined(DUAL_CORE) && defined(CORE_CM0PLUS)
337 /* Get HCLK2 prescaler */
338 tmp = AHBPrescTable[((RCC->EXTCFGR & RCC_EXTCFGR_C2HPRE) >> RCC_EXTCFGR_C2HPRE_Pos)];
339 #else
340 /* Get HCLK1 prescaler */
341 tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
342 #endif
343
344 /* Core clock frequency */
345 SystemCoreClock = SystemCoreClock / tmp;
346 }
347 /**
348 * @}
349 */
350
351 /**
352 * @}
353 */
354
355 /**
356 * @}
357 */
358