arm工作模式——异常和中断使用方法
来源:互联网 发布:win7电脑打不开软件 编辑:程序博客网 时间:2024/06/06 21:43
Arm920T寄存器简单介绍:
R1-R15:通用寄存器
R13:栈指针寄存器
R14:程序连接寄存器,当执行BL子程序调用指令时,R14中得到R15(程序计数寄存器pc)的备份,而当
发生中断或异常时,对应的R14_svc、R14_irq等保存R15返回值。
R15:程序计数器pc
CPSR:当前程序状态寄存器
1、T位(1位) Thumb/Arm。
2、I位与F位(5、6位)IRQ中断、FIQ中断开关。
SPSR:程序状态保存寄存器,SPSR中保存前一个工作模式的CPSR值。
异常发生时,将切换进入相应的异常模式,ARM920T cpu核自动完成如下工作,注意是自动完成。
1、在异常模式的连接寄存器R14中保存前一个工作模式的下一条即将执行的指令地址(R15->R14_xxx),
对于ARM状态,这个值是当前pc值加4或加8。
2、将CPSR的值复制到异常模式的SPSR(CPSR->SPSR)。(所用模式共用一个CPSR,各异异常模式有一个
自己的SPSR,用于保存前一个模式下的CPSR值)。
3、将CPSR的工作模式位设置为这个异常模式对应的工作模式。
4、令pc值等于这个异常模式在异常向量表中的地址,即跳转去执行异常向量表中的相应指令。
相反地,从异常模式回到之前的工作模式,需要通过软件完成如下事情:
1、将异常模式下的R14减去一个适当值后赋给pc寄存器。
2、将SPSR的值复制回CPSR。
退出异常时pc的值计算方法见韦东山的《嵌入式Linux应用开发完全手册》表9.1 p146。
中断处理过程:
1、中断控制器汇集各类外设发出的中断信号,然后告诉cpu。
2、cpu保存当前程序的运行环境,调用中断服务程序(ISR,Interrupt Service Rountine)。
3、在ISR中通过读取中断控制器,外设的相关寄存器来识别这是哪一个中断,并进行相应的处理。
4、清除中断,通过读写中断控制器和外设的相关寄存器实现。
5、恢复运行环境,继续执行。
各寄存器用途:
SUBSRCPND:标识INT_RXD0、INT_TXD0等中断是否已经发生。
INTSUBMSK:屏蔽SUBSRCPND寄存器所标识的中断。
SRCPND:每一位用来表示一个(或一类)中断是否已经发生,两类中断,这两类中断是:使用
SUBSRCPND/INTSUBMSK控制的中断request source(with sub register)使用SRCPND/INTMSK
控制的中断request source(without sub register)。
INTMSK:屏蔽SRCPND寄存器所标识的中断。
INTMOD:某位被置1时,它对应的中断被设为FIQ。同一时刻只能设置其中的一位,只能设置一个FIQ。
PRIORITY:优先级仲裁器。多个普通中断同时发生的时候,根据这个寄存器找出优先级最高的处理。
INTPND:cpu即将处理的中断标志。同一时刻只能设置其中1位,ISR中可根据这个位确定发生的是哪个中断。
INTOFFSET:表示INTPND哪位被置1。
中断有两类,是request_source(without sub register)和request_source(with usb register),这两类对
应不同的屏蔽寄存器(INTMSK和INTSUBMSK)和发生中断的标志寄存器(SRCPND和SUBSRCPND)。
如果被触发的中断有快速中断(IFQ)(INTMOD寄存器中为1的为对应的是FIQ),则cpu进如快中断处理。若几个IRQ同时,则选出优先级最高的,其在INTPND寄存器中的相应位被置1,然后cpu进入中断模式处理。
中断服务程序可通过读取INTPND寄存器或者INTOFFSET寄存器来确定中断源。
优先级在PRIORITY寄存器设置。
中断使用:
(1)、设置好中断与快中断模式下的栈
(2)、准备好中断处理函数
1、异常向量
在异常向量表中设置好当进入中断模式或快中断模式时的跳转函数,他们的异常向量地
址分别是0x00000018、0x0000001c。
2、中断服务程序(ISR)
跳转函数最终调用具体的中断服务函数,对于IRQ、读取INTPND寄存器或INTOFFSET寄存
器的值来确定中断源,然后分别处理,对于FIQ,无须判断。
3、清除中断
可在调用ISR之前,也可以在ISR之后,取决于是否嵌套。
清除顺序:1外设 2SUBSRCPND(用到的话)SRCPND中相应的位 3 轻INTPND相应位。
(3)进入、退出中断模式或快速中断模式是,需要保存、恢复被中断程序的运行环境。
1、对于IRQ,进入和退出的代码如下:
中断触发条件(低电 平触发、高电平触发、下降沿触发还是上升沿触发)等。一些中断拥有自己的屏
蔽寄存器,还要开启他。
(5)对于“request sources(without sub-register)"中的中断,将INTSUBMSK寄存器中相应的位设为0。
(6)确定使用此中断的方式:FIQ或IRQ。
如果是FIQ,则在INTMOD寄存器中设置相应的位为1.
如果是IRQ,则在RIORITY寄存器中设置优先级。
(7)如果是IRQ,将INTMSK寄存器中相应位设为0(IFQ不受INTMSK寄存器控制)。
(8)设置CPSR寄存器中的I-bit(对于IRQ)或F-bit(对于FIQ)为0,使能IRQ或IFQ。
中断实例:在JZ2440开发板上,把K1-K4四个按键所接的CPU引脚设成外部中断功能。本程序的main函数是一
个不做任何事情的无限循环,程序的功能完全靠中断来驱动:当按下某个按键时,CPU调用其中断服务程序
R1-R15:通用寄存器
R13:栈指针寄存器
R14:程序连接寄存器,当执行BL子程序调用指令时,R14中得到R15(程序计数寄存器pc)的备份,而当
发生中断或异常时,对应的R14_svc、R14_irq等保存R15返回值。
R15:程序计数器pc
CPSR:当前程序状态寄存器
1、T位(1位) Thumb/Arm。
2、I位与F位(5、6位)IRQ中断、FIQ中断开关。
SPSR:程序状态保存寄存器,SPSR中保存前一个工作模式的CPSR值。
异常发生时,将切换进入相应的异常模式,ARM920T cpu核自动完成如下工作,注意是自动完成。
1、在异常模式的连接寄存器R14中保存前一个工作模式的下一条即将执行的指令地址(R15->R14_xxx),
对于ARM状态,这个值是当前pc值加4或加8。
2、将CPSR的值复制到异常模式的SPSR(CPSR->SPSR)。(所用模式共用一个CPSR,各异异常模式有一个
自己的SPSR,用于保存前一个模式下的CPSR值)。
3、将CPSR的工作模式位设置为这个异常模式对应的工作模式。
4、令pc值等于这个异常模式在异常向量表中的地址,即跳转去执行异常向量表中的相应指令。
相反地,从异常模式回到之前的工作模式,需要通过软件完成如下事情:
1、将异常模式下的R14减去一个适当值后赋给pc寄存器。
2、将SPSR的值复制回CPSR。
退出异常时pc的值计算方法见韦东山的《嵌入式Linux应用开发完全手册》表9.1 p146。
中断处理过程:
1、中断控制器汇集各类外设发出的中断信号,然后告诉cpu。
2、cpu保存当前程序的运行环境,调用中断服务程序(ISR,Interrupt Service Rountine)。
3、在ISR中通过读取中断控制器,外设的相关寄存器来识别这是哪一个中断,并进行相应的处理。
4、清除中断,通过读写中断控制器和外设的相关寄存器实现。
5、恢复运行环境,继续执行。
各寄存器用途:
SUBSRCPND:标识INT_RXD0、INT_TXD0等中断是否已经发生。
INTSUBMSK:屏蔽SUBSRCPND寄存器所标识的中断。
SRCPND:每一位用来表示一个(或一类)中断是否已经发生,两类中断,这两类中断是:使用
SUBSRCPND/INTSUBMSK控制的中断request source(with sub register)使用SRCPND/INTMSK
控制的中断request source(without sub register)。
INTMSK:屏蔽SRCPND寄存器所标识的中断。
INTMOD:某位被置1时,它对应的中断被设为FIQ。同一时刻只能设置其中的一位,只能设置一个FIQ。
PRIORITY:优先级仲裁器。多个普通中断同时发生的时候,根据这个寄存器找出优先级最高的处理。
INTPND:cpu即将处理的中断标志。同一时刻只能设置其中1位,ISR中可根据这个位确定发生的是哪个中断。
INTOFFSET:表示INTPND哪位被置1。
中断有两类,是request_source(without sub register)和request_source(with usb register),这两类对
应不同的屏蔽寄存器(INTMSK和INTSUBMSK)和发生中断的标志寄存器(SRCPND和SUBSRCPND)。
如果被触发的中断有快速中断(IFQ)(INTMOD寄存器中为1的为对应的是FIQ),则cpu进如快中断处理。若几个IRQ同时,则选出优先级最高的,其在INTPND寄存器中的相应位被置1,然后cpu进入中断模式处理。
中断服务程序可通过读取INTPND寄存器或者INTOFFSET寄存器来确定中断源。
优先级在PRIORITY寄存器设置。
中断使用:
(1)、设置好中断与快中断模式下的栈
(2)、准备好中断处理函数
1、异常向量
在异常向量表中设置好当进入中断模式或快中断模式时的跳转函数,他们的异常向量地
址分别是0x00000018、0x0000001c。
2、中断服务程序(ISR)
跳转函数最终调用具体的中断服务函数,对于IRQ、读取INTPND寄存器或INTOFFSET寄存
器的值来确定中断源,然后分别处理,对于FIQ,无须判断。
3、清除中断
可在调用ISR之前,也可以在ISR之后,取决于是否嵌套。
清除顺序:1外设 2SUBSRCPND(用到的话)SRCPND中相应的位 3 轻INTPND相应位。
(3)进入、退出中断模式或快速中断模式是,需要保存、恢复被中断程序的运行环境。
1、对于IRQ,进入和退出的代码如下:
sub lr,lr,#4 @计算返回地址stmdbsp!,{r0-r12,lr}@保存使用到的寄存器...... @处理中断ldmiasp!,{r0-r12,pc}^@中断返回@ ^ 表示将spsr的值赋给cpsr
2、对于FIQ、进入和退出的代码如下:
sub lr,lr #4@计算返回地址stmdb sp!,{r0-r7,lr}@保存使用到的寄存器……@处理快速中断ldimasp!,{r0-r7,pc}^@ ^ 表示将spsr的值赋给cpsr(4)根据具体中断,设置相关外设。比如对于GPIO中断,需要将相应的引脚的功能设为“外部中断”、设置
中断触发条件(低电 平触发、高电平触发、下降沿触发还是上升沿触发)等。一些中断拥有自己的屏
蔽寄存器,还要开启他。
(5)对于“request sources(without sub-register)"中的中断,将INTSUBMSK寄存器中相应的位设为0。
(6)确定使用此中断的方式:FIQ或IRQ。
如果是FIQ,则在INTMOD寄存器中设置相应的位为1.
如果是IRQ,则在RIORITY寄存器中设置优先级。
(7)如果是IRQ,将INTMSK寄存器中相应位设为0(IFQ不受INTMSK寄存器控制)。
(8)设置CPSR寄存器中的I-bit(对于IRQ)或F-bit(对于FIQ)为0,使能IRQ或IFQ。
中断实例:在JZ2440开发板上,把K1-K4四个按键所接的CPU引脚设成外部中断功能。本程序的main函数是一
个不做任何事情的无限循环,程序的功能完全靠中断来驱动:当按下某个按键时,CPU调用其中断服务程序
来点亮对应的LED。主要看一下head.S和interrupt.c
@******************************************************************************@ File:head.S@ 功能:初始化,设置中断模式、管理模式的栈,设置好中断处理函数@****************************************************************************** .extern main.text .global _start _start:@****************************************************************************** @ 异常向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用@****************************************************************************** b Reset@ 0x04: 未定义指令中止模式的向量地址HandleUndef: b HandleUndef @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式HandleSWI: b HandleSWI@ 0x0c: 指令预取终止导致的异常的向量地址HandlePrefetchAbort: b HandlePrefetchAbort@ 0x10: 数据访问终止导致的异常的向量地址HandleDataAbort: b HandleDataAbort@ 0x14: 保留HandleNotUsed: b HandleNotUsed@ 0x18: 中断模式的向量地址 b HandleIRQ@ 0x1c: 快中断模式的向量地址HandleFIQ: b HandleFIQReset: ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈 bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启 msr cpsr_c, #0xd2 @ 进入中断模式 ldr sp, =3072 @ 设置中断模式栈指针 msr cpsr_c, #0xd3 @ 进入管理模式 ldr sp, =4096 @ 设置管理模式栈指针, @ 其实复位之后,CPU就处于管理模式, @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略 bl init_led @ 初始化LED的GPIO管脚 bl init_irq @ 调用中断初始化函数,在init.c中 msr cpsr_c, #0x53 @ 设置I-bit=0,开IRQ中断 ldr lr, =halt_loop @ 设置返回地址 ldr pc, =main @ 调用main函数halt_loop: b halt_loopHandleIRQ: sub lr, lr, #4 @ 计算返回地址 stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器 @ 注意,此时的sp是中断模式的sp @ 初始值是上面设置的3072 ldr lr, =int_return @ 设置调用ISR即EINT_Handle函数后的返回地址 ldr pc, =EINT_Handle @ 调用中断服务函数,在interrupt.c中int_return: ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsrinterrupt.c:
#include "s3c24xx.h"void EINT_Handle(){ unsigned long oft = INTOFFSET; unsigned long val; switch( oft ) { // S2被按下 case 0: { GPFDAT |= (0x7<<4); // 所有LED熄灭 GPFDAT &= ~(1<<4); // LED1点亮 break; } // S3被按下 case 2: { GPFDAT |= (0x7<<4); // 所有LED熄灭 GPFDAT &= ~(1<<5); // LED2点亮 break; } // K4被按下 case 5: { GPFDAT |= (0x7<<4); // 所有LED熄灭 GPFDAT &= ~(1<<6); // LED4点亮 break; } default: break; } //清中断 if( oft == 5 ) EINTPEND = (1<<11); // EINT8_23合用IRQ5 SRCPND = 1<<oft; INTPND = 1<<oft;}
阅读全文
1 0
- arm工作模式——异常和中断使用方法
- arm的异常、中断和arm工作模式的联系
- 浅析arm的异常、中断和arm工作模式的联系
- ARM的工作模式和中断流程
- ARM异常和中断
- ARM中断和异常
- ARM工作模式与中断
- ARM工作模式与中断
- arm —工作模式
- ARM中的异常和中断
- ARM的异常和中断
- ARM中的异常和中断
- arm linux 中断和异常
- 转载——ARM异常中断初探
- 8.ARM工作模式和寄存器及异常
- ARM处理器模式和片内寄存器, ARM 异常及中断
- 保护模式及其编程——中断和异常处理
- ARM—工作状态,工作模式
- fabric源码解析21——撇开的一笔
- java-Random类
- 11.24~25数据结构题解及总结
- 如何更改工程内最少的代码修改系统UISwitch的大小和样式
- 插入排序
- arm工作模式——异常和中断使用方法
- mAP
- Python--os模块
- 数据库新动向 Oracle 与微软割据局面产生
- 写一个老是忘记的linux进程pid是哪个?
- 请移步新博客
- 利用asio实现了一个服务器,多个客户端连接,并异常断开连接,发现后面再也连接不上服务器了,不能建立新连接了。原因分析
- linux实验四
- python---之np.newaxis