编译器编译后,生成的是一个xx.bin文件,如下图:

 关于arm处理器stm32启动过程启动文件详解(本质刨析)_gnu

 左边的是编译器生成的目标文件,存放在外存中,其中Text_start等标识符,编译器会自动给出,汇编里面直接引用是可以的。

启动的过程:(启动文件要做的,也是CPU上电后就运行的程序)


  1. CPU把Data段和Bss段分别搬运到内存RAM中即可,Text段不用搬,因为是代码段,只需要读取即可。
  2. 跳转到外部出口函数,一般就是main函数了,就进入了用户世界了。

我们打开stm32官方的启动文件,发现如下:(是跳到了__main函数,并没有搬运Data段和Bss段啊,也没有跳转到我们用户的main函数啊,这是怎么回事呢?)

 关于arm处理器stm32启动过程启动文件详解(本质刨析)_stm32_02

这是因为,__main函数是libc库文件标准定义了,里面就是搬运Data段和Bss段到指定的RAM区域中。里面会再次跳到我们的main函数的,就进入了用户的世界。如下所示:

关于arm处理器stm32启动过程启动文件详解(本质刨析)_main函数_03

当然我们也可以不用libc库中的__main函数,我们自己写一个搬运Data段和Bss段的代码,然后跳到我们指定的main函数去。示意代码如下,自己对着理解理解就可以了,不难。

.cpu cortex-m3
.fpu softvfp
.syntax unified
.thumb

.text
.global RESET_HANDLER
.global __ENTRY
.extern myMain
.type RESET_HANDLER,function
.type FAULT_HANDLER,function
.word Msp_stack
.word RESET_HANDLER
.word FAULT_HANDLER
.word FAULT_HANDLER
__ENTRY:
RESET_HANDLER:
ldr r0,=Psp_stack
msr psp,r0 @初始化线程栈指针,主栈指针是自动初始化的
CPSID I @PRIMASK=1,关中断
@CPSID F @FAULTMASK=1,关异常
mov r0,#0
msr control,r0 @初始化代码在特权级,栈指针选择msp

movs r1, #0
bl LoopCopyDataInit

CopyDataInit:
ldr r3, =text_end
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4

LoopCopyDataInit:
ldr r0, =data_start
ldr r3, =data_end
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =bss_start
ldr r3, =bss_end
b LoopFillZerobss

FillZerobss:
movs r1, #0
str r1, [r2], #4

LoopFillZerobss:
cmp r2, r3
bcc FillZerobss

mov r0,r0
bl myMain
b .

FAULT_HANDLER:
bx lr