![Lee_的头像 Lee_的头像](https://cdn.eetrend.com/files/styles/picture200/public/pictures/picture-147-1476977402.jpg?itok=DhnfPdhO)
来源:光豆儿(头条号)
main()是用户程序的入口,那么MCU在main()之前都做了什么呢,下面以stm32f10x芯片为例,描述下main()之前的事情。
简单说MCU在进入main()之前,一直再做进入main()的准备工作。那么这些准备工作都包括什么?
![MCU在main()之前都干了什么](http://mcu.eetrend.com/files/2017-02/wen_zhang_/100005113-16319-2.jpg)
一、初始化MSP与PC寄存器
![MCU在main()之前都干了什么](http://mcu.eetrend.com/files/2017-02/wen_zhang_/100005113-16320-3.jpg)
stm32离开复位状态之后自动从以下两个地址取值:
1. 从0x00000000地址读取MSP的初始值,即栈指针
2. 从0x00000004地址读取PC的初始值,即复位函数的指针
其实不只是stm32从这两个地址取值,所有的Cortex-M3内核在启动后都是先从这两个地址取值的。可能大家有个疑问,STM32的Flash地址是0x8000000,不是0x00000000啊,这是因为ST公司将Flash的起始地址映射到了0x00000000上。
二、初始化运行环境
当PC寄存器有值了之后,内核将根据PC的值跳转到复位函数执行下一步的操作。我们从ST提供的startup文件来看stm32的复位函数:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
复位函数先跳入SystemInit(),再跳入__main()。这两个函数一个是对基本的硬件环境进行初始化,一个是对基本的软件环境进行初始化。
● 2.1 设置基本硬件环境
SystemInit()的作用是对系统的时钟源进行初始化,配置各总线时钟,以及优化Flash的读取。也就是说当SystemInit()返回时,stm32就有了最基本的运行能力。
● 2.2 配置基本软件环境
之后进入__main()。注意__main()不同于main()函数。__main()是编译器生成的,它是执行C代码程序的入口,包括初始化C代码运行环境,也就是说从现在开始就要配置最基本的软件运行环境了。而main()是我们的用户程序的入口。那么软件环境是如何配置的,都需要配置什么?
首先将我们定义的全局变量和静态变量加载到RAM中,并对ZI变量赋0值(ZI是Zero Init的缩写,就是我们定义的初值为0或者系统默认赋值为0的变量)。
然后调用__rt_entry()对C语言运行环境做初始化,C语言运行环境的初始化包括:
1. 建立堆栈
2. 调用__rt_lib_init()初始化C库函数,若main()有参数则建立参数
3. 调用main()
三、总结
至此我们就进入了用户程序的入口main(),开始执行我们编写的代码。而上面的初始化过程则都是芯片公司和编译器提供的。只有通过上面的初始化过程,对MCU进行软硬件进行配置,用户程序才能调用相关的C语言程序代码,并执行相应的程序。