在arm核中,以CortexM3为例,它在机制层面提供给用户一个向量表(Vector)的概念。向量表的定义可以在官方的keil启动文件中找到,启动文件是.s汇编语言。一般是命名为startup_stm32xxx.s。向量表可以通过标号__Vector来辨识。
在__Vector标号的下面几段语句中,DCD分配了其他标号辨识。
第一个__initial_sp是堆栈指针的起始地址(MSP),它指向分配给程序的栈区的栈底,此外,arm采用向上增长或向下增长的满栈。详情请看arm具体的堆栈分析。
第二个Reset_Handler是复位中断的句柄或者说处理函数。也是我们今天要关注的重头戏。它实际上也是一个指针,指向的是复位处理函数。当外部触发复位中断或者是初始化时,可以通过该函数来进行引导或初始化。
其他的往下罗列的标号我们今天暂不分析,对于简单的BootLoader只需要讨论上述两个内容。
我们再来看Reset_Handler,这个复位标号在功能上做了什么工作,首先PROC 和ENDP是一对编码区域限制指令。随后EXPORT声明了这个复位服务中断函数,并且熟悉为弱{WEAK}(有点类似于重载的机制)。同时IMPORT __main和SystemInit。再往后跳转SystemInit处理,然后再跳到__main来进行处理。
同时我们可以创建一个简单的代码,并通过keil编译生成.bin二进制文件。通过SublimeText软件我们可以观察到它的最前面的一部分内容。
由于是32位的核,那么每个标号占用的字节数是32/8=4个字节,那么0x58100020便是他的栈指针地址,0x3d010008是其复位中断处理函数。
因此每次会从0x3d010008这个位置来执行System_Init然后再跳到__main。因此,BootLoader在最后的跳转语句时。需要找到烧录固件的位置(即向量表的起始地址)+4,这样就能找到复位处理函数,从而根据这个函数来预处理和初始化。从而为App部分的代码执行来创建环境。