The SystemInit() function appears in the first line of the main() function, which shows its importance. I have never paid attention to the SystemInit() function before, and I only know that it is a function for initializing the STM32 system. Today I decided to take a closer look and start learning STM32 again. This function is in system_stm32f10x.c, and this C file is mainly used for specific hardware configuration related work.
void SystemInit (void)
{
RCC->CR |= (uint32_t)0x00000001;
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif
RCC->CR &= (uint32_t)0xFEF6FFFF;
RCC->CR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
RCC->CR &= (uint32_t)0xEBFFFFFF;
RCC->CIR = 0x00FF0000;
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
RCC->CIR = 0x009F0000;
RCC->CFGR2 = 0x00000000;
#else
RCC->CIR = 0x009F0000;
#endif
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif
#endif
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
#endif
}
From the function description, this function is to initialize the internal FALSH, PLL and update the system clock. This function needs to be called after reset.
RCC->CR |= (uint32_t)0x00000001;
The first line of code operates the clock control register to enable the internal 8M high-speed clock. From this we can see that after the system starts up, it first relies on the internal clock source to work.
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
These two lines of code operate the clock configuration register. They mainly set MCO (microcontroller clock output), PLL related (PLL multiplication factor, PLL input clock source), ADCPRE (ADC clock), PPRE2 (high-speed APB division factor), PPRE1 (low-speed APB division factor), HPRE (AHB pre-division factor), SW (system clock switch). At the beginning, the system clock switches to HSI, which is used as the system initial clock. The macro STM32F10X_CL is a macro related to a specific STM32 chip.
RCC->CR &= (uint32_t)0xFEF6FFFF;
RCC->CR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR &= (uint32_t)0xFF80FFFF;
These sentences are to configure the related parameters after turning off HSE, CSS, PLL, etc. and then turn them on to achieve the purpose of taking effect.
#ifdef STM32F10X_CL
RCC->CR &= (uint32_t)0xEBFFFFFF;
RCC->CIR = 0x00FF0000;
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
RCC->CIR = 0x009F0000;
RCC->CFGR2 = 0x00000000;
#else
RCC->CIR = 0x009F0000;
#endif
This section is mainly about interrupt setup. At the beginning, we need to disable all interrupts and clear all interrupt flags. Different hardware has different settings.
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif
#endif
This paragraph is related to setting external RAM. The STM32F103RBT I used has nothing to do with this.
SetSysClock();
This is another function, which mainly configures the system clock frequency. The frequency division values of HCLK, PCLK2, and PCLK1 represent AHB, APB2, and APB1 respectively. Of course, it also does other things, such as configuring the FLASH delay period and enabling the pre-fetch buffer period. The details of the latter configuration are not yet understood.
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
#endif
This code mainly implements the relocation of the vector table. It depends on whether you want to locate the vector table in the internal SRAM or the internal FLASH. This SCB was not found in the STM32 reference manual at first. It turns out that it is related to the Cortex-M3 core. So ST did not include it. I will learn about the core later, but here is a reminder for myself.
Then take a look at what the function SetClock() in SystemInit() does.
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif definedSYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif definedSYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif definedSYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif definedSYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif definedSYSCLK_FREQ_72MHz
SetSysClockTo72();
#endif
}
It can be seen that different system clocks are set according to different macros, and these macros are in the same source file as this function. The official is very considerate, we only need to select the corresponding macro to achieve the purpose of quickly configuring the system clock.
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
#define SYSCLK_FREQ_24MHz 24000000
#else
#define SYSCLK_FREQ_72MHz 72000000
#endif
For example, if I need to configure the system clock to 72MHZ, I only need to remove the comment symbols on both sides of #define SYSCLK_FREQ_72MHz 72000000.
This function also contains the SetSysClockTo72() function, which is used to configure the registers.
#elif definedSYSCLK_FREQ_72MHz
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
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)
{
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
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);
RCC->CR |= RCC_CR_PLL2ON;
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
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
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
RCC->CR |= RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{
}
}
#endif
The above code needs to be looked at carefully. That's pretty much it for SystemInit().
Previous article:STM32 general timer---basic timing learning
Next article:How does the STM32 library read and write some pins of the same group of IO ports?
Recommended ReadingLatest update time:2024-11-16 08:28
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Document Resources | Upgrade again - i.MX6Q development board manual update
- Share: [G-Non-contact object size and shape measurement] G-Fuzhou University-Non-contact object shape measurement
- Research on FFT Implementation Using FPGA
- The virtual machine Ubuntu system runs C language code and Python code
- ADC_DAC Basics
- [Help] How should I set the pull-up or pull-down resistor for ZYNQ's MIO?
- Show off the development board of ON Semiconductor's Internet of Things Innovation Design Competition!
- How to use Labview to perform secondary development on Ginkgo 2
- Looking forward to the review of the Yatli series~
- Common problems and solutions in CCS compilation