xref: /btstack/port/stm32-l073rz-nucleo-em9304/Src/system_stm32l0xx.c (revision e838079242074edcbcbb400962776e15fe6ca6cb)
1 /**
2   ******************************************************************************
3   * @file    system_stm32l0xx.c
4   * @author  MCD Application Team
5   * @brief   CMSIS Cortex-M0+ 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_stm32l0xx.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   *
22   ******************************************************************************
23   * @attention
24   *
25   * <h2><center>&copy; Copyright(c) 2016 STMicroelectronics.
26   * All rights reserved.</center></h2>
27   *
28   * This software component is licensed by ST under BSD 3-Clause license,
29   * the "License"; You may not use this file except in compliance with the
30   * License. You may obtain a copy of the License at:
31   *                        opensource.org/licenses/BSD-3-Clause
32   *
33   ******************************************************************************
34   */
35 
36 /** @addtogroup CMSIS
37   * @{
38   */
39 
40 /** @addtogroup stm32l0xx_system
41   * @{
42   */
43 
44 /** @addtogroup STM32L0xx_System_Private_Includes
45   * @{
46   */
47 
48 #include "stm32l0xx.h"
49 
50 #if !defined  (HSE_VALUE)
51   #define HSE_VALUE    ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
52 #endif /* HSE_VALUE */
53 
54 #if !defined  (MSI_VALUE)
55   #define MSI_VALUE    ((uint32_t)2097152U) /*!< Value of the Internal oscillator in Hz*/
56 #endif /* MSI_VALUE */
57 
58 #if !defined  (HSI_VALUE)
59   #define HSI_VALUE    ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
60 #endif /* HSI_VALUE */
61 
62 
63 /**
64   * @}
65   */
66 
67 /** @addtogroup STM32L0xx_System_Private_TypesDefinitions
68   * @{
69   */
70 
71 /**
72   * @}
73   */
74 
75 /** @addtogroup STM32L0xx_System_Private_Defines
76   * @{
77   */
78 /************************* Miscellaneous Configuration ************************/
79 
80 /*!< Uncomment the following line if you need to relocate your vector Table in
81      Internal SRAM. */
82 /* #define VECT_TAB_SRAM */
83 #define VECT_TAB_OFFSET  0x00U /*!< Vector Table base offset field.
84                                    This value must be a multiple of 0x100. */
85 /******************************************************************************/
86 /**
87   * @}
88   */
89 
90 /** @addtogroup STM32L0xx_System_Private_Macros
91   * @{
92   */
93 
94 /**
95   * @}
96   */
97 
98 /** @addtogroup STM32L0xx_System_Private_Variables
99   * @{
100   */
101   /* This variable is updated in three ways:
102       1) by calling CMSIS function SystemCoreClockUpdate()
103       2) by calling HAL API function HAL_RCC_GetHCLKFreq()
104       3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
105          Note: If you use this function to configure the system clock; then there
106                is no need to call the 2 first functions listed above, since SystemCoreClock
107                variable is updated automatically.
108   */
109   uint32_t SystemCoreClock = 2097152U; /* 32.768 kHz * 2^6 */
110   const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
111   const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
112   const uint8_t PLLMulTable[9] = {3U, 4U, 6U, 8U, 12U, 16U, 24U, 32U, 48U};
113 
114 /**
115   * @}
116   */
117 
118 /** @addtogroup STM32L0xx_System_Private_FunctionPrototypes
119   * @{
120   */
121 
122 /**
123   * @}
124   */
125 
126 /** @addtogroup STM32L0xx_System_Private_Functions
127   * @{
128   */
129 
130 /**
131   * @brief  Setup the microcontroller system.
132   * @param  None
133   * @retval None
134   */
SystemInit(void)135 void SystemInit (void)
136 {
137 /*!< Set MSION bit */
138   RCC->CR |= (uint32_t)0x00000100U;
139 
140   /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
141   RCC->CFGR &= (uint32_t) 0x88FF400CU;
142 
143   /*!< Reset HSION, HSIDIVEN, HSEON, CSSON and PLLON bits */
144   RCC->CR &= (uint32_t)0xFEF6FFF6U;
145 
146   /*!< Reset HSI48ON  bit */
147   RCC->CRRCR &= (uint32_t)0xFFFFFFFEU;
148 
149   /*!< Reset HSEBYP bit */
150   RCC->CR &= (uint32_t)0xFFFBFFFFU;
151 
152   /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
153   RCC->CFGR &= (uint32_t)0xFF02FFFFU;
154 
155   /*!< Disable all interrupts */
156   RCC->CIER = 0x00000000U;
157 
158   /* Configure the Vector Table location add offset address ------------------*/
159 #ifdef VECT_TAB_SRAM
160   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
161 #else
162   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
163 #endif
164 }
165 
166 /**
167   * @brief  Update SystemCoreClock according to Clock Register Values
168   *         The SystemCoreClock variable contains the core clock (HCLK), it can
169   *         be used by the user application to setup the SysTick timer or configure
170   *         other parameters.
171   *
172   * @note   Each time the core clock (HCLK) changes, this function must be called
173   *         to update SystemCoreClock variable value. Otherwise, any configuration
174   *         based on this variable will be incorrect.
175   *
176   * @note   - The system frequency computed by this function is not the real
177   *           frequency in the chip. It is calculated based on the predefined
178   *           constant and the selected clock source:
179   *
180   *           - If SYSCLK source is MSI, SystemCoreClock will contain the MSI
181   *             value as defined by the MSI range.
182   *
183   *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
184   *
185   *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
186   *
187   *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
188   *             or HSI_VALUE(*) multiplied/divided by the PLL factors.
189   *
190   *         (*) HSI_VALUE is a constant defined in stm32l0xx_hal.h file (default value
191   *             16 MHz) but the real value may vary depending on the variations
192   *             in voltage and temperature.
193   *
194   *         (**) HSE_VALUE is a constant defined in stm32l0xx_hal.h file (default value
195   *              8 MHz), user has to ensure that HSE_VALUE is same as the real
196   *              frequency of the crystal used. Otherwise, this function may
197   *              have wrong result.
198   *
199   *         - The result of this function could be not correct when using fractional
200   *           value for HSE crystal.
201   * @param  None
202   * @retval None
203   */
SystemCoreClockUpdate(void)204 void SystemCoreClockUpdate (void)
205 {
206   uint32_t tmp = 0U, pllmul = 0U, plldiv = 0U, pllsource = 0U, msirange = 0U;
207 
208   /* Get SYSCLK source -------------------------------------------------------*/
209   tmp = RCC->CFGR & RCC_CFGR_SWS;
210 
211   switch (tmp)
212   {
213     case 0x00U:  /* MSI used as system clock */
214       msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> RCC_ICSCR_MSIRANGE_Pos;
215       SystemCoreClock = (32768U * (1U << (msirange + 1U)));
216       break;
217     case 0x04U:  /* HSI used as system clock */
218       if ((RCC->CR & RCC_CR_HSIDIVF) != 0U)
219       {
220         SystemCoreClock = HSI_VALUE / 4U;
221       }
222       else
223       {
224         SystemCoreClock = HSI_VALUE;
225       }
226       break;
227     case 0x08U:  /* HSE used as system clock */
228       SystemCoreClock = HSE_VALUE;
229       break;
230     default:  /* PLL used as system clock */
231       /* Get PLL clock source and multiplication factor ----------------------*/
232       pllmul = RCC->CFGR & RCC_CFGR_PLLMUL;
233       plldiv = RCC->CFGR & RCC_CFGR_PLLDIV;
234       pllmul = PLLMulTable[(pllmul >> RCC_CFGR_PLLMUL_Pos)];
235       plldiv = (plldiv >> RCC_CFGR_PLLDIV_Pos) + 1U;
236 
237       pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
238 
239       if (pllsource == 0x00U)
240       {
241         /* HSI oscillator clock selected as PLL clock entry */
242         if ((RCC->CR & RCC_CR_HSIDIVF) != 0U)
243         {
244           SystemCoreClock = (((HSI_VALUE / 4U) * pllmul) / plldiv);
245         }
246         else
247         {
248           SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv);
249         }
250       }
251       else
252       {
253         /* HSE selected as PLL clock entry */
254         SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv);
255       }
256       break;
257   }
258   /* Compute HCLK clock frequency --------------------------------------------*/
259   /* Get HCLK prescaler */
260   tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos)];
261   /* HCLK clock frequency */
262   SystemCoreClock >>= tmp;
263 }
264 
265 
266 
267 /**
268   * @}
269   */
270 
271 /**
272   * @}
273   */
274 
275 /**
276   * @}
277   */
278 
279 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
280