单片机如何从上电复位执行到main函数?

本文详细介绍了Cortex-M架构单片机从上电复位到执行main函数的过程,包括启动文件、系统初始化、全局变量初始化等步骤。通过分析启动文件的向量表、中断处理程序、SystemInit函数,以及编译器的初始化代码,揭示了程序如何从复位入口开始,经过系统配置,直至进入用户代码的main函数。同时,文中还讨论了全局变量的初始化机制,以及如何根据需求定制系统初始化过程。
摘要由CSDN通过智能技术生成

单片机如何从上电复位执行到main函数?

从事嵌入式开发的搭档可能会思考过一个问题,我们一般都是使用芯片厂商提供的驱动库和初始化文件,直接从main函数初始写程序,那么系统上电之后,程序怎么引导进main函数执行的呢?还有,系统上电之后RAM的数据是随机的,那么定义的全局变量的初始值又是怎么实现的呢?

下面我将带着这两个问题,以Cortex-M架构为例,采用IAR EWARM作为编译工具链,从系统上电之后执行的第一条代码初始,梳理系统的启动过程,了解编译器在此期间所做的工作。其他的工具链,如Keil和GCC在系统初始化过程所做的工作也是相似的,但详细的实现有所差异。

1、启动文件

芯片厂商提供的启动文件,一般是采用汇编语言编写,少数用C语言。在启动文件中一般至少存在下面两个局部内容:

1、向量表

2、默认的中断和异常处理程序

向量表实际上是一个数组,放置在存储器的零地址,每个元素存储的是各个中断或异常处理程序的入口地址。以STM32F107芯片基于IAR工具的启动文件为例:

文件的开头定义了一个名为__vector_table的全局符号,“DATA”的作用是在代码段中定义一个数据区,用作向量表。数据区的内容是使用DCD指令定义的32位宽度常量,除了第一个sfe(CSTACK)比较特殊以为,其他的常量都是异常和中断效劳程序的地址(在编译时函数名会被替换成函数的入口地址)。sfe(CSTACK)是IAR汇编器段操作,用于获取段(section)的完毕地址,在这里意欲何为呢?

实际上这是获取堆栈基地址的操作。IAR在链接器脚本(*.icf)文件中定义堆栈,实际是定义了一个名为“CSTACK”的空闲块(block),如下图的脚本命令所示。所谓的块就是保留一段不间断的地址空间,用来作为堆栈或者堆。当然,块也能够是用内容的,例如能够用来管理段,但不在今天的探讨范围。

我们知道Cortex-M架构的堆栈模型是满减栈,堆栈从高地址向低地址增长,因此堆栈的基地址是CSTACK的完毕地址。

向量表的第一个元素是栈基址这是由Cortex-M架构定义的。系统上电后硬件自动从向量表中获取,并设置主堆栈指针MSP,而不是像其他ARM架构,堆栈指针须要通过软件来设置。

向量表中第二个元素是复位异常(Reset_Handler)的入口地址。系统上电后,硬件自动从__vector_table + 4的位置读取,并从读取到的地址初始执行。系统上电后CPU执行的第一条是Reset_Handler函数的第一条语句。

上面的THUMB命令表示接下来的代码采用THUMB模式(Cortex-M只支持Thumb-2指令集);SECTION用于定义一个段,段名为“.ResetHandler”,段的类型是代码(CODE);REODER指示用给定的名称开启一个新的段;ROOT指示链接器,当段内的符号没有被引用,链接器也不能够丢弃这个段。

PUBWEAK是弱定义,假如用户在其他位置编写了中断处理函数,在连接时实际链接用户所编写的,启动文件中用汇编写的效劳函数会忽略。之所以要在启动文件中以弱定义的方式编写全部的异常和中断效劳函数,是为了防止用户在没有编写效劳函数的情况下开启并触发了中断,导致系统的不确定。

2、系统初始化过程

在EWARM的工程Options > Debugger > Setup中将“Run to”勾选取消,这样在进入调试之后就会停第一条要执行的代码的位置:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值