—————————————————————————————————————————————————————————————————
system_stm32f10x.c 文件
——————————————————————————————————————————————————————————————————
system_stm32f10x.c文件主要有1个全局变量u32 SystemCoreClock(存放系统主频,以Hz为单位),2个外部函数void SystemInit(void)和void SystemCoreClockUpdate(void);
SystemInit()在启动文件复位服务函数中首先被调用完成系统时钟的初始化,然后跳转到库函数__main()完成堆栈、堆的初始化工作,然后调用main()函数,跳转到用户程序中。
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
现在分析SystemInit()函数:
void SystemInit (void)
{
/* 首先把RCC寄存器恢复为复位状态 ,省略此处代码,有兴趣的可以自己查看源代码*/
/* 然后调用SetSysClock()函数配置System clock frequency, HCLK, PCLK2 and PCLK1频率和FLASH有关的一些功能*/
SetSysClock();
}
接下来分析SetSysClock()函数
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
SetSysClockTo72();
#endif
}可以看出来,根据宏定义配置调用相应的函数,一般都习惯配置为主频72M,那么看看SetSysClockTo72()函数
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* 高速外部晶振HSE使能 */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);//RCC_CR_HSEON这些常数都定义在stm32f10x.h文件中
/* 等待HSE稳定,如果在HSEStartUp_TimeOut时间内还没有稳定,那么就退出此函数*/
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
/*HSE稳定启动后,HSEStatus置1,否则清零*/
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
/*如果HSE稳定启动,就配置一系列时钟,否则退出函数*/
if (HSEStatus == (uint32_t)0x01)
{
/* Flash预取指缓冲使能*/
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state ,在stm32参考手册中第2章嵌入式闪存一节中有规定*/
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/2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz,外部晶振使用的是8Hhz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |RCC_CFGR_PLLMULL));//先对PLLSRC PLLXTPRE PLLMULL位段清零
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//HSE不分频,9倍频后作为PLL锁相环的时钟输入
/* PLL使能 */
RCC->CR |= RCC_CR_PLLON;
/* 等待PLL稳定*/
while((RCC->CR & RCC_CR_PLLRDY) == 0){}
/* 选择PLL输出作为系统时钟源*/
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/*等待PLL被配置为系统时钟源*/
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}
}
else
{ /* 此次是HSE起振失败后,需要有相应的处理代码,需要用户根据自己的需要进行代码编写*/
}
}
到此,SystemInit()函数讲解完毕。
SystemCoreClockUpdate()函数其实就是对全局变量SystemCoreClock进行更新,使SystemCoreClock存储系统现在使用的系统时钟频率。
——————————————————————————————————————————————————————————————
system_stm32f10x.c文件讲解完毕,接下来是内核文件core_cm3.c与core_cm3.h进行讲解。
本文来自论坛,点击查看完整帖子内容。