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