理解这篇文章之前,我们需要配合了解两个基础知识。
一个是加载视图和运行试图,一个是单片机的存储空间。
这篇文章会涉及两个新内容,而加载视图又涉及启动代码和Scatter文件。
所以通过集成环境讲解启动代码总显得力不从心。
这里我们从编译器和链接器开始讲起。
1、C语言的编译都是按照文件进行编译的,编译完成后,每一个.c文件会生成相应的.o文件,这个过程是编译器(ARMCC)做的。
2、因为各个.o的信息是分散的,函数变量都是们没有统一编址的,所以lds链接器需要将各个.o文件的信息汇总到一起,就是code+RO+RW的位置,这就形成了加载视图。
3、启动代码starts.s 做一些基础工作外,根据Scatter文件的信息 ,对RW进行搬移,搬移到RAM中,方便后期的访问。
4、搬移完成后,我们就可以访问全局变量了(这个时候全局变量都是在RAM里的,我们通过map文件看到的)
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
Cortex-M0 以及M3 内核的 0地址保留,0x00000004地址用于存放复位向量。上电后,程序跳转到0x00000004地址运行,此地址存储的就是复位中断。
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
复位中断,先运行 系统初始化(SystemInit),然后跳转到__main过程。