以我的s3c2440为基础,分析arm9下CPU的工作模式和异常处理。
CPU有7种工作模式:
● 用户模式(user 模式),运行应用的普通模式
● 快速中断模式(fiq 模式),用于支持数据传输或通道处理
● 中断模式(irq 模式),用于普通中断处理
● 超级用户模式(svc 模式),操作系统的保护模式
● 异常中断模式(abt 模式),输入数据后登入或预取异常中断指令
● 系统模式(sys 模式),使操作系统使用的一个有特权的用户模式
● 未定义模式(und 模式),执行了未定义指令时进入该模式
各种模式的不同,其实是CPU中使用的寄存器不太一样。
如图
以系统模式和用户模式下的R0到R15为基础,不同工作模式下,带灰色三角形的是各自模式下自带的相关寄存器,比如FIQ快中断模式下R8-R14寄存器是该模式自己的,和系统模式和用户模式下的R8-R14在硬件上是不同的寄存器。R13是SP堆栈指针寄存器,用来设置栈;R14是链接寄存器,用来保存返回地址。
快中断模式下有自己独有的R8-R14寄存器,那么它的工作速度就会比较快一些。
CPSR和SPSR两个寄存器分别是当前程序状态寄存器和保存程序状态寄存器,它们的结构是相同的,如图:
M0-M4用来显示当前CPU工作在什么模式下,如图
10000就是用户模式,11111就是系统模式……
T用来指示当前是使用ARM指令集还是Thumb指令集。
F用来设置快中断模式下中断功能的使能,I用来设置中断模式下中断功能的使能。
N、Z、C、V 均为条件码标志位,它们的内容根据算术或逻辑运算的结果所改
变,并且来作为一些指令是否运行的检测条件,比如减法操作的结果为0的话会影响Z位(zero)。
发生异常时芯片会自动进行的操作
假设发生了未定义指令异常。
进入异常:
- 将下一条指令的地址保存到相应的 Link(R14) 寄存器中,比如发生了未定义指令异常,此时从管理模式下进入未定义模式,那么就将管理模式下的下一条指令地址保存到未定义模式下的R14中。
- 拷贝 CPSR 到相应的 SPSR,即拷贝管理模式下CPSR寄存器的值到未定义模式下SPSR寄存器中。
- 根据异常类型强制改变 CPSR 模式位的值。
- 令 PC 的值指向异常处理向量所指的下一条指令。
(这时也可能设置中断禁止标志,以防止不可估计的异常嵌套发生)
这里要详细提一下第4条,异常处理向量其实就是张表,如下:
当发生相应异常时硬件会自动设置PC寄存器,让程序跳转到特定地址去执行特定处理程序,比如发生了未定义指令异常,那么PC会自动跳到0x00000004这个地址,如果是软中断会自动跳转到0x0000008,如果是上电复位会自动跳转到0x00000000。这里跳转的地址是绝对地址,如果你是nand启动,那么就是片内内存SRAM中的0x00000000 0x00000004 0x00000008……;如果你是nor启动,那么就是nor flash的0x00000000 0x00000004 0x00000008……。跳转到的地址是硬件自己设计的,没什么道理好讲,我们能做的就是在相应的地址写好相应的处理方式,比如发生了软中断,那么我们就在0x00000008这个地址写好处理函数入口,让程序自己跳过去执行,因此程序的开头往往是这样的:
这就是异常向量表的内容——一条条跳转语句,发生一个异常就跳转到那个异常的处理入口,所以当发生一个异常时会跳转两次,第一次是硬件自己跳到异常向量表,第二次是我们写的跳转到相应处理程序。要注意的是,当发生异常跳转时,程序会跳回0x0000xxxx,这是绝对跳转,因此即使你在异常发生之前已经重定位到SDRAM(内存)中了,异常发生后还是会跳出SDRAM中执行,那么你就需要重新进行跳转,让程序跳回SDRAM。
离开异常处理时的行为
- 将 Link 寄存器,减去相应的偏移量,赋给 PC(偏移量的值由异常的类型
决定); - 拷贝回 SPSR 到 CPSR;
- 如果在进入中断时设置了中断禁止标志,清除它。
(进入和离开异常处理是参考了网上的s3c2440用户手册的中文版本)
——————————————————————————————————
在arm中,中断(IRQ硬件中断)是异常的一种,对IQR的操作还有对中断控制器相关寄存器的操作,之后单独详解。
在加入操作系统之后,这7种模式不会都用到。
其实上电复位之后就会发生reset异常,然后进入管理模式。
————————————————————————————————
暂时就这么多,过两天再补充一下,因为这里还有一些知识点没弄清楚。