环境:STM32F207
内容:SystemInit到底做了啥
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit ;现在着重讲这个地方
BLX R0
LDR R0, =__main
BX R0
ENDP
事先说明:我对整个流程并不是很清楚,所以我只会站在一个初学者的角度来写这篇文章,老手们就请见谅
言归正传:
贴上函数说明,来自stm32固件库:
/**
* @brief Setup the microcontroller system
* Initialize the Embedded Flash Interface, the PLL and update the
* SystemFrequency variable.
* @param None
* @retval None
*/
这段话的意思大概为:初始化FLASH接口,锁相环和更新系统时钟
源代码如下:
void SystemInit(void)
{
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
①:
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
这里是什么意思?不懂我们就看看stm32f207上面是怎么说CR寄存器的:
这句代码对应的寄存器如上,他其实要做的事情就是一个,打开HSI(内部高速晶振).我们再大致看看HISION说明:大概意思就是我们不能够将这一位清零,为啥?
他说,当我们离开待机模式的时候硬件强制将HISION置1,或者当我们外部晶振起振失败,我们也会直接或者间接使用到HSI。所以意思就是,我们只能开,不能关。
其实我们也可以反问自己一句,我们复位的时候还没有启动外部晶振同时也没有手动将HISON打开,为什么我们CPU能够跑,他是用的HSI 还是LSI?这个问题,我也不知道,
只能下来看看。能够想到这点就可以了。
②
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
这里来了个新的寄存器CFGR,他说将CFGR复位,为啥复位成0,不是FFF,不是DDDD,那也要看看datasheet里面每一项怎么写的,再看手册之前,先说一下
CFGR的作用就是如下图:
是的,CFGR的作用就是配置SYSCLK的,其实我们现在不看手册自己也会有几个疑问,如果系统启动,我们系统时钟是多少?时钟源是什么?所以这里就会有答案
我们上一张图片说的大概意思就是CFGR作用是选择系统时钟源什么的,现在这张图片就是写了CFGR有哪些位,我们肉眼看看也能够知道SW代表switch,pre代表预分频,所以我们知道
这里肯定是做的是系统时钟相关的时钟源选择切换和预分频处理相关动作,那么我们要好好看看一下sw0,sw1...,看了之后就知道为什么上电复位成为0了。
sw=0,表示系统时钟使用的是HSI。sws=0,也是同样意思,其实sws不能够设置,只能够查看。
下面我将列出其他位代表的意思:
HPRE:0000 代表不对系统时钟进行分频,时钟树里面中间框框AHB PRESC
PPREX(1,2):0000 代表APB2,APB1时钟来源都直接是AHB,并没有经过AHB分频,上面时钟树
RTCPRE:0000 不将HSE时钟提供给RTC,因为现在时钟本来就不精确,所以上电就给RTC,没有这个必要
I2SSC: 0000 选择PLLI2S时钟为I2S的时钟
好了,这句话,我们就引出了这么多内容,先说明:我在写文章的时候是边写边查,所以希望初学者按照我的思路来走,不要觉得文章太长没意思,有意思的文章不多,
也不是我能够一时半会儿写得出来的,所以请将就一下,至少对你会有很大帮助。
③
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
又来操作CR了,上面我们的CFGR主要做的是时钟源的设置,这个CR主要做的事情就是打开某些东西,比如PLLCSS,HSE等,至于为什么要先设置CFGR再设置CR,
很明显了,我们刚才设置CFGR目的是让系统先跑起来,使用HSI为系统时钟,跑起来之后再进行HSE,PLL等设置,这也合情合理。
我们知道&=的作用主要是清零,|=的作用主要是置一,那么我们看看这里CR想要将哪几位清零呢,为什么清零
0XFEF6FFFF=
主要是讲bit15之上的某些位给置零了。
其实这些值的大概意思就是上面备注写的:reset HSEON CSSON PLLON具体这些做什么用,除了CSSON以外,我觉得新手都应该看得懂。
CSSON,大概就是启用安全时钟系统,我理解为当HSE运行稳定了,打开这个,它相当于是去检测HSE是否正常工作。老手看到请指证
④
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
上面有个CFGR事用来配置系统时钟的,主要是系统时钟预分频器还有就是各种switch,那么PLLCFGR是什么意思就很好理解了,当然是
对锁相环进行操作的寄存器。具体每个值是多少,以及这个寄存器的作用是什么,我们后面来看,因为在sysclock函数里面要对每个值进行设置。所以这里只需要知道,这里是进行了PLLCFG的复位操作
⑤
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
这里说说HSE bypass是什么意思,bypass的意思就是直通,hse bypass就是说,信号源不是来自晶振了,而是另外的时钟源,比如信号发生器等。这里意思肯定是禁止bypass,如果我们打开,那么我们晶振就可以
不用初始化了。
⑥
/* Disable all interrupts */
RCC->CIR = 0x00000000;
这里说的是关闭中断,其实这个要分开理解,我们一般理解的终端是在终端向量表里面列出来的终端,比如定时器,外部中断,但是这里的中断是什么呢,主要是一些和时钟相关的中断。这里注意一下就可以了,
后面我们会看到另外一个关中断操作。
⑦
SetSysClock();
这个函数主要就是重新操作我们上面列出的一些寄存器,具体操作我们暂时和systemInit函数分开,我们下一节来讲这个SetSysClock.
⑧
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
设置中断向量表,这个地方我们会参考另外一个PDF文档<Cortex M3权威指南.pdf>
OK,做一个总结,其实SystemInit()这个函数只有这么几句话,但是用了很大篇幅来写,为什么,为的就是了解STM32相关的寄存器,不是说我们以后每次
使用STM32都必须亲自设置,而是我们要对此有个比较清晰的了解,技术,就要死磕到底。