1 /**
2   ******************************************************************************
3   * @file    system_stm32f1xx.c
4   * @author  MCD Application Team
5   * @brief   CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
6   *
7   * 1.  This file provides two functions and one global variable to be called from
8   *     user application:
9   *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
10   *                      factors, AHB/APBx prescalers and Flash settings).
11   *                      This function is called at startup just after reset and
12   *                      before branch to main program. This call is made inside
13   *                      the "startup_stm32f1xx_xx.s" file.
14   *
15   *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
16   *                                  by the user application to setup the SysTick
17   *                                  timer or configure other parameters.
18   *
19   *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
20   *                                 be called whenever the core clock is changed
21   *                                 during program execution.
22   *
23   * 2. After each device reset the HSI (8 MHz) is used as system clock source.
24   *    Then SystemInit() function is called, in "startup_stm32f1xx_xx.s" file, to
25   *    configure the system clock before to branch to main program.
26   *
27   * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depending on
28   *    the product used), refer to "HSE_VALUE".
29   *    When HSE is used as system clock source, directly or through PLL, and you
30   *    are using different crystal you have to adapt the HSE value to your own
31   *    configuration.
32   *
33   ******************************************************************************
34   * @attention
35   *
36   * Copyright (c) 2017-2021 STMicroelectronics.
37   * All rights reserved.
38   *
39   * This software is licensed under terms that can be found in the LICENSE file
40   * in the root directory of this software component.
41   * If no LICENSE file comes with this software, it is provided AS-IS.
42   *
43   ******************************************************************************
44   */
45 
46 /** @addtogroup CMSIS
47   * @{
48   */
49 
50 /** @addtogroup stm32f1xx_system
51   * @{
52   */
53 
54 /** @addtogroup STM32F1xx_System_Private_Includes
55   * @{
56   */
57 
58 #include "stm32f1xx.h"
59 
60 /**
61   * @}
62   */
63 
64 /** @addtogroup STM32F1xx_System_Private_TypesDefinitions
65   * @{
66   */
67 
68 /**
69   * @}
70   */
71 
72 /** @addtogroup STM32F1xx_System_Private_Defines
73   * @{
74   */
75 
76 #if !defined  (HSE_VALUE)
77   #define HSE_VALUE               8000000U /*!< Default value of the External oscillator in Hz.
78                                                 This value can be provided and adapted by the user application. */
79 #endif /* HSE_VALUE */
80 
81 #if !defined  (HSI_VALUE)
82   #define HSI_VALUE               8000000U /*!< Default value of the Internal oscillator in Hz.
83                                                 This value can be provided and adapted by the user application. */
84 #endif /* HSI_VALUE */
85 
86 /*!< Uncomment the following line if you need to use external SRAM  */
87 #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
88 /* #define DATA_IN_ExtSRAM */
89 #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
90 
91 /* Note: Following vector table addresses must be defined in line with linker
92          configuration. */
93 /*!< Uncomment the following line if you need to relocate the vector table
94      anywhere in Flash or Sram, else the vector table is kept at the automatic
95      remap of boot address selected */
96 /* #define USER_VECT_TAB_ADDRESS */
97 
98 #if defined(USER_VECT_TAB_ADDRESS)
99 /*!< Uncomment the following line if you need to relocate your vector Table
100      in Sram else user remap will be done in Flash. */
101 /* #define VECT_TAB_SRAM */
102 #if defined(VECT_TAB_SRAM)
103 #define VECT_TAB_BASE_ADDRESS   SRAM_BASE       /*!< Vector Table base address field.
104                                                      This value must be a multiple of 0x200. */
105 #define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
106                                                      This value must be a multiple of 0x200. */
107 #else
108 #define VECT_TAB_BASE_ADDRESS   FLASH_BASE      /*!< Vector Table base address field.
109                                                      This value must be a multiple of 0x200. */
110 #define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
111                                                      This value must be a multiple of 0x200. */
112 #endif /* VECT_TAB_SRAM */
113 #endif /* USER_VECT_TAB_ADDRESS */
114 
115 /******************************************************************************/
116 
117 /**
118   * @}
119   */
120 
121 /** @addtogroup STM32F1xx_System_Private_Macros
122   * @{
123   */
124 
125 /**
126   * @}
127   */
128 
129 /** @addtogroup STM32F1xx_System_Private_Variables
130   * @{
131   */
132 
133   /* This variable is updated in three ways:
134       1) by calling CMSIS function SystemCoreClockUpdate()
135       2) by calling HAL API function HAL_RCC_GetHCLKFreq()
136       3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
137          Note: If you use this function to configure the system clock; then there
138                is no need to call the 2 first functions listed above, since SystemCoreClock
139                variable is updated automatically.
140   */
141 uint32_t SystemCoreClock = 8000000;
142 const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
143 const uint8_t APBPrescTable[8U] =  {0, 0, 0, 0, 1, 2, 3, 4};
144 
145 /**
146   * @}
147   */
148 
149 /** @addtogroup STM32F1xx_System_Private_FunctionPrototypes
150   * @{
151   */
152 
153 #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
154 #ifdef DATA_IN_ExtSRAM
155   static void SystemInit_ExtMemCtl(void);
156 #endif /* DATA_IN_ExtSRAM */
157 #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
158 
159 /**
160   * @}
161   */
162 
163 /** @addtogroup STM32F1xx_System_Private_Functions
164   * @{
165   */
166 
167 /**
168   * @brief  Setup the microcontroller system
169   *         Initialize the Embedded Flash Interface, the PLL and update the
170   *         SystemCoreClock variable.
171   * @note   This function should be used only after reset.
172   * @param  None
173   * @retval None
174   */
SystemInit(void)175 void SystemInit (void)
176 {
177 #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
178   #ifdef DATA_IN_ExtSRAM
179     SystemInit_ExtMemCtl();
180   #endif /* DATA_IN_ExtSRAM */
181 #endif
182 
183   /* Configure the Vector Table location -------------------------------------*/
184 #if defined(USER_VECT_TAB_ADDRESS)
185   SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
186 #endif /* USER_VECT_TAB_ADDRESS */
187 }
188 
189 /**
190   * @brief  Update SystemCoreClock variable according to Clock Register Values.
191   *         The SystemCoreClock variable contains the core clock (HCLK), it can
192   *         be used by the user application to setup the SysTick timer or configure
193   *         other parameters.
194   *
195   * @note   Each time the core clock (HCLK) changes, this function must be called
196   *         to update SystemCoreClock variable value. Otherwise, any configuration
197   *         based on this variable will be incorrect.
198   *
199   * @note   - The system frequency computed by this function is not the real
200   *           frequency in the chip. It is calculated based on the predefined
201   *           constant and the selected clock source:
202   *
203   *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
204   *
205   *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
206   *
207   *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
208   *             or HSI_VALUE(*) multiplied by the PLL factors.
209   *
210   *         (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value
211   *             8 MHz) but the real value may vary depending on the variations
212   *             in voltage and temperature.
213   *
214   *         (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value
215   *              8 MHz or 25 MHz, depending on the product used), user has to ensure
216   *              that HSE_VALUE is same as the real frequency of the crystal used.
217   *              Otherwise, this function may have wrong result.
218   *
219   *         - The result of this function could be not correct when using fractional
220   *           value for HSE crystal.
221   * @param  None
222   * @retval None
223   */
SystemCoreClockUpdate(void)224 void SystemCoreClockUpdate (void)
225 {
226   uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U;
227 
228 #if defined(STM32F105xC) || defined(STM32F107xC)
229   uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U;
230 #endif /* STM32F105xC */
231 
232 #if defined(STM32F100xB) || defined(STM32F100xE)
233   uint32_t prediv1factor = 0U;
234 #endif /* STM32F100xB or STM32F100xE */
235 
236   /* Get SYSCLK source -------------------------------------------------------*/
237   tmp = RCC->CFGR & RCC_CFGR_SWS;
238 
239   switch (tmp)
240   {
241     case 0x00U:  /* HSI used as system clock */
242       SystemCoreClock = HSI_VALUE;
243       break;
244     case 0x04U:  /* HSE used as system clock */
245       SystemCoreClock = HSE_VALUE;
246       break;
247     case 0x08U:  /* PLL used as system clock */
248 
249       /* Get PLL clock source and multiplication factor ----------------------*/
250       pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
251       pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
252 
253 #if !defined(STM32F105xC) && !defined(STM32F107xC)
254       pllmull = ( pllmull >> 18U) + 2U;
255 
256       if (pllsource == 0x00U)
257       {
258         /* HSI oscillator clock divided by 2 selected as PLL clock entry */
259         SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
260       }
261       else
262       {
263  #if defined(STM32F100xB) || defined(STM32F100xE)
264        prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U;
265        /* HSE oscillator clock selected as PREDIV1 clock entry */
266        SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
267  #else
268         /* HSE selected as PLL clock entry */
269         if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
270         {/* HSE oscillator clock divided by 2 */
271           SystemCoreClock = (HSE_VALUE >> 1U) * pllmull;
272         }
273         else
274         {
275           SystemCoreClock = HSE_VALUE * pllmull;
276         }
277  #endif
278       }
279 #else
280       pllmull = pllmull >> 18U;
281 
282       if (pllmull != 0x0DU)
283       {
284          pllmull += 2U;
285       }
286       else
287       { /* PLL multiplication factor = PLL input clock * 6.5 */
288         pllmull = 13U / 2U;
289       }
290 
291       if (pllsource == 0x00U)
292       {
293         /* HSI oscillator clock divided by 2 selected as PLL clock entry */
294         SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
295       }
296       else
297       {/* PREDIV1 selected as PLL clock entry */
298 
299         /* Get PREDIV1 clock source and division factor */
300         prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;
301         prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U;
302 
303         if (prediv1source == 0U)
304         {
305           /* HSE oscillator clock selected as PREDIV1 clock entry */
306           SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
307         }
308         else
309         {/* PLL2 clock selected as PREDIV1 clock entry */
310 
311           /* Get PREDIV2 division factor and PLL2 multiplication factor */
312           prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4U) + 1U;
313           pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8U) + 2U;
314           SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;
315         }
316       }
317 #endif /* STM32F105xC */
318       break;
319 
320     default:
321       SystemCoreClock = HSI_VALUE;
322       break;
323   }
324 
325   /* Compute HCLK clock frequency ----------------*/
326   /* Get HCLK prescaler */
327   tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
328   /* HCLK clock frequency */
329   SystemCoreClock >>= tmp;
330 }
331 
332 #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
333 /**
334   * @brief  Setup the external memory controller. Called in startup_stm32f1xx.s
335   *          before jump to __main
336   * @param  None
337   * @retval None
338   */
339 #ifdef DATA_IN_ExtSRAM
340 /**
341   * @brief  Setup the external memory controller.
342   *         Called in startup_stm32f1xx_xx.s/.c before jump to main.
343   *         This function configures the external SRAM mounted on STM3210E-EVAL
344   *         board (STM32 High density devices). This SRAM will be used as program
345   *         data memory (including heap and stack).
346   * @param  None
347   * @retval None
348   */
SystemInit_ExtMemCtl(void)349 void SystemInit_ExtMemCtl(void)
350 {
351   __IO uint32_t tmpreg;
352   /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is
353     required, then adjust the Register Addresses */
354 
355   /* Enable FSMC clock */
356   RCC->AHBENR = 0x00000114U;
357 
358   /* Delay after an RCC peripheral clock enabling */
359   tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN);
360 
361   /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */
362   RCC->APB2ENR = 0x000001E0U;
363 
364   /* Delay after an RCC peripheral clock enabling */
365   tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN);
366 
367   (void)(tmpreg);
368 
369 /* ---------------  SRAM Data lines, NOE and NWE configuration ---------------*/
370 /*----------------  SRAM Address lines configuration -------------------------*/
371 /*----------------  NOE and NWE configuration --------------------------------*/
372 /*----------------  NE3 configuration ----------------------------------------*/
373 /*----------------  NBL0, NBL1 configuration ---------------------------------*/
374 
375   GPIOD->CRL = 0x44BB44BBU;
376   GPIOD->CRH = 0xBBBBBBBBU;
377 
378   GPIOE->CRL = 0xB44444BBU;
379   GPIOE->CRH = 0xBBBBBBBBU;
380 
381   GPIOF->CRL = 0x44BBBBBBU;
382   GPIOF->CRH = 0xBBBB4444U;
383 
384   GPIOG->CRL = 0x44BBBBBBU;
385   GPIOG->CRH = 0x444B4B44U;
386 
387 /*----------------  FSMC Configuration ---------------------------------------*/
388 /*----------------  Enable FSMC Bank1_SRAM Bank ------------------------------*/
389 
390   FSMC_Bank1->BTCR[4U] = 0x00001091U;
391   FSMC_Bank1->BTCR[5U] = 0x00110212U;
392 }
393 #endif /* DATA_IN_ExtSRAM */
394 #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
395 
396 /**
397   * @}
398   */
399 
400 /**
401   * @}
402   */
403 
404 /**
405   * @}
406   */
407