ARM+Linux中断系统详细分析
Linux中断系统到底是否支持优先级,可否嵌套,中断号又是怎么来确定的,中断产生时又是如何一步步执行到中断处理函数的。为了彻底搞懂Linux中断系统,我决定从最原始材料出发,一探究竟。(s3c2440+linux2.6.21)
先来看看ARM的硬件执行流程
异常是ARM处理器模式分类,ARM有七种运行模式USR,SYS,SVC,IRQ,FIQ,UND,ABT
五种异常模式:SVC,IRQ,FIQ,UND,ABT
中断模式是ARM异常模式之一(IRQ模式,FIQ模式),是一种异步事件,如外部按键产生中断,内部定时器产生中断,通信数据口数据收发产生中断等。
1.当一个异常产生时,以FIQ为例,CPU切入FIQ模式时,
①将原来执行程序的下一条指令地址保存到LR中,就是将R14保存到R14_fiq里面。
②拷贝CPSR到SPSR_fiq。
③改变CPSR模式位的值,改到FIQ模式。
④改变PC值,将其指向相应的异常处理向量表。
离开异常处理的时候,
①将LR(R14_fiq)赋给PC。
②将SPSR(SPSR_fiq)拷贝到CPSR。
③清除中断禁止标志(如果开始时置位了)。
ARM一般在某个固定地址中有一个异常向量表,比如0x0
当一个外部IRQ中断产生时
①处理器切换到IRQ模式
②PC跳到0x18处运行,因为这是IRQ的中断入口。
③通过0x18:LDR PC, IRQ_ADDR,跳转到相应的中断服务程序。这个中断服务程序就要确定中断源,每个中断源会有自己独立的中断服务程序。
④得到中断源,然后执行相应中断服务程序
⑤清除中断标志,返回
这就是一个外部中断完整的执行流程了,下面以具体寄存器来更具体的了解ARM的中断机制。
假设ARM核有两个中断引脚,一根是irq pin,一根是fiq pin,正常情况下,ARM核只是机械地随着PC指示去执行,当CPSR中的I位和F位都为1时,IRQ和FIQ都处于禁止状态,这时候无论发什么信号,ARM都不会理睬。
当I位或F位为0时,irq pin有中断信号过来时,ARM当前工作就会被打断,切换到IRQ模式,并且跳转到异常向量表的中断入口0x18,SRCPND中相应位置1,经过检查中断优先级寄存器以及屏蔽寄存器,确定中断源,INTPND相应位置1(经过仲裁,只有一位置1),这过程由ARM自动完成。0x18存放的是总的中断处理函数,在这个函数里,可以建立一个二级中断向量表,先清除SRCPND相应位,然后根据中断源执行相应中断服务程序,清除INTPND,返回。
及时清除中断Pending寄存器的标志位是为了避免两个问题:①发生中断返回后,立即又被中断,不断的重复响应②丢失中断处理过程中发生的中断,返回后不响应。
在某个IRQ中断程序执行过程中,有另外一个外部IRQ中断产生,会将SRCPND相应位置1,等该中断服务执行完,经过仲裁决定下一个要响应的中断。但是假如当产生的是FIQ,则保存当前IRQ的现场,嵌套响应FIQ,FIQ服务程序执行完,再继续执行IRQ服务。那么当一个FIQ正在服务,产生另外一个FIQ,会怎样呢,答案是不会被打断,跟IRQ一样等当前中断服务完成,再仲裁剩余需要相应的中断。
所以得出这样的结论:
①关于中断嵌套:IRQ模式只能被FIQ模式打断,FIQ模式下谁也打不断。
②关于优先级:ARM核对中断优先级,有明确的可编程管理。
下面再来看看Linux对ARM是怎么处理的,记住一个前提:Linux对ARM的硬件特性可以取舍,但不可更改。
1.建立异常向量表:
系统从arch/arm/kernel/head.S的ENTRY(stext)开始执行,__lookup_processor_type检查处理器ID,__lookup_machine_type检查机器ID,__create_page_tables创建页表,启动MMU,然后由arch/arm/kernel/head_common.S跳到start_kernel()->trap_init()
点击(此处)折叠或打开
- void __init trap_init(void)
- {
- 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);
- memcpy((void*)vectors+0x1000-kuser_sz,__kuser_helper_start,kuser_sz);
- …
- }
- #define CONFIG_VECTORS_BASE 0xffff0000
CONFIG_VECTORS_BASE在autoconf.h定义,在ARMV4及V4T以后的大部分处理器中,中断向量表的位置可以有两个位置:一个是0,另一个是0xffff0000。可以通过CP15协处理器c1寄存器中V位(bit[13])控制。V和中断向量表的对应关系如下:
V=0~0x00000000~0x0000001C
V=1~0xffff0000~0xffff001C
__vectors_end至__vectors_start之间为异常向量表,
ARMLinux中断系 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)