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