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