ARM单片机上电启动流程详解
ARM单片机启动流程分析
一、ARM架构
1.ARM MCU的复位系统(CM3)
在ARM Cortex-M3内核中提供了多个复位信号,但是各厂商在设计自己的MCU系统时一般只使用以下三个复位信号,其他的复位信号在MCU内部实现(如:看门狗复位信号,软件复位)。
注意:软件复位(寄存器AIRCR的第0位)只能复位内核,内核以外的不受影响
2.中断向量表
在MCU中用于存储中断服务程序入口地址的表格。该表格其实就是一个32位(4字节)连续地址的一块物理空间,该物理空间中存储着各种中断服务程序的入口地址。
中断向量表的初始地址是 0。因此,在地址 0 处必须包含一张向量表,用于初始时的异常分配。
异常类型 | 表项地址偏移量 | 异常向量 |
---|---|---|
0 | 0x00 | MSP |
1 | 0x04 | 复位 |
2 | 0x08 | NMI |
3 | 0x0C | 硬 fault |
4 | 0x10 | MemManage fault |
5 | 0x14 | 总线 fault |
6 | 0x18 | 用法 fault |
7‐10 | 0x1c‐0x28 | 保留 |
11 | 0x2c | SVC |
12 | 0x30 | 调试监视器 |
13 | 0x34 | 保留 |
14 | 0x38 | PendSV |
15 | 0x3c | SysTick |
16 | 0x40 | IRQ #0 |
17 | 0x44 | IRQ #1 |
18‐255 | 0x48‐0x3FF | IRQ #2 ‐ #239 |
在 MCU 的内核汇编启动文件中可以找到每一个中断向量表中存储的中断服务函数入口:
二、MCU初次上电
MCU初次上电初始化MCU期间调试组件或调试寄存器将不能被访问(上电时刻无法进行系统DAP调试)。
DEMCR 中的控制位是在上电复位时得到复位的。系统复位(例如,往 NVIC 应用程序中断及复位寄存器中写命令)不会影响到它们。
1.产生上电复位(nPORESET)
上电第一时刻产生一个上电复位(nPORESET)状态,在等待时钟信号稳定后退出复位状态。
注意:上电复位信号不是中断,并不会进入某个中断
2.堆栈初始化
在退出复位状态后,CM3 做的第一件事就是读取下列两个 32 位整数的值:
1.从地址 0x0000_0000 处(中断向量地址偏移量0)取出 MSP 的初始值。
2.从地址 0x0000_0004 处(中断向量地址偏移量4)取出 PC 的初始值——这个值是复位向量,LSB 必须是 1。然后从这个值所对应的地址处取指,进入复位中断中断。
上电后,通过从向量表中取出 0 号向量,仅初始化了 MSP。MSP 初始化好后就为复位中断服务(和其他特权级态服务)准备好了堆栈。
注意:CM3 是在 Thumb态下执行,所以向量表中的每个数值都必须把 LSB 置 1(也就是奇数)。
所以下图中使用 0x101 来表达地址 0x100
3.进入复位中断服务程序
1.裸机的复位中断服务程序
在裸机程序中通常只是用一个sp指针(MSP)。下图是裸机的复位中断服务程序,直接对系统进行初始化后,跳转到main中去运行。
2.带操作系统的复位中断服务程序
一般来讲带操作系统的复位中断服务程序也是对系统进行初始化,然后跳转到main中去执行应用程序,与裸机不同的是带操作系统的复位中断复服务程序还会对操作系统内核的一些东西进行初始化(不细节讨论初始化了些什么东西)。
4.跳转到main应用程序
在完成复位中断复位程序后,就会跳转到main里面去执行应用程序了,至此从上电到程序跳转到main的整个流程就结束了。
三.双堆栈的使用
一般来讲,操作系统为了避免出现应用程序恶意修改内核,都会使用双堆栈(MSP和PSP)。
由于从向量表中取出 0 号向量,仅初始化了 MSP。而对于 PSP 指针的初始化(或修改)需要在 PendSV 中断服务中对各个线程的 PSP 指针进行保护和更新。
如下图在RT-Thread操作系统对任务进行切换时设置PSP指针的部分程序:
作者:constant_LDX