1 /**
2   ******************************************************************************
3   * @file    system_stm32l5xx.c
4   * @author  MCD Application Team
5   * @brief   CMSIS Cortex-M33 Device Peripheral Access Layer System Source File
6   *
7   *   This file provides two functions and one global variable to be called from
8   *   user application:
9   *      - SystemInit(): This function is called at startup just after reset and
10   *                      before branch to main program. This call is made inside
11   *                      the "startup_stm32l5xx.s" file.
12   *
13   *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
14   *                                  by the user application to setup the SysTick
15   *                                  timer or configure other parameters.
16   *
17   *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
18   *                                 be called whenever the core clock is changed
19   *                                 during program execution.
20   *
21   *   After each device reset the MSI (4 MHz) is used as system clock source.
22   *   Then SystemInit() function is called, in "startup_stm32l5xx.s" file, to
23   *   configure the system clock before to branch to main program.
24   *
25   *   This file configures the system clock as follows:
26   *=============================================================================
27   *-----------------------------------------------------------------------------
28   *        System Clock source                    | MSI
29   *-----------------------------------------------------------------------------
30   *        SYSCLK(Hz)                             | 4000000
31   *-----------------------------------------------------------------------------
32   *        HCLK(Hz)                               | 4000000
33   *-----------------------------------------------------------------------------
34   *        AHB Prescaler                          | 1
35   *-----------------------------------------------------------------------------
36   *        APB1 Prescaler                         | 1
37   *-----------------------------------------------------------------------------
38   *        APB2 Prescaler                         | 1
39   *-----------------------------------------------------------------------------
40   *        PLL_SRC                                | No clock
41   *-----------------------------------------------------------------------------
42   *        PLL_M                                  | 1
43   *-----------------------------------------------------------------------------
44   *        PLL_N                                  | 8
45   *-----------------------------------------------------------------------------
46   *        PLL_P                                  | 7
47   *-----------------------------------------------------------------------------
48   *        PLL_Q                                  | 2
49   *-----------------------------------------------------------------------------
50   *        PLL_R                                  | 2
51   *-----------------------------------------------------------------------------
52   *        PLLSAI1_SRC                            | NA
53   *-----------------------------------------------------------------------------
54   *        PLLSAI1_M                              | NA
55   *-----------------------------------------------------------------------------
56   *        PLLSAI1_N                              | NA
57   *-----------------------------------------------------------------------------
58   *        PLLSAI1_P                              | NA
59   *-----------------------------------------------------------------------------
60   *        PLLSAI1_Q                              | NA
61   *-----------------------------------------------------------------------------
62   *        PLLSAI1_R                              | NA
63   *-----------------------------------------------------------------------------
64   *        PLLSAI2_SRC                            | NA
65   *-----------------------------------------------------------------------------
66   *        PLLSAI2_M                              | NA
67   *-----------------------------------------------------------------------------
68   *        PLLSAI2_N                              | NA
69   *-----------------------------------------------------------------------------
70   *        PLLSAI2_P                              | NA
71   *-----------------------------------------------------------------------------
72   *        Require 48MHz for USB FS,              | Disabled
73   *        SDIO and RNG clock                     |
74   *-----------------------------------------------------------------------------
75   *=============================================================================
76   ******************************************************************************
77   * @attention
78   *
79   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
80   * All rights reserved.</center></h2>
81   *
82   * This software component is licensed by ST under BSD 3-Clause license,
83   * the "License"; You may not use this file except in compliance with the
84   * License. You may obtain a copy of the License at:
85   *                        opensource.org/licenses/BSD-3-Clause
86   *
87   ******************************************************************************
88   */
89 
90 /** @addtogroup CMSIS
91   * @{
92   */
93 
94 /** @addtogroup STM32L5xx_system
95   * @{
96   */
97 
98 /** @addtogroup STM32L5xx_System_Private_Includes
99   * @{
100   */
101 
102 #include "stm32l5xx.h"
103 
104 #if !defined  (HSE_VALUE)
105   #define HSE_VALUE    16000000U /*!< Value of the External oscillator in Hz */
106 #endif /* HSE_VALUE */
107 
108 #if !defined  (MSI_VALUE)
109   #define MSI_VALUE    4000000U  /*!< Value of the Internal oscillator in Hz*/
110 #endif /* MSI_VALUE */
111 
112 #if !defined  (HSI_VALUE)
113   #define HSI_VALUE    16000000U /*!< Value of the Internal oscillator in Hz*/
114 #endif /* HSI_VALUE */
115 
116 /**
117   * @}
118   */
119 
120 /** @addtogroup STM32L5xx_System_Private_TypesDefinitions
121   * @{
122   */
123 
124 /**
125   * @}
126   */
127 
128 /** @addtogroup STM32L5xx_System_Private_Defines
129   * @{
130   */
131 
132 /************************* Miscellaneous Configuration ************************/
133 /*!< Uncomment the following line if you need to relocate your vector Table in
134      Internal SRAM. */
135 /* #define VECT_TAB_SRAM */
136 #define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field.
137                                    This value must be a multiple of 0x200. */
138 /******************************************************************************/
139 /**
140   * @}
141   */
142 
143 /** @addtogroup STM32L5xx_System_Private_Macros
144   * @{
145   */
146 
147 /**
148   * @}
149   */
150 
151 /** @addtogroup STM32L5xx_System_Private_Variables
152   * @{
153   */
154   /* The SystemCoreClock variable is updated in three ways:
155       1) by calling CMSIS function SystemCoreClockUpdate()
156       2) by calling HAL API function HAL_RCC_GetHCLKFreq()
157       3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
158          Note: If you use this function to configure the system clock; then there
159                is no need to call the 2 first functions listed above, since SystemCoreClock
160                variable is updated automatically.
161   */
162   uint32_t SystemCoreClock = 4000000U;
163 
164   const uint8_t  AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
165   const uint8_t  APBPrescTable[8] =  {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
166   const uint32_t MSIRangeTable[16] = {100000U,   200000U,   400000U,   800000U,  1000000U,  2000000U, \
167                                       4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U, \
168                                       0U,       0U,       0U,        0U};  /* MISRAC-2012: 0U for unexpected value */
169 /**
170   * @}
171   */
172 
173 /** @addtogroup STM32L5xx_System_Private_FunctionPrototypes
174   * @{
175   */
176 
177 /**
178   * @}
179   */
180 
181 /** @addtogroup STM32L5xx_System_Private_Functions
182   * @{
183   */
184 
185 /**
186   * @brief  Setup the microcontroller system.
187   * @retval None
188   */
189 
SystemInit(void)190 void SystemInit(void)
191 {
192 #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
193   extern uint32_t __VECTOR_TABLE;
194   SCB->VTOR = (uint32_t) &__VECTOR_TABLE;
195 #endif
196 
197   /* Configure the Vector Table location add offset address ------------------*/
198 #ifdef VECT_TAB_SRAM
199   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
200 #endif
201 }
202 
203 /**
204   * @brief  Update SystemCoreClock variable according to Clock Register Values.
205   *         The SystemCoreClock variable contains the core clock (HCLK), it can
206   *         be used by the user application to setup the SysTick timer or configure
207   *         other parameters.
208   *
209   * @note   Each time the core clock (HCLK) changes, this function must be called
210   *         to update SystemCoreClock variable value. Otherwise, any configuration
211   *         based on this variable will be incorrect.
212   *
213   * @note   - The system frequency computed by this function is not the real
214   *           frequency in the chip. It is calculated based on the predefined
215   *           constant and the selected clock source:
216   *
217   *           - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*)
218   *
219   *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**)
220   *
221   *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
222   *
223   *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***)
224   *             or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
225   *
226   *         (*) MSI_VALUE is a constant defined in stm32l5xx_hal.h file (default value
227   *             4 MHz) but the real value may vary depending on the variations
228   *             in voltage and temperature.
229   *
230   *         (**) HSI_VALUE is a constant defined in stm32l5xx_hal.h file (default value
231   *              16 MHz) but the real value may vary depending on the variations
232   *              in voltage and temperature.
233   *
234   *         (***) HSE_VALUE is a constant defined in stm32l5xx_hal.h file (default value
235   *              8 MHz), user has to ensure that HSE_VALUE is same as the real
236   *              frequency of the crystal used. Otherwise, this function may
237   *              have wrong result.
238   *
239   *         - The result of this function could be not correct when using fractional
240   *           value for HSE crystal.
241   *
242   * @retval None
243   */
SystemCoreClockUpdate(void)244 void SystemCoreClockUpdate(void)
245 {
246   uint32_t tmp, msirange, pllvco, pllsource, pllm, pllr;
247 
248   /* Get MSI Range frequency--------------------------------------------------*/
249   if((RCC->CR & RCC_CR_MSIRGSEL) == 0U)
250   { /* MSISRANGE from RCC_CSR applies */
251     msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U;
252   }
253   else
254   { /* MSIRANGE from RCC_CR applies */
255     msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U;
256   }
257   /*MSI frequency range in HZ*/
258   msirange = MSIRangeTable[msirange];
259 
260   /* Get SYSCLK source -------------------------------------------------------*/
261   switch (RCC->CFGR & RCC_CFGR_SWS)
262   {
263     case 0x00:  /* MSI used as system clock source */
264       SystemCoreClock = msirange;
265       break;
266 
267     case 0x04:  /* HSI used as system clock source */
268       SystemCoreClock = HSI_VALUE;
269       break;
270 
271     case 0x08:  /* HSE used as system clock source */
272       SystemCoreClock = HSE_VALUE;
273       break;
274 
275     case 0x0C:  /* PLL used as system clock  source */
276       /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
277          SYSCLK = PLL_VCO / PLLR
278          */
279       pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
280       pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U ;
281 
282       switch (pllsource)
283       {
284         case 0x02:  /* HSI used as PLL clock source */
285           pllvco = (HSI_VALUE / pllm);
286           break;
287 
288         case 0x03:  /* HSE used as PLL clock source */
289           pllvco = (HSE_VALUE / pllm);
290           break;
291 
292         default:    /* MSI used as PLL clock source */
293           pllvco = (msirange / pllm);
294           break;
295       }
296       pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U);
297       pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U;
298       SystemCoreClock = pllvco/pllr;
299       break;
300 
301     default:
302       SystemCoreClock = msirange;
303       break;
304   }
305   /* Compute HCLK clock frequency --------------------------------------------*/
306   /* Get HCLK prescaler */
307   tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
308   /* HCLK clock frequency */
309   SystemCoreClock >>= tmp;
310 }
311 
312 
313 /**
314   * @}
315   */
316 
317 /**
318   * @}
319   */
320 
321 /**
322   * @}
323   */
324 
325 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
326