对于小编来说,我以前对STM32F103的学习是通过正点原子的资料及视频学习,我也看过野火的资料,发现他们的视频都集中在C语言的基础上,不会跟你说启动文件是干什么的,直接就让你拿来用。现在我们要进入ARM世界了,就一定要开始了解汇编语言,了解启动文件里都做了些什么,它的作用是什么。
我们来一段一段解析startup文件。
1. 栈空间设置
;堆栈大小设置,如果局部变量过多,这里应该相应改大.默认是1024字节.
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
这里 Stack_Size EQU 0x00000400
什么意思呢,EQU在会汇编里相当于c语言的const关键词,用于定义一个常量。这里有一个需要知道的知识点,在ARM世界里栈是向下生长的。在这里也介绍一下堆和栈的区别,栈:一般用于存放函数的临时变量,即局部变量。在C语言中函数返回时你return的参数,实际上就是将函数内的局部变量压入栈中,等跳出函数时再将数据出栈的过程。栈最重要的作用还是在于线程切换时用来保护现场。堆:一般由程序员自行分配和释放,分配类似数据结构中的链表。在单片机里,没有内存管理堆存在将没有意义。所以对于我们之前学习的STM32F103的知识而言,在没用操作系统,纯裸机开发是只需要用到栈的。那可能就有疑问了,那我们的全局变量现在在哪?我们的全局变量其实存在于芯片内部的静态存储区里。
下一句 AREA STACK, NOINIT, READWRITE, ALIGN=3
,伪指令AREA,表示开辟一段内存空间,段名是STACK。NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0。READWRITE表示可读可写, ALIGN=3——2 的3次方表示以8字节对齐。SPACE用于申请一片内存空间,所以Stack_Mem SPACE Stack_Size
的意思就是申请Stack_Size(1024字节)大小的内存空间,这个内存空间叫做Stack_Mem。
__initial_sp只是一个标号,相当于一个指向当前位置的一个指针,前面从内存地址当前位置0x20000000开始开辟了一个1024字节的栈,所以这里__initial_sp指向0x20000400。注意一下,我上面推出的这个地址是基于你c语言代码主函数里什么也没写且堆为空的时候的情况,毕竟不要忘了,栈前面还有静态存储区和堆区。
这个如果你对C语言有一定了解,肯定也了解过C语言goto的用法,它也要用到标号。
2. 堆空间设置
;未用到编译器自带的内存管理(malloc,free等),设置Heap_Szie为0
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
根据上面对栈的解释,相信你已经能够看懂这段代码了。
这里设置了堆的空间大小为0,也就是实际上必不会给堆分配空间,到这里我们就可以判定现在内存中会存在一个静态存储区(如果C语言中存在变量的话)和一个1024字节的栈。在不使用堆的情况下,要注意了,你的栈的大小一定要比你定义的变量要大,不然你在使用大数组的时候就会直接从栈里溢出到静态存储区,整个程序直接跑飞。在ARM里规定堆默认是向上生长的,所以__heap_base是堆的起始位置,__heap_limit是堆的结束位置。
PRESERVE8
THUMB
PRESERVE8: 指定当前文件的堆栈按照 8 字节对齐。
THUMB: 表示后面指令兼容 THUMB 指令。 THUBM 是 ARM 以前的指令集, 16bit,现在 Cortex-M 系列的都使用 THUMB-2 指令集, THUMB-2 是 32 位的,兼容 16 位和 32 位的指令,是 THUMB 的超集。
3. 中断向量表
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
首先定义了一个数据段RESET,只读。因为我们的中断向量表定好了以后肯定不希望有人可以修改它的。这里我们有接触到了一个伪指令EXPORT,它用来声明__Vectors、 __Vectors_End 和__Vectors_Size 这三个标号具有全局属性。使用EXPORT可以让该变量被其他文件引用,意味着这三个标号可以被c语言代码引用。类似c语言里的extern关键词。
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler