ARM异常中断处理:
ARM体系异常中断种类:按中断的处理优先级从高到低依次为:复位、数据访问中止、快速中断请求、外部中断请求、预取指中止、未定义指令、软件中断。
ARM体系中的异常中断向量表:
0x0 复位
0x4 未定义指令
0x8 软件中断(SWI)
0x0c 预取指中止
0x10 数据访问中止
0x14 保留
0x18 外部中断请求(IRQ)
0x1c 快速中断请求(FIQ)
各异常中断对应着一定的处理器模式,不同处理器模式下有各自的物理寄存器。如果异常中断处理程序中使用它自己的物理寄存器之外的其他寄存器,异常中断处理程序
必须保存和恢复这些寄存器。
进入和退出异常中断的过程:
进入中断的过程:
<1>将当前程序状态寄存器CPSR的内容保存到将要执行的异常中断对应的SPSR寄存器中。
<2>设置当前程序状态寄存器CPSR中相应的位,使处理器进入相应的执行模式;设置CPSR中的位,禁止IRQ中断,当进入FIQ模式时,禁止FIQ中断。
<3>将寄存器lr_mode设置成返回地址
<4>将程序计数器PC,设置成该异常中断的中断向量地址,从而跳转到相应的异常中断处理程序处执行。
上述的处理器对异常中断的响应过程可以用如下的伪代码描述:
R14_<exception_mode> = return_link
SPSR_<exception_mode> = CPSR
CPSR[4:0] = exception_mode_number
/*当运行于ARM状态时*/
CPSR[5] = 0
/*当相应的FIQ异常中断时,禁止新的FIQ中断*/
if <exception_mode> == reset or FIQ then
CPSR[6] = 1
/*禁止新的IRQ中断*/
CPSR[7] = 1
PC = exception_vector_address
响应复位异常中断:当处理器的复位引脚有效时,处理器中止当前指令。当处理器的复位引脚变成无效时,处理器开始执行下面的操作:
R14_svc = UNPREDICTABLE value
SPSR_svc = UNPREDICTABLE value
/*进入特权模式*/
CPSR[4:0] = 0b10011
/*切换到ARM状态*/
CPSR[5] = 0
/*禁止新的FIQ中断*/
CPSR[6] = 1
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF0000
else
PC = 0x00000000
响应未定义指令异常中断:处理器检测到未定义指令异常时,处理器开始执行下面的操作:
R14_und = address_of_next_instruction_after_the_undefined_instruction
SPSR_und = CPSR
/*进入未定义指令异常中断模式*/
CPSR[4:0] = 0b11011
/*切换到ARM状态*/
CPSR[5] = 0
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF0004
else
PC = 0x00000004
响应SWI异常中断:处理器检测到SWI异常时,处理器开始执行下面的操作:
R14_svc = address_of_next_instruction_after_the_SWI_instruction
SPSR_svc = CPSR
/*进入特权模式*/
CPSR[4:0] = 0b10011
/*切换到ARM状态*/
CPSR[5] = 0
/*CPSR[6]不变*/
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF0008
else
PC = 0x00000008
响应预取指中止异常中断:处理器检测到预取指中止异常时,处理器开始执行下面的操作:
R14_abt = address_of_the_aborted_instruction + 4
SPSR_abt = CPSR
/*进入预取指中止异常中断模式*/
CPSR[4:0] = 0b10111
/*切换到ARM状态*/
CPSR[5] = 0
/*CPSR[6]不变*/
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF000C
else
PC = 0x0000000C
响应数据访问中止异常中断:处理器检测到数据访问中止异常时,处理器开始执行下面的操作:
R14_abt = address_of_the_aborted_instruction + 8
SPSR_abt = CPSR
/*进入数据访问中止异常中断模式*/
CPSR[4:0] = 0b10111
/*切换到ARM状态*/
CPSR[5] = 0
/*CPSR[6]不变*/
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF0010
else
PC = 0x00000010
响应IRQ异常中断:处理器检测到IRQ异常时,处理器开始执行下面的操作:
R14_irq = address_of_next_instruction_to_be_executed + 4
SPSR_irq = CPSR
/*进入IRQ异常中断模式*/
CPSR[4:0] = 0b10010
/*切换到ARM状态*/
CPSR[5] = 0
/*CPSR[6]不变*/
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF0018
else
PC = 0x00000018
响应FIQ异常中断:处理器检测到FIQ异常时,处理器开始执行下面的操作:
R14_fiq = address_of_next_instruction_to_be_executed + 4
SPSR_fiq = CPSR
/*进入FIQ异常中断模式*/
CPSR[4:0] = 0b10001
/*切换到ARM状态*/
CPSR[5] = 0
/*禁止新的FIQ中断*/
CPSR[6] = 1
/*禁止新的IRQ中断*/
CPSR[7] = 1
if high_vectors_configured then
PC = 0xFFFF001C
else
PC = 0x0000001C
退出中断的过程:从异常中断处理程序中返回包括以下两个基本操作
<1>将SPSR_mode寄存器的内容复制到当前程序状态寄存器CPSR中,以恢复被中断的程序的处理器状态。
<2>将lr_mode寄存器的内容复制到程序计数器PC中,以返回到发生异常中断的指令的下一条指令处执行。
对不同的异常中断,PC所指的位置是不同的,同时,返回地址也是不同的。
SWI和未定义指令异常中断处理程序的返回:
SWI和未定义指令异常中断是由当前执行的指令自身产生的,中断发生时,PC指向当前指令后的第2条指令,处理器将PC-4保存到异常模式下的lr_mode寄存器中,因此通过以下命令来实现返回:MOVS PC, LR 。当异常中断处理程序中使用了数据栈时,可以通过以下指令在进入中断处理程序时保存被中断程序的执行现场,在退出中断处理程序时恢复被中断程序的执行现场:
STMFD sp!, {reglist,lr}
;... ...
LDMFD sp!, {reglist,pc}^
IRQ和FIQ异常中断处理程序的返回:
IRQ和FIQ异常中断发生时,PC指向当前指令后的第3条指令,处理器将PC-4保存到异常模式下的lr_mode寄存器中,这时,PC-4指向当前指令后的第2条指令,因此通过以下命令来实现返回:SUBS PC, LR,#4 。当异常中断处理程序中使用了数据栈时,可以通过以下指令在进入中断处理程序时保存被中断程序的执行现场,在退出中断处理程序时恢复被中断程序的执行现场:
SUBS LR, LR, #4
STMFD sp!, {reglist,lr}
;... ...
LDMFD sp!, {reglist,pc}^
将异常中断处理程序注册到异常中断向量表中:
<1>使用跳转指令:在异常中断对应的向量表中特定的位置放一条跳转指令,直接跳转到该异常中断的处理程序。缺点:只能在32M的空间内跳转
<2>使用数据读取指令LDR:使用LDR向PC直接赋值。第一步:先将异常中断处理程序的绝对地址存放在距离向量表4KB的范围内的一个存储单元中;第二步:再使用LDR将该单元的内容读取到PC中。
相关文章
- 解读《ARM Cortex-M3 与Cortex-M4 权威指南》——第2章 嵌入式软件开发简介
- 《青少年编程与数学》课程方案:2、课程内容 4_2-十、Java语言编程
- Java IO编程全解(六)——4种I/O的对比与选型
- Python进阶(4)_进程与线程 (python并发编程之多进程)
- ARM架构—— Cortex-M3与Cortex-M4特点概述
- 嵌入式学习37-TCP并发模型-有限 2.IO模型: 1.阻塞IO: 没有数据到来时,可以让任务挂起 节省CPU资源开销,提高系统效率 2.非阻塞IO: 程序未接收到数据时一直执行 效率很低 3.异步IO 只能绑定一个文件描述符用来 读取数据 4.多路复用IO select 1.select监听的集合中的文件描述符有 上限限制 2.select有 内核层 向 用户层数据空间 拷贝 的过程,占用系统资源开销 3.select必须 轮询检测 产生 事件 的文件描述符 4.select 只能工作 在 水平触发 模式(低速模式) 无法工作 在 边沿触发 模式(高速模式) poll (监听的集合中的文件描述符有 没有上限限制) 1.poll有 内核层 向 用户层 数据空间 拷贝 的过程,占用系统资源开销 2.poll必须 轮询检测 产生 事件 的文件描述符 3.poll 只能工作在水平触发模式(低速模式) 与select相同 无法工作在边沿触发(高速模式) 3.函数接口: 1.select int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 功能: select 监听 文件描述符集合 中 是否 有文件描述编程 ready状态 select 监听 文件描述符集合 中 ,若有状态 , 将没有ready状态的T除 若无状态,将阻塞继续等待 参数: nfds: 最大文件描述符的值 +1 readfds: 读 文件描述符集合 writefds: 写 文件描述符集合 exceptfds: 其余 文件描述符集合 timeout: 等待的时长 NULL 一直等待(超时处理) 返回值: 成功 返回 文件描述符集合中 的 文件描述符个数 失败 返回 -1 void FD_CLR (int fd, fd_set *set); 功能: 将文件描述符 fd 从集合中清除
- 突破编程_C++_设计模式(装饰器模式)-4 装饰器模式的优点与缺点
- 单片机开发:keil4 C51 安装与破解 - 编程的故事
- 突破编程_C++_基础教程(输入、输出与文件)-4 文件操作
- 计算概论(A)/基础编程练习2(8题)/4:骑车与走路