ARM 异常

start                   ;系统复位位置

_start: b      reset           ;各个异常向量对应的跳转代码

        ldr     pc, _undefined_instruction;未定义的指令异常

        ldr     pc, _software_interrupt    ;软件中断异常

        ldr     pc, _prefetch_abort         ;内存操作异常

        ldr     pc, _data_abort              ;数据异常

        ldr     pc, _not_used                 ;未使用

        ldr     pc, _irq                      ;慢速中断异常

        ldr     pc, _fiq                      ;快速中断异常

从中我们可以看出,ARM支持7种异常。问题时发生了异常后ARM是如何响应的呢?第一个复位异常很好理解,它放在0x0的位置,一上电就执行它,而且我们的程序总是从复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。那么怎么会执行到后面几个异常处理函数呢?

看看书后,明白了ARM对异常的响应过程,于是就能够回答以前的这个疑问。

当一个异常出现以后,ARM会自动执行以下几个步骤:

1)把下一条指令的地址放到连接寄存器LR(通常是R14),这样就能够在处理异常返回时从正确的位置继续执行。

2)将相应的CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中。从异常退出的时候,就可以由SPSR来恢复CPSR

(3)根据异常类型,强制设置CPSR的运行模式位。

4)强制PC(程序计数器)从相关异常向量地址取出下一条指令执行,从而跳转到相应的异常处理程序中。

至于这些异常类型各代表什么,我也没有深究。因为平常就关心reset了,也没有必要弄清楚。

ARM规定了异常向量的地址:

b      reset           ;复位0x0

ldr  pc, _undefined_instruction;未定义的指令异常0x4

        ldr     pc, _software_interrupt    ;软件中断异常   0x8

        ldr     pc, _prefetch_abort         ;预取指令   0xc

        ldr     pc, _data_abort              ;数据       0x10

        ldr     pc, _not_used                 ;未使用     0x14

        ldr     pc, _irq                      ;慢速中断异常  0x18

        ldr    pc, _fiq                      ;快速中断异常   0x1c

这样理解这段代码就非常简单了。碰到异常时,PC会被强制设置为对应的异常向量,从而跳转到相应的处理程序,然后再返回到主程序继续执行。

这些引导程序的中断向量,是仅供引导程序自己使用的,一旦引导程序引导Linux内核完毕后,会使用自己的中断向量。

嗬嗬,这又有问题了。比如,ARM发生中断(irq)的时候,总是会跑到0x18上执行啊。那Linux内核又怎么能使用自己的中断向量呢?原因在于Linux内核采用页式存储管理。开通MMU的页面映射以后,CPU所发出的地址就是虚拟地址而不是物理地址。就Linux内核而言,虚拟地址0x18经过映射以后的物理地址就是0xc000 0018。所以Linux把中断向量放到0xc000 0018就可以了。

另外,说一下MMU。说句实话,还不是很明白这个MMU机理。参加Intel培训的时候,李眈说了MMU的两个主要作用:

(1)安全性:规定访问权限

 (2)提供地址空间:把不连续的空间转换成连续的。

2点是不是实现页式存储的意思?

200569日晚

补充一下:  05/06/14

.globl _start
;系统复位位置
_start: b reset
;各个异常向量对应的跳转代码
ldr pc, _undefined_instruction
;未定义的指令异常

……

_undefined_instruction :
.word undefined_instruction

也许有人会有疑问,同样是跳转指令,为什么第一句用的是 b reset
而后面的几个都是用ldr

为了理解这个问题,我们以未定义的指令异常为例。

当发生了这个异常后,CPU总是跳转到0x4,这个地址是虚拟地址,它映射到哪个物理地址
取决于具体的映射。
ldr pc, _undefined_instruction
相对寻址,跳转到标号_undefined_instruction,然而真正的跳转地址其实是_undefined_instruction的内容——undefined_instruction。那句.word的相当于:
_undefined_instruction dw undefined_instruction (
详见毕设笔记3)。
这个地址undefined_instruction到底有多远就难说了,也许和标号_undefined_instruction在同一个页面,也许在很远的地方。不过除了reset其他的异常是MMU开始工作之后才可能发生的,因此undefined_instruction 的地址也经过了MMU的映射。
在刚加电的时候,CPU0x0开始执行,MMU还没有开始工作,此时的虚拟地址和物理地址相同;另一方面,重启在MMU开始工作后也有可能发生,如果reset也用ldr就有问题了,因为这时候虚拟地址和物理地址完全不同。

因此,之所以resetb,就是因为resetMMU建立前后都有可能发生,而其他的异常只有在MMU建立之后才会发生。用b resetreset子程序与reset向量在同一页面,这样就不会有问题(b是相对跳转的)。如果二者相距太远,那么编译器会报错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值