32单片机(以HC32F460为例,简称460)的软件程序主要在main函数中进行编辑,但是在上电后且还未进入main函数前,芯片还有一系列的操作,理解这段过程有助于功能开发和问题排查。
- 通过boot引脚选择启动模式
460的boot引脚为PB11,引脚接高电平为从 Flash 启动,低电平为从 BOOT 启动。
一般设计好的460电路板都会将boot引脚拉高,从而在flash中加载程序。460在flash中读取程序的起始地址为0(逻辑地址直接对应物理地址),而STM32的起始地址一般在0x08000000(逻辑地址0对应0x08000000)。
以下(2)-(4)步其实就是startup_hc32f460.s中做的事。

- 程序先定义好栈区和堆区的默认大小。
- 从地址0x00000000读取 __initial_sp 初始栈顶值到MSP(Main Stack Pointer)
因为程序烧入flash之后,是通过二进制数存放的,而存放在最开始地址上的就是初始栈顶指针,所以程序会读取这个指针,赋给MSP。 - 从地址0x00000004读取 Reset_Handler 地址到PC
紧接在后面的是中断向量表,排在第一个的是复位中断处理函数Reset_Handler,PC指针会指向这里,运行这个中断处理函数,默认的Reset_Handler函数会导入SystemInit 和__main两个函数。
以下步骤可以参考下图。

- 运行SystemInit 函数
函数功能主要是一些寄存器配置的工作,例如配置初始化FPU,外部SRAM,中断向量表(根据用户设置的地址)等。 - 运行__main函数
__main是 ARM 编译器内置的库函数,而非用户编写的代码,因此在工程源码中看不到。功能为:初始化RW段、ZI段,即全局变量和静态变量;对堆栈区等区域的初始化;调用用户主函数main - 运行main函数