中断基础知识
1、七种工作模式与相关寄存器
7种工作模式对应的寄存器
七种工作模式:
工作模式 | 描述 |
用户模式(usr) | arm处理器正常的程序执行状态 |
快速中断模式(fiq) | 用于高速数据传输或通道处理 |
中断模式(irq) | 用于通用的中断处理 |
管理模式(svc) | 操作系统使用的保护模式 |
数据访问终止模式(abt) | 当数据或指令预取终止时进入该模式,可用于虚拟存储和及存 储保护 |
系统模式(sys) | 运行具有特权的操作系统任务 |
未定义指令中止模式(und) | 当未定义的指令执行时进入该模式,可用于支持硬件 协处理器的软件仿真 |
ARM920T有31个通用的32位寄存器和6个程序状态寄存器。这37个寄存器分为7组,进入某个工作方式 ,就使用它那组的寄存器。有些寄存器在各种模式下都可以公用,那么当发生模式切换的时候,就需要保存这些寄存器的值,因为其他的模式也可以使用这些寄存器嘛!还有些寄存器只是本模式下用的,在其他模式下无法访问到,那么当发生模式转换时就不需要保存这些寄存器。
图中R0-R15可以直接访问,这些寄存器中除了R15外都是通用寄存器,即他们既可以用于保存数据也可以用于保存地址。另外,R13-R15稍微有点特殊,R13又被称为栈指针寄存器,通常被用于保存栈指针。R14又被称为程序连接寄存器或者连接寄存器,当执行BL子程序调用指令时,R14得到R15(程序寄存器PC)的备份。而当发生中断或异常时,对应的R14_svc、R14_irq、R14_fiq、R14_abt或者R14_und中保存R15返回值,R15是程序寄存器。
快速中断模式有7个备份寄存器R8-R14(即R8_fiq-R14_fiq),这使得由快速中断模式切换到其他模式或者从其它模式切换到快速中断模式时,并不需要保存寄存器R8_fiq-R14_fiq,如果其它一些公用寄存器也没有使用,甚至不需要保存任何寄存器。用户模式、管理模式、数据访问终止模式和未定义指令中止模式都含有两个独占的寄存器副本R13、R14,这样可以令每个模式都拥有自己的堆栈指针寄存器和连接寄存器。
每种工作模式除了R0-R15共16个寄存器外,还有第十七个寄存器CPSR,即当前程序状态寄存器。CPSR中一些位被用于标识各种状态,一些位被用于标识当前处于什么工作模式。同时每一种模式下都有一个专用的物理状态寄存器SPSR,当特定异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容,当异常退出时,可以用SPSR中保存的值来恢复CPSR。
CPSR中各位意义如下:
(1)条件标志位
标识位 | 含义 |
N | 本位设置成当前指令运算结果的bit[31]的值 |
Z | z=1表示运算的结果为零;z=0表示运算的结果不为零 |
C | 1、在加法指令中(包括比较指令CMP): |
V | 对于加减运算指令: |
以下指令会影响CPSR中的条件标志位:
<1>比较指令,如:CMP、CMN、TEQ及TST等
<2>当一些算数运算指令和逻辑运算指令的目标寄存器不是R15时,这些指令会影响CPSR中的条件标志位
<3>MSR指令可以向CPSR/SPSR中写入新值
<4>MRC指令将R15作为目标寄存器时,可以把协处理器产生的条件标志位的值传送到ARM处理器
<5>一些LDM指令的变种指令可以将SPSR的值复制到CPSR中,这种操作主要用于从异常中断程序中返回
<6>一些带"位设置"的算术和逻辑指令的变种指令,也可以将SPSR的值复制到CPSR中,这种操作主要用于从异常程序中返回
(2)Q标识位
在ARM V5的系列处理器中,CPSR的bit[27]称为q标识位,主要用于指示增强的DSP指令是否发生了溢出。
同样的SPSR的bit[27]位也称为q标识位,用于在异常中断发生时保存和恢复CPSR中的Q标识位。
(3)控制位
<1>中断禁止位
当I=1时,禁止IRQ中断
当F=1时,禁止FIQ中断
通常一旦进入中断服务程序可以通过置位I和F来禁止中断,但是在本中断服务程序退出前,必须回复I和F原来的值
<2>T控制位
对于ARMv4及更高版本的T系列处理器,T控制位含义如下:
T=0,表示执行ARM指令
T=1,表示执行Thumb指令
对于ARMv5及更高版本的非T系列处理器,T控制位含义如下:
T=0,表示执行ARM指令
T=1,表示强制下一条执行的指令产生为定义指令中断
(3)M控制位
控制位M[4:0]称为处理器模式标志位,具体如下:
M[4:0] | 处理器模式 | 可访问的寄存器 |
0b10000 | user pc | PC,R14~R0,CPSR |
0b10001 | FIQ | PC,R14_FIQ-R8_FIQ,R7~R0,CPSR,SPSR_FIQ |
0b10010 | IRQ | PC,R14_IRQ-R13_IRQ,R12~R0,CPSR,SPSR_IRQ |
0b10011 | SUPERVISOR | PC,R14_SVC-R13_SVC,R12~R0,CPSR,SPSR_SVC |
0b10111 | ABORT | PC,R14_ABT-R13_ABT,R12~R0,CPSR,SPSR_ABT |
0b11011 | UNDEFINEED | PC,R14_UND-R8_UND,R12~R0,CPSR,SPSR_UND |
0b11111 | SYSTEM | PC,R14-R0,CPSR(ARM V4以及更高版本) |
2、ARM处理器对异常中断的相应过程以及从异常中断处理程序中返回
(1)ARM处理器对异常中断的相应过程
当一个异常出现以后,ARM微处理器会执行以下几个步骤:
<1>在异常工作模式的连接寄存器R14中保存前一个工作模式的下一条地址,即将执行的指令的地址。对于ARM状态,这个值是当前PC值加4或者8
<2>将CPSR的值复制到异常模式的SPSR
<3>将CPSR的工作模式位设为这个异常对应的工作模式
<4>令PC的值等于这个异常模式在异常向量表中的地址,即跳转到异常向量表中的相应地址,这个地方可以放中断服务程序
(2)从异常中断处理程序中返回
相反的,从异常工作模式退出回到之前的工作模式时,需要完成下面几个步骤:
<1>前面进入异常工作模式时,连接寄存器中保存了前一个工作模式的一个指令地址,将它减去一个适当的值后赋给PC寄存器,具体可以查看下面的表格:
<2>将SPSR的值复制会CPSR
<3>若在进入异常处理时设置了中断禁止位,现在要清除
3、S3C2410/S3C2440中断控制器
(1)中断控制寄存器
SUBSRCPND、INTSUBMSK这两个寄存器中相同的位对应相同的中断;SRCPND、INTMSK、INTMOD、INTPND这4个寄存器中相同的位对应相同的中断。下面我们具体来说一说:
<1>SUBSRCPND寄存器
SUBSRCPND寄存器用来标识某类子中断是否发生,比如我们的UART中断,他就包括三个子中断:接收中断、发送中断、ERR中断。具体来说,比如SUBSRCPND寄存器的3个中断INT_TXD0、INT_RXD0、TIN_ERR0,只要有一个中断发生了并且它没有被屏蔽,则SRCPND寄存器里面的INT_UART0位被置1
要清楚中断时,往SUBSRCPND寄存器中某位写入1即可。
<2>INTSUBMSK寄存器
INTSUBMSK寄存器用来屏蔽SUBSRCPND寄存器所标识的中断。某位被置1,对应的中断被屏蔽
<3>SRCPND寄存器
每一位用来表示一个或一类中断是否已经发生。清除中断写入1
<4>INTMSK寄存器
INTMSK寄存器用来屏蔽SRCPND寄存器所标识的中断,置1表示屏蔽。但是它只能屏蔽IRQ中断,无法屏蔽FIQ中断
<5>INTMOD寄存器
当INTMOD寄存器某位设为1时,它对应的中断被设为FIQ,即此中断发生时,CPU将进入快速中断模式,这通常用来处理特别紧急的中断。同一时间里,INTMOD寄存器中只有一位被设为1
<6>PRIORITY寄存器
设置优先级,仅仅对IRQ中断有效
<7>INTPND寄存器
1表示相应的中断被响应,0表示没有响应。同一时间,此寄存器只有一位被置1,随后CPU将进入中断模式处理它。在ISR中,可以根据这个为确定是哪个中断。清除中断时,往这个位写入1
<8>INTOFFSET寄存器
这个寄存器被用来表示INTPND寄存器中哪位被置1了,即INTPND寄存器中位[x]为1时,INTOFFSET寄存器的值为x
清除SRCPND、INTPND寄存器时,INTOFFSET寄存器被自动清除
(2)使用中断的步骤如下:
<1>设置好中断模式和快速中断模式下的栈,当发生中断IRQ时,CPU进入中断模式,这时就使用中断模式下的栈;当发生快速中断FIQ时,CPU进入快速中断模式,这时就使用快速中断模式下的栈
<2>准备好中断处理函数
first:异常向量
在异常向量表中设置好当进入中断模式或快速中断模式时的跳转函数,他们的异常向量表地址分别是0x00000018、0x0000001c
second:中断服务程序(ISR)
IRQ、FIQ的跳转函数,最终将调用具体中断的服务函数
对于IRQ,读取INTPND寄存器或INTOFFSET寄存器的值来判断中断源,然后分别处理
对于FIQ,因为只有一个中断可以设为FIQ,无需判断中断源
third:清除中断
如果不清除中断,则CPU会误以为这个中断又发生了一次
清除中断时,从源头开始:首先,需要的话,操作具体外设清除中断信号;其次清除SUBSRCPND、SRCPND寄存器中的相应位(往相应位写1即可);最后,清除INTPND寄存器中的相应位(往相应位写1即可),最简单的方法就是:INTPND=INTPND
<3>进入、退出中断模式或快速中断模式时,需要保存、恢复被中断程序的运行环境
<4>根据具体中断,设置相关外设。比如对于GPIO中断,需要将相应引脚功能设为外部中断、设置中断发生条件。一些中断拥有自己的屏蔽寄存器,还要开启它
<5>对于无子中断源的请求,将INTSUBMASK寄存器中相应位设为0
<6>确定使用此中断的方式:FIQ或IRQ
如果是FIQ,则在INTMOD寄存器中设置相应位为1
如果是IRQ,则在RIORITY寄存器中设置优先级
<7>如果是IRQ,将INTMSK寄存器中相应位设为0(FIQ不受INTMSK寄存器控制)
<8>设置CPSR寄存器中的I_bit(对于IRQ)或F_bit(对于FIQ)