您的当前位置:首页ARM异常中断机制

ARM异常中断机制

来源:小侦探旅游网
ARM9(以S3C2410为例)中断机制

一、ARM异常机制介绍

ARM9处理器有7种工作模式。分别是 用户模式(usr):ARM处理器正常的程序执行状态。 快速中断模式(fiq):用于高速数据传输或通道处理。 外部中断模式(irq):用于通用的中断处理。 管理模式(svc):操作系统使用的保护模式。 数据访问终止模式(abt):当数据或指令预取终止时进入该模式。 系统模式(sys):运行具有特权的操作系统任务。 未定义指令中止模式(und):当未定义的指令执行时进入该模式。 每种模式通过5位二进制编码进行标示: 用户模式 快速中断模式 外部中断模式 管理模式 数据访问终止模式 未定义指令中止模式 系统模式 10000 10001 10010 10011 10111 11011 11111 模式编码存放在CPSR(程序当前状态寄存器)中的[4:0]。 快速中断模式、外部中断模式、数据访问终止模式、未定义指令中止模式、管理模式称为异常模式。 异常类型 复位 未定义指令 软件中断 指令预取中止 数据中止 IRQ(外部中断请求) FIQ(快速中断请求) 具体含义 当处理器的复位电平有效时,产生复位异常,程序跳转到复位异常处理程序处执行。 遇到不能处理的指令时,产生未定义指令异常。 该异常由执行SWI指令产生,可用于用户模式下的程序调用特权操作指令。可使用该异常机制实现系统功能调用。 若处理器预取指令的地址不存在,或该地址不允许当前指令访问,存储器会向处理器发出中止信号,但当预取的指令被执行时,才会产生指令预取中止异常。 若处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时,产生数据中止异常。 当处理器的外部中断请求引脚有效,且CPSR中的I位为0时,产生IRQ异常。系统的外设可通过该异常请求中断服务。 当处理器的快速中断请求引脚有效,且CPSR中的F位为0时,产生FIQ异常。 当多个异常发生时,处理器根据优先级进行处理。 优先级 1(最高) 2 3 复位 数据中止 FIQ 4 5 6(最低) IRQ 预取指令中止 未定义指令、SWI 异常中断发生时,处理器执行完当前的指令,需要保存当前执行现场,切换到相应的异常模式,并跳转到相应的异常中断处理程序。中断处理完成后,处理器返回现场执行下条指令。

异常处理一般过程如下:

(1)把当前工作模式中的下一条即将运行的指令地址保存到R14中; (2)保存当前CPSR到SPSR(保存程序状态寄存器); (3)改写CPSR中的工作模式为当前产生异常的工作模式; (4)禁止IRQ(如果进入FIQ则禁止FIQ); (5)跳转到相应异常向量表入口;

如果是复位异常处理会禁止所有中断,另外由于不用返回,因此不需要作(1)(2)步。以上的异常处理操作都是由处理器自动完成的。

二、异常向量表

Linux内核启动时,向量表的创建过程为:init/main.c->start_kernel()->trap_init()。

trap_init函数位于/arch/$(ARCH)/kernel/traps.c中。trap_init函数中向量表创建的相关代码如下: unsigned long vectors = CONFIG_VECTORS_BASE;

……

memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); 其中CONFIG_VECTORS_BASE是向量表的基地址。在ARM V4及V4T以后的大部分处理器中,向量表可以有两个位置:一个是0,另一个是0xffff0000。通过CP15协处理器c1寄存器中V位(bit[13])控制。V和异常向量表的对应关系如下: V=0 ~ 0x00000000~0x0000001C V=1 ~ 0xffff0000~0xffff001C

CONFIG_VECTORS_BASE的值在内核的相关配置文件中定义。比如在/arch/arm/configs/s3c2410_defconfig中CONFIG_VECTORS_BASE=0xffff0000。

异常向量表存放在__vectors_start至__vectors_end定义的空间内。 异常向量表的逻辑结构(8*4个字节)为: 异常类型 复位 未定义指令 软件中断 中止(数据) 保留 IRQ FIQ 工作模式 管理模式 未定义指令中止模式 管理模式 数据访问终止模式 外部中断模式 快速中断模式 地址 0x00000000 0x00000004 0x00000008 0x0000000C 0x00000010 0x00000014 0x00000018 0x0000001C 中止(预取指令) 数据访问终止模式 异常向量表的物理结构位于arch/arm/kernel/entry-armv.S中,如下所示: .globl __vectors_start __vectors_start:

swi SYS_ERROR0:

b vector_und + stubs_offset //复位异常:

ldr pc, .LCvswi + stubs_offset //未定义指令异常: b vector_pabt + stubs_offset //软件中断异常:

b vector_dabt + stubs_offset //数据异常(预取指令中止、数据中止): b vector_addrexcptn + stubs_offset //保留:

b vector_irq + stubs_offset //普通中断异常: b vector_fiq + stubs_offset //快速中断异常: .globl __vectors_end: __vectors_end:

异常向量表中各种异常对应位置上放置了一条跳转指令,用于指向相应异常的处理程序。__stubs_start至__stubs_end之间是异常处理程序的位置。

stubs_offset的值为:

.equ stubs_offset, __vectors_start + 0x200 - __stubs_start

三、中断处理

中断发生后,处理器执行向量表中的b vector_irq + stubs_offset指令。接着根据进入中断前的具体工作模式,执行irq_handler处理过程。irq_handler处理过程位于/arch/arm/kernel/entry-armv.S中,如下所示: .macro irq_handler ……

1: get_irqnr_and_base r0, r6, r5, lr @判断中断号,通过R0返回 ……

bne asm_do_IRQ @进入中断处理。 …… .endm

中断号的值是在和平台相关的文件中决定的。比如IRQ_EINT0在include/asm/arch-s3c2410/irqs.h中定义。这说明中断号的具体值和硬件中断挂起寄存器中的中断号是不等的。

asm_do_IRQ位于arch/arm/kernel/irq.c,如下所示:

asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) {

struct pt_regs *old_regs = set_irq_regs(regs);

struct irq_desc *desc = irq_desc + irq; //根据中断号找到对应的irq_desc。irq_desc 是外部中断描述符表,用于存储中断的相关信息

……

desc_handle_irq(irq, desc);// 根据中断号和desc进入中断处理 irq_finish(irq); irq_exit();

set_irq_regs(old_regs); }

static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc) {

desc->handle_irq(irq, desc); //中断处理 }

在include/linux/interrupt.h中定义了irqaction结构体,如下所示: struct irqaction {

irq_handler_t handler; //中断处理函数,注册时提供 unsigned long flags; //中断标志,注册时提供 cpumask_t mask; //中断掩码 const char *name; //中断名称

void *dev_id; //设备id,本文后面部分介绍中断共享时会详细说明这个参数的作用 struct irqaction *next; //如果有中断共享,则继续执行, int irq; //中断号,注册时提供

struct proc_dir_entry *dir; //指向IRQn相关的/proc/irq/n目录的描述符 };

在注册中断号为irq的中断服务程序时,系统会根据注册参数封装相应的irqaction结构体。并把中断号为irq的irqaction结构体写入irq_desc [irq]->action。这样就把设备的中断请求号与该设备的中断服务例程irqaction联系在一起了。当CPU接收到中断请求后,就可以根据中断号通过irq_desc []找到该设备的中断服务程序。

因篇幅问题不能全部显示,请点此查看更多更全内容