从要做的事情上来说,无论哪种ARM架构的异常/中断都是一样的
- 每执行完一条指令都会检查有无中断/异常产生
- 发现有中断/异常产生,开始处理:
- 保存现场
- 分辨异常/中断,调用对应的异常/中断处理函数
- 恢复现场
- 保存现场
- 每执行完一条指令都会检查有无中断/异常产生
不同的芯片,不同的架构,在这方面的处理稍有差别:
- CPU中止当前执行,跳转去执行处理异常的代码:也有差异
- cortex M3/M4在向量表上放置的是函数地址
- cortex A7在向量表上放置的是跳转指令
- cortex M3/M4在向量表上放置的是函数地址
- 保存/恢复现场:cortex M3/M4是硬件实现的,cortex A7是软件实现的
- CPU中止当前执行,跳转去执行处理异常的代码:也有差异
Cortex M3/M4
- M3/M4中有一个_Vectors向量表,其中放着各种异常/中断的处理函数
- 异常/中断发生时,CPU怎么知道跳过来执行哪一个函数呢?
- 这应该由硬件决定,硬件上确定了当前发生了哪个异常/中断,CPU由此找到向量表中的某一项,从而跳转过去执行处理函数
- 编译时,vector向量表会保存在程序的最前面,将会被烧写到片内的flash上
- 这个flash的地址是多少呢?
- 在MDK中指定了:
- ROM地址为:0x8000000,大小为0x80000
- 在MDK中指定了:
- 注意:虽然flash基地址是0x8000000,但当我们复位后,这个地址将会映射到0地址去
- 这意味着,我们可以使用0x8000000来访问ROM,也可以使用0地址来访问ROM
- M3/M4中保存现场(将寄存器保存到栈中)是由硬件自动实现的;硬件保存现场后还要分辨是哪个异常/中断,得到异常/中断号,使用异常/中断号在flash上的vector向量表中找到一项,CPU跳转过去执行其中的函数
- 处理函数执行完后,就会返回,这个步骤将会触发硬件将之前保存的寄存器值恢复回去,这样之前被中断的程序就会继续运行了
发生异常/中断时,硬件上实现了这些事情:
- 保存现场:把被中断瞬间的寄存器的值保存进栈里
- 根据异常/中断号,从向量表中得到函数地址,跳转过去执行
- 函数执行完后,从栈中恢复现场
保存现场、分辨异常/中断、跳转执行,都是硬件实现的。我们只需要在向量表中,把处理函数的地址填进去就可以了。 硬件承包了大部分的工作。
- 保存现场:把被中断瞬间的寄存器的值保存进栈里
M3/M4的向量表中,存放的是函数地址
Cortex A7
- A7的向量表与M3/M4不一样,其中存放的是跳转指令
- Uboot中的异常向量表
- 目录是:u-boot/arch/arm/lib/vector.S 并不位于某个处理器芯片下面,这表明这个vector应该是通用的
- 这其中放的是某一种异常的总入口,是一条跳转指令
- 显然,在跳转到的异常总入口里,应该进行更进一步的异常分辨(如中断_irq中,应该进一步区分是什么中断)
- A7中,CPU执行完一条指令后检测到发生中断时,由硬件进行异常模式切换_irq,然后跳转执行中断向量表中的跳转指令,进而跳转到异常处理函数的总入口
- 向量表中直接对PC赋值,那么中断前程序的地址(返回地址)怎么办?硬件自动保存PC值到LR寄存器了吗?
- 一般异常模式(除FIQ)只有SP和LR两个寄存器是独有的,PC寄存器是公用的
- 猜测最大可能是PC值自动保存到对应模式的LR寄存器,那么跳转到向量表的指令就应该用的跳转指令B/BL了,只有这样PC值才会自动的被保存在LR寄存器中
- 保存/恢复现场由软件进行
发生异常/中断时,硬件上实现了这些事情:
- CPU切换到对应的异常模式,比如IRQ模式、未定义模式、SVC模式
保存被中断时的CPSR到SPSR
- CPSR:current program status register,当前程序状态寄存器
- SRSR:saved program status register,保存的程序状态寄存器
跳到这个异常的入口地址去,执行指令,这通常是一条跳转指令
软件要做的事情就比较多了:
- 保存现场
- 分辨异常/中断
- 调用对应的处理函数
- 恢复现场
A7的向量表中,存放的是跳转指令。