1. 启动文件简介
启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:
- 初始化堆栈指针SP=_initial_sp;
- 初始化程序计数器指针PC=Reset_Handler;
- 设置堆、栈的大小;
- 初始化中断向量表;
- 配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM);
- 调用SystemIni() 函数配置STM32的系统时钟。
- 设置C库的分支入口“__main”(最终用来调用main函数);
2. 查找ARM汇编指令
在讲解启动代码的时候,会涉及到ARM的汇编指令和Cortex内核的指令,有关Cortex内核的指令我们可以参考《CM3权威指南CnR2》第四章:指令集。 剩下的ARM的汇编指令我们可以在MDK->Help->Uvision Help中搜索到,以EQU为例,检索如下:
检索出来的结果会有很多,我们只需要看Assembler User Guide 这部分即可。下面列出了启动文件中使用到的ARM汇编指令, 该列表的指令全部从ARM Development Tools这个帮助文档里面检索而来。其中编译器相关的指令WEAK和ALIGN为了方便也放在同一个表格了。
3. 启动文件代码讲解
3.1. Stack—栈
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
开辟栈的大小为0X00000400(1KB,单位为字节数,这里是十六进制表示,换算成二进制是2^10字节),名字为STACK,NOINIT即不初始化,可读可写,8(2^3)字节对齐。
栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM的大小。如果编写的程序比较大, 定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬fault的时候,这时你就要考虑下是不是栈不够大,溢出了。
EQU:宏定义的伪指令,相当于等于,类似与C中的#define。
AREA:告诉汇编器汇编一个新的代码段或者数据段。STACK表示段名,这个可以任意命名;NOINIT表示不初始化; READWRITE表示可读可写,ALIGN=3,表示按照2^3对齐,即8字节对齐。
SPACE:用于分配一定大小的内存空间,单位为字节。这里指定大小等于Stack_Size。
标号__initial_sp紧挨着SPACE语句放置,表示栈的结束地址,即栈顶地址,栈是由高向低生长的。
3.2.