What's in the first function SystemInit(), clock settings and a brief introduction

The SystemInit() function appears in the first line of the main() function, which shows its importance. The function SystemInit() has never been concerned before, only that it is a function for initialization of STM32 system. Today I decided to take a closer look and start STM32 again. This function is in system_stm32f10x.c. This C file is mainly for the specific hardware configuration related work.


  1. /** @addtogroup STM32F10x_System_Private_Functions 
  2.   * @{ 
  3.   */  
  4.   
  5. /** 
  6.   * @brief  Setup the microcontroller system 
  7.   *         Initialize the Embedded Flash Interface, the PLL and update the  
  8.   *         SystemCoreClock variable. 
  9.   * @note   This function should be used only after reset. 
  10.   * @param  None 
  11.   * @retval None 
  12.   */  
  13. void SystemInit (void)  
  14. {  
  15.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */  
  16.   /* Set HSION bit */  
  17.   RCC->CR |= (uint32_t)0x00000001;  
  18.   
  19.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */  
  20. #ifndef STM32F10X_CL  
  21.   RCC->CFGR &= (uint32_t)0xF8FF0000;  
  22. #else  
  23.   RCC->CFGR &= (uint32_t)0xF0FF0000;  
  24. #endif /* STM32F10X_CL */     
  25.     
  26.   /* Reset HSEON, CSSON and PLLON bits */  
  27.   RCC->CR &= (uint32_t)0xFEF6FFFF;  
  28.   
  29.   /* Reset HSEBYP bit */  
  30.   RCC->CR &= (uint32_t)0xFFFBFFFF;  
  31.   
  32.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */  
  33.   RCC->CFGR &= (uint32_t)0xFF80FFFF;  
  34.   
  35. #ifdef STM32F10X_CL  
  36.   /* Reset PLL2ON and PLL3ON bits */  
  37.   RCC->CR &= (uint32_t)0xEBFFFFFF;  
  38.   
  39.   /* Disable all interrupts and clear pending bits  */  
  40.   RCC->CIR = 0x00FF0000;  
  41.   
  42.   /* Reset CFGR2 register */  
  43.   RCC->CFGR2 = 0x00000000;  
  44. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)  
  45.   /* Disable all interrupts and clear pending bits  */  
  46.   RCC->CIR = 0x009F0000;  
  47.   
  48.   /* Reset CFGR2 register */  
  49.   RCC->CFGR2 = 0x00000000;        
  50. #else  
  51.   /* Disable all interrupts and clear pending bits  */  
  52.   RCC->CIR = 0x009F0000;  
  53. #endif /* STM32F10X_CL */  
  54.       
  55. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)  
  56.   #ifdef DATA_IN_ExtSRAM  
  57.     SystemInit_ExtMemCtl();   
  58.   #endif /* DATA_IN_ExtSRAM */  
  59. #endif   
  60.   
  61.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */  
  62.   /* Configure the Flash Latency cycles and enable prefetch buffer */  
  63.   SetSysClock();  
  64.   
  65. #ifdef VECT_TAB_SRAM  
  66.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */  
  67. #else  
  68.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */  
  69. #endif   
  70. }  

From the function description, the function is to initialize the internal FALSH, PLL and update the system clock. This function needs to be called after reset starts.

  1. RCC->CR |= (uint32_t)0x00000001;  

The first line of code operates the clock control register, enabling the internal 8M high-speed clock. It can be seen from this that the system works first by relying on the internal clock source after starting.

  1. #ifndef STM32F10X_CL  
  2.   RCC->CFGR &= (uint32_t)0xF8FF0000;  
  3. #else  
  4.   RCC->CFGR &= (uint32_t)0xF0FF0000;  

These two lines of code are the operating clock configuration registers. MCO (MCO clock output) PLL correlation (PLL frequency doubling coefficient, PLL input clock source), ADCPRE (ADC clock), PPRE2 (high-speed APB frequency dividing coefficient), PPRE1 (low-speed APB frequency dividing coefficient), HPRE(AHB pre-dividing coefficient), SW (system clock switching), at the beginning, the system clock is switched to HSI, which serves as the system initial clock. The macro STM32F10X_CL is a macro related to the specific STM32 chip.

  1. /* Reset HSEON, CSSON and PLLON bits */  
  2. RCC->CR &= (uint32_t)0xFEF6FFFF;  
  3.   
  4. /* Reset HSEBYP bit */  
  5. RCC->CR &= (uint32_t)0xFFFBFFFF;  
  6.   
  7. /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */  
  8. RCC->CFGR &= (uint32_t)0xFF80FFFF;  

These sentences are to configure the parameters related to HSE, CSS, PLL and so on, and then open them to achieve the purpose of taking effect.

  1. #ifdef STM32F10X_CL  
  2.   /* Reset PLL2ON and PLL3ON bits */  
  3.   RCC->CR &= (uint32_t)0xEBFFFFFF;  
  4.   
  5.   /* Disable all interrupts and clear pending bits  */  
  6.   RCC->CIR = 0x00FF0000;  
  7.   
  8.   /* Reset CFGR2 register */  
  9.   RCC->CFGR2 = 0x00000000;  
  10. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)  
  11.   /* Disable all interrupts and clear pending bits  */  
  12.   RCC->CIR = 0x009F0000;  
  13.   
  14.   /* Reset CFGR2 register */  
  15.   RCC->CFGR2 = 0x00000000;        
  16. #else  
  17.   /* Disable all interrupts and clear pending bits  */  
  18.   RCC->CIR = 0x009F0000;  
  19. #endif /* STM32F10X_CL */  

This section is mainly related to interrupt settings. In the beginning, we need to prohibit all interrupts and clear all interrupt flags. Different hardware has different features.

  1. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)  
  2.   #ifdef DATA_IN_ExtSRAM  
  3.     SystemInit_ExtMemCtl();   
  4.   #endif /* DATA_IN_ExtSRAM */  
  5. #endif  

This section has something to do with setting up external RAM. The STM32F103RBT I used has nothing to do with it.

  1. SetSysClock();  

This is another function, mainly to configure the system clock frequency. The fractional frequencies of HCLK, PCLK2 and PCLK1 represent AHB,APB2 and ABB1 respectively. Other things, of course, are configuring FLASH latency cycles and enabling prefetch buffers. The latter configuration is not yet known.

  1. #ifdef VECT_TAB_SRAM  
  2.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */  
  3. #else  
  4.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */  
  5. #endif   

This code mainly realizes the relocation of the vector table. Depending on whether you want to locate the vector table in internal SRAM or internal FLASH. This SCB has not been found in the STM32 reference manual since it was originally related to the Cortex-M3 kernel. So ST didn't include it. Kernel things to understand later, here to remind yourself.


Then look at what the function SetClock() in SystemInit() does.

  1. static void SetSysClock(void)  
  2. {  
  3. #ifdef SYSCLK_FREQ_HSE  
  4.   SetSysClockToHSE();  
  5. #elif defined SYSCLK_FREQ_24MHz  
  6.   SetSysClockTo24();  
  7. #elif defined SYSCLK_FREQ_36MHz  
  8.   SetSysClockTo36();  
  9. #elif defined SYSCLK_FREQ_48MHz  
  10.   SetSysClockTo48();  
  11. #elif defined SYSCLK_FREQ_56MHz  
  12.   SetSysClockTo56();    
  13. #elif defined SYSCLK_FREQ_72MHz  
  14.   SetSysClockTo72();  
  15. #endif  
  16.    
  17.  /* If none of the define above is enabled, the HSI is used as System clock 
  18.     source (default after reset) */   
  19. }  


It can be seen that different system clocks are set according to different macros, which are in the same source file as this function. Officials are very considerate. We can quickly configure the system clock by selecting the appropriate macro.
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)  
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */  
  3.  #define SYSCLK_FREQ_24MHz  24000000  
  4. #else  
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */  
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */   
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */  
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */  
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */  
  10. #define SYSCLK_FREQ_72MHz  72000000  
  11. #endif  


For example, if I need to configure the system clock to 72MHZ, I just need to remove the annotations on both sides of # define SYSCLK_FREQ_72MHz 72000000.

This function also has the SetSysClockTo72() function, which is the specific operation register configuration.

  1. #elif defined SYSCLK_FREQ_72MHz  
  2. /** 
  3.   * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2  
  4.   *         and PCLK1 prescalers.  
  5.   * @note   This function should be used only after reset. 
  6.   * @param  None 
  7.   * @retval None 
  8.   */  
  9. static void SetSysClockTo72(void)  
  10. {  
  11.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;  
  12.     
  13.   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/      
  14.   /* Enable HSE */      
  15.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);  
  16.    
  17.   /* Wait till HSE is ready and if Time out is reached exit */  
  18.   do  
  19.   {  
  20.     HSEStatus = RCC->CR & RCC_CR_HSERDY;  
  21.     StartUpCounter++;    
  22.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));  
  23.   
  24.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)  
  25.   {  
  26.     HSEStatus = (uint32_t)0x01;  
  27.   }  
  28.   else  
  29.   {  
  30.     HSEStatus = (uint32_t)0x00;  
  31.   }    
  32.   
  33.   if (HSEStatus == (uint32_t)0x01)  
  34.   {  
  35.     /* Enable Prefetch Buffer */  
  36.     FLASH->ACR |= FLASH_ACR_PRFTBE;  
  37.   
  38.     /* Flash 2 wait state */  
  39.     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);  
  40.     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;      
  41.   
  42.    
  43.     /* HCLK = SYSCLK */  
  44.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;  
  45.         
  46.     /* PCLK2 = HCLK */  
  47.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;  
  48.       
  49.     /* PCLK1 = HCLK */  
  50.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;  
  51.   
  52. #ifdef STM32F10X_CL  
  53.     /* Configure PLLs ------------------------------------------------------*/  
  54.     /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */  
  55.     /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */  
  56.           
  57.     RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |  
  58.                               RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);  
  59.     RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |  
  60.                              RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);  
  61.     
  62.     /* Enable PLL2 */  
  63.     RCC->CR |= RCC_CR_PLL2ON;  
  64.     /* Wait till PLL2 is ready */  
  65.     while((RCC->CR & RCC_CR_PLL2RDY) == 0)  
  66.     {  
  67.     }  
  68.       
  69.      
  70.     /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */   
  71.     RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);  
  72.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |   
  73.                             RCC_CFGR_PLLMULL9);   
  74. #else      
  75.     /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */  
  76.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |  
  77.                                         RCC_CFGR_PLLMULL));  
  78.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);  
  79. #endif /* STM32F10X_CL */  
  80.   
  81.     /* Enable PLL */  
  82.     RCC->CR |= RCC_CR_PLLON;  
  83.   
  84.     /* Wait till PLL is ready */  
  85.     while((RCC->CR & RCC_CR_PLLRDY) == 0)  
  86.     {  
  87.     }  
  88.       
  89.     /* Select PLL as system clock source */  
  90.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));  
  91.     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;      
  92.   
  93.     /* Wait till PLL is used as system clock source */  
  94.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)  
  95.     {  
  96.     }  
  97.   }  
  98.   else  
  99.   { /* If HSE fails to start-up, the application will have wrong clock  
  100.          configuration. User can add here some code to deal with this error */  
  101.   }  
  102. }  
  103. #endif  

The above code needs to be looked at carefully. SystemInit() is about that.

Posted by GooberDLX on Wed, 22 May 2019 13:43:30 -0700