STM32之启动文件的详解

本文以STM32F407为例,介绍STM32的启动文件。如有解释不正确的地方,还请大家留言评论。
由于启动文件中涉及到一些汇编的知识,所以在讲解的过程中会补充一些汇编的知识。
一般而言,系统上电后第一个执行的是由汇编所编写的启动文件,其主要工作为以下三部分
(1)初始化堆栈指针SP
(2)初始化中断向量表
(3)初始化PC指针,令其=Reset_Handler配置系统时钟
调用C库函数_main初始化用户堆栈,从而最终调用main函数进入C的世界

一.初始化堆栈指针

是多少阿大撒的在这里插入图片描述
上图就是初始化堆栈指针的代码,最上面的那段英文的大体意思就是说你可以根据你应用的需要来配置相应大小的堆栈空间。
(1)初始化栈指针(SP)
在这里插入图片描述
这段代码的意思就是将栈大小设为0x0000 0400(1KB),栈名为STACK,不初始化,可读可写,8(2^3)字节对齐。最后的__initial_sp表示栈的结束地址,即栈顶地址,因为栈是由高地址向低地址生长。栈的主要作用是用于局部变量、函数调用以及函数形参等的开销,其大小应小于内部RAM的大小,以及考虑到局部变量的需求,防止栈溢出。所以你要根据你的应用来设置栈的大小,一般情况下1kb够你用的了。
(2)初始化堆(Heap)
在这里插入图片描述
这段代码和上一段没有什么区别 ,因为我们在应用中不使用malloc相关的函数,没有用到堆区,所以将堆的大小设为0x0000 0000(0B),栈名为HEAP,不初始化,可读可写,8(2^3)字节对齐。而__heap_base为堆的起始地址,__heap_limit为堆的结束地址,因为堆的由低地址向高地址生长。 堆的作用是用于malloc()之类的函数申请的动态内存的分配。

二.初始化中断向量表

在这里插入图片描述
由于图标太长,所以只粘贴了一部分,不影响讲解。
请大家先看到红色箭头所指向的地方,这段话的意思就是系统上电复位之后,中断向量表的首地址为0x0000 0000。DCD的意思就是开辟一个4字节对齐的空间,每一个四字节对齐的空间里存储着中断函数的入口地址,图片中开辟空间的顺序是严格按照每一个中断源在内存中所对应的中断地址,顺序不可以弄反,否则就会出现错误,如果你想更深入的了解,可以去看Cortex-M4内核相关的书籍
在这里插入图片描述
并且将它设置为仅读,且存储在代码区。

三.初始化PC指针,令其=Reset_Handler

在这里插入图片描述
这里先说明一下,如果你的项目是寄存器版本的话,就应该和上图一样,如果是库函数版本,就将上图中白色前面的冒号去掉。
使能浮点运算的代码不需要管,看下面的代码。LDR R0,SystemInit 的意思就是将SystemInit函数的地址加载到R0寄存器组,BLX R0 就是跳到SystemInit函数地址处去执行SystemInit函数,(执行SystemInit函数就是配置好系统时钟)并返回到原处。然后在将c库函数__main的入口地址加载到R0中,再跳到__main函数的地址处执行_main函数(执行_main函数初始化栈、堆,配置系统环境,在函数的最后调用用户编写的main函数,进入C的世界。),但是并不返回。这里再说明一下BLX和BX这两个指令的意思是不一样的。
在这里插入图片描述在这里插入图片描述
这里再补充一下,就是说编译生成的HEX文件是烧写到0x0800 0000 处的内存块里面的,然而cpu上电复位后是从0x0800 0000处开始执行代码的,我们进入调试界面的时候我们就会发现上图中蓝色图标指向的那行代码,所以我们就认为cpu上电复位后执行的第一条指令就是这条语句,它的地址就是0x0800 0000。然而并不是这样,cpu上电复位后第一个执行的语句就是跳到中断向量表中的Reset_Handler处,然后跳转到Reset_Handler函数的实体,然后再执行箭头所指向的那个语句(该语句就在Reset_Handler函数的实体中)。所以我们就会发现这个语句的地址并不是0x0800 0000 而是
0x0800 0228.
在这里插入图片描述
现在,大部分的内容都已经讲的差不多了,接下来补充一下其他的内容。
在这里插入图片描述
相信大家都知道这是定义了一些函数,但是函数的右边有一个【weak】这是一个弱定义,也就是说如果除本文件外,其它的文件中也定义了同样函数,链接的时候链接那个文件中的函数,因此,cpu在响应中断的时候执行的是那个文件中的函数实体,但是为什么要这样做呢,就是因为如果你在别的文件中定义的函数名写错了,不是本文第四张图中定义的函数名,那么在链接的时候,就会将该文件中的函数链接进去,当cpu在响应中断的时候就会执行这个文件中的函数,B . 的意思你可以理解为死循环,所以如果你粗心函数名写错了,那这个问题就很难发现了,所以我们在定义一个中断函数的时候千万不要写错,不然程序就卡死了。

           然后最后就是关于堆栈的初始化。

在这里插入图片描述
如上述代码所述,根据宏__MICROLIB是否定义来决定用户堆栈初始化的方法。其他的这里就不多说了,就补充一下IMPORT和EXPORT的作用吧。
IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的
EXPORT ,表示本程序里面用到的变量提供给其他模块调用的。

扫码关注公众号,领取免费学习资料
在这里插入图片描述

  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值