Detailed explanation of STM32 clock initialization function SystemInit()

Publisher:Tianyun2021Latest update time:2016-09-28 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
After a day, I finally understood what functions the SystemInit() function implements. I am a beginner in STM32. I have recorded it as follows (please point out any misunderstandings):
The library used is 3.5, STM32F107VC, and the development environment is RVMDK4.23
I have defined STM32F10X_CL,SYSCLK_FREQ_72MHz
Function calling order:
startup_stm32f10x_cl.s (startup file) → SystemInit() → SetSysClock () → SetSysClockTo72()
RCC register reset value used to initialize the clock:
RCC_CR = 0x0000 xx83; RCC_CFGR = 0x0000 0000;RCC_CIR = 0x0000 0000; RCC_CFGR2 = 0x0000 0000;
SystemInit()
The value of the RCC register before calling SetSysClock() is as follows (all are AND and OR operations, which will not be repeated here):
RCC->CR = 0x0000 0083; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000; As for what these registers mean, please refer to the chip data RCC register for details. This article does not focus on this.
The SetSysClock() function is as follows:
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz //My definition is SYSCLK_FREQ_72MHz, so call SetSysClockTo72()
  SetSysClockTo72();
#endif
}
The SetSysClockTo72() function is as follows:
static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
 
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  
  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;
 
    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
     /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
      /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 
#else    
    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */
 
    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;
 
    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
 
    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }
}
 
 
1: AHB, APB1, APB2 clock confirmed
//HCLK = SYSCLK, from the following analysis we can conclude that SYSCLK uses the PLLCLK clock, which is 72MHZ (as for how 72MHZ is obtained, please see the following analysis)
   //Then HCLK (AHB bus clock) = PLLCLK = 72MHZ    
    //AHB bus clock is equal to system clock SYSCLK, that is, AHB clock = HCLK = SYSCLK = 72MHZ
   /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
 
   //PLCK2 is equal to HCLK divided by 1, so PCLK2 = HCLK, HCLK = 72MHZ, then PLCK2 (APB2 bus clock) = 72MHZ   
   //APB2 bus clock is equal to one-divided frequency of HCLK, that is, no frequency division; APB2 clock = HCLK = SYSCLK = 72MHZ 
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
 
    //PCLK1 = HCLK / 2; PCLK1 is equal to the HCLK clock divided by two, so PCLK1(APB1) = 72MHZ / 2 = 36MHZ    
    //APB1 bus clock is equal to HCLK divided by 2, that is, APB1 clock = HCLK / 2 = 36MHZ
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
 
2: How to determine SYSCLK (system clock) is 72MHZ (external crystal oscillator 25MHZ)
//Remember to refer to the clock tree P115 page and RCC clock register of the English chip data for understanding
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
 
RCC_CFGR2_PREDIV2_DIV5: PREDIV2 = 5; 5 division
          That is, PREDIV2 divides the input external clock by 5, so PLL2 and PLL3 are 25/5 = 5MHZ before multiplication.
RCC_CFGR2_PLL2MUL8 : PLL2MUL = 8; 8 times frequency  
          After 8 times, PLL2 clock = 5 * 8 = 40MHZ; therefore PLL2CLK = 40MHZ
RCC_CFGR2_PREDIV1SRC_PLL2: Bit 16 of RCC_CFGR2 is 1, which selects PLL2CLK as the clock source for PREDIV1
RCC_CFGR2_PREDIV1_DIV5: PREDIV1 = 5; PREDIV1 divides the input clock by 5 PREDIV1CLK = PLL2CLK / 5 = 8MHZ
 
Detailed explanation of STM32 clock initialization function SystemInit() - lucjn - My blogDetailed explanation of STM32 clock initialization function SystemInit() - lucjn - My blogThe above is the configuration of RCC_CFGR2
--------------------------------------------------------------------------------------
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
 RCC_CFGR_PLLMULL9); 
 
RCC_CFGR_PLLXTPRE_PREDIV1: operates the 17th bit PLLXTPRE of RCC_CFGR. Operating this bit has the same effect as operating the lowest bit in bit [3:0] of the RCC_CFGR2 register.  
RCC_CFGR_PLLSRC_PREDIV1: Select PREDIV1 output as PLL input clock; PREDIV1CLK = 8MHZ, so the clock source input to the PLL multiplier is 8MHZ
RCC_CFGR_PLLMULL9: PLLMUL = 9; PLL multiplication factor is 9, that is, PLLCLK = PREDIV1CLK * 8 = 72MHZ
 
The above is the configuration of RCC_CFGR
---------------------------------------------------------------------------------------------------
 
 RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //Select PLLCLK as the system clock source 
 
--------------------------------------------------------------------------------------------------
So far, the basic configuration has been completed, and the configured clock is as follows:
SYSCLK (system clock) = 72MHZ
AHB bus clock = 72MHZ
APB1 bus clock = 36MHZ
APB2 bus clock = 72MHZ
PLL clock = 72MHZ
PLL2 clock = 40MHZ

Keywords:STM32 Reference address:Detailed explanation of STM32 clock initialization function SystemInit()

Previous article:Notes on using Jlink to download programs for LPC2136
Next article:STM32 GPIO settings

Recommended ReadingLatest update time:2024-11-16 21:43

STM32 uses ordinary IO ports to measure the frequency of PWM
There are many ways for STM32 to measure the frequency of external input signals: Use the internal timer input capture function. Use ordinary IO port to set external interrupt + timer to measure the frequency of PWM signal.  Of these two methods, the first one is recommended, as it uses internal resources to save
[Microcontroller]
STM32 jtag debugger runs out of program
Development environment: keil MDK V5.10 Operating system: Windows 7 (32-bit) Target hardware: STM32F103C8 Problem description: When using jtag to debug a certain software, KEIL can download the software normally. Once F5 is used to run at full speed, it is immediately found that the program is running away. After pau
[Microcontroller]
STM32 system clock default settings
"We have always said that STM32 has a very complex clock system. However, in the Atom or Wildfire routines, as long as the clock is involved, we can only see similar library function calls, such as RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); This only plays the role of turning on the US
[Microcontroller]
Problems encountered during stm32 transplantation
1.Warning: L6305W: Image does not have an entry point. (Not specified or not set due to multiple choices.)    In the Linker---Misc controls of Options for Target, add the entry address: --entry Reset_Handler  2. Error: L6915E: Library reports error: __use_no_semihosting was requested, but __user_initial_stackheap
[Microcontroller]
Problems encountered during stm32 transplantation
STM32 firmware library description
Version: v2.0.3 l Release time: 09/22/2008 l Function: : Provides driver functions for all peripherals on the STM32 microcontroller chip, allowing users to spend more time on application development to speed up product time to market. (In essence, it defines the parameter configuration of various registers as macros
[Microcontroller]
STM32 firmware library description
Without crystal oscillator, the frequency multiplication of STM32 internal HSI clock is used
The blogger recently used the STM32F1 series microcontroller to make a touch screen USB mouse. He considered not using an external crystal oscillator but using the STM32 internal 8MHz HSI RC as the clock source. Since the USB protocol stipulates a 48MHz USB clock, the HIS must be processed by PLL multiplication to obt
[Microcontroller]
Without crystal oscillator, the frequency multiplication of STM32 internal HSI clock is used
STM32 study notes: simple Bootloader serial port upgrade design
Concept Introduction Before learning how to make a serial port upgrade Bootloader, let's first understand STM32's IAP (In Application Programming). IAP is the user's own program burning part of the User Flash area during operation. The purpose is to easily update the firmware program in the product through the reser
[Microcontroller]
STM32 study notes: simple Bootloader serial port upgrade design
STM32 Getting Started: GPIO
       I have been using STM32 for a while. I felt it was difficult to get started and I didn't know where to start. Now I have learned a little bit and I would like to share it with you.        First of all, what is GPIO? The answer to this question is that I don’t know either! At least I don’t need to know it for no
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号