ARMLinux中断处理过程分析_第1页
ARMLinux中断处理过程分析_第2页
ARMLinux中断处理过程分析_第3页
ARMLinux中断处理过程分析_第4页
ARMLinux中断处理过程分析_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、ARM Linux中断处理过程分析(1) 原创 2007-06-09 21:43:26 发表者: jimmy_lee   Author:    jimmy.liDate:      2007-06-09 在我的上一篇文章(ARM linux的中断向量表初始化分析)中已经分析了ARM Linux中断向量表是如何建立的,在这篇文章中,我将分析一下Linux内核的ARM体系下,中断处理是如何响应的一个过程。在ARM体系架构下,定义了7种异常,每一种异常都有自己的入口地址,即异常向量

2、表,当异常发生时,处理器会自动跳转到相应的入口处执行。对于ARMv4及其以上的版本,异常向量表的起始位置由协处理器15(cp15)的控制寄存器(c1)里的V位(bit13)有关,当V=时,异常向量表的起始位置在0x00000000,而当V=时,异常向量表就起始于0xffff0000位置。在上一篇文章中,我们已经分析知道异常向量表放置于0xffff0000起始位置,而IRQ中断处理入口地址为:0xffff0018,所以当发生一IRQ中断异常时,处理器会自动跳转到0xffff0018这个虚拟地址上。0xffff0018这个虚拟地址上是一条跳转指令:b_real_stubs_start + (vec

3、tor_IRQ - _stubs_start)   所以对于IRQ的处理就是从vector_IRQ标号处开始的。在linux内核中相应代码如下:1 vector_IRQ:2 save mode specific registers34ldrr13, .LCsirq5sublr, lr, #46strlr, r13 save lr_IRQ7mrslr, spsr8strlr, r13, #4 save spsr_IRQ910 now branch to the relevent MODE handling routine1112mrsr13, cpsr13bicr1

4、3, r13, #MODE_MASK14orrr13, r13, #I_BIT | MODE_SVC15msrspsr_c, r13 switch to SVC_32 mode1617andlr, lr, #1518ldrlr, pc, lr, lsl #219movspc, lr Changes mode and branches2021.LCtab_irq:.word_irq_usr 0 (USR_26 / USR_32)22.word_irq_invalid 1 (FIQ_26 / FIQ_32)23.word_irq_invalid 2 (IRQ_26 / IRQ_32)24.word

5、_irq_svc 3 (SVC_26 / SVC_32)25.word_irq_invalid 426.word_irq_invalid 527.word_irq_invalid 628.word_irq_invalid 729.word_irq_invalid 830.word_irq_invalid 931.word_irq_invalid a32.word_irq_invalid b33.word_irq_invalid c34.word_irq_invalid d35.word_irq_invalid e36.word_irq_invalid f首先,行48是保存进入IRQ模式之前的p

6、c指针(在lr_IRQ)和CPSR(在SPSR_IRQ)到.LCsirq所指向的地址中。.LCsirq相关代码也是位于entry-armv.S中:.LCsirq:.word_temp_irq_temp_irq:.word0 saved lr_irq.word0 saved spsr_irq.word-1 old_r0在这里补充一下ARM对于异常的处理过程,可以用下面的一段伪码来表示:r14_<异常模式> = return linkSPSR_<异常模式> = CPSRCPSR4:0 = 异常模式编码CPSR5 = 0;运行于ARM状态If<异常模式> = Re

7、set or FIQ then;当复位或响应FIQ异常时,禁止新的fiq和irq异常CPSR6 = 1;CPSR7 = 1;else if<异常模式> = IRQ then;当响应IRQ异常时,禁止新的IRQ异常CPSR7 = 1;PC = 异常向量地址所以在运行到行48之前时,lr为进入IRQ之前的pc指针,spsr为进入IRQ之前的cpsr指针。接着,行1215更新spsr寄存器为SVR模式,并关闭IRQ,为从IRQ模式切换到SVR模式做准备。行17,根据进入IRQ模式之前的psr(因为在行7,lr已经被置以spsr_irq),获取之前的处理器模式(psr &0b111

8、1)。行18,根据获取的进入IRQ之前的处理器模式,查找相应的跳转入口(_irq_usr对应于之前是USR模式,_irq_svc对于之前是SVC模式,对于其它模式均跳转到_irq_invalid,在linux系统中处理器进入IRQ之前只有usr和svc两种模式,其它模式均不允许开启IRQ)。此行实际上是:lr = pc+lr<<2,pc指向当前指令地址值加8个字节的地址,即pc指向当前指令的下两条指令的地址,所以pc在此时指向的是.LCtab_irq地址。行19,跳转到相应入口,并且ARM寄存器r13和r14则切换到了SVC模式下的寄存器。ARM Linux中断处理过程分析(2)

9、原创 2007-06-10 20:51:14 发表者: jimmy_lee   Author:    jimmy.liDate:      2007-06-10- 续前文,让我们先分析进入IRQ之前的处理器模式为SVC时的情况,程序会跳转到_irq_svc继续运行,其相应代码如下:20_irq_svc:subsp, sp, #S_FRAME_SIZE21stmiasp, r0 - r12 save r0 - r1222ldrr7, .LCirq23addr5, sp, #S_

10、FRAME_SIZE24ldmiar7, r7 - r925addr4, sp, #S_SP26movr6, lr27stmiar4, r5, r6, r7, r8, r9 save sp_SVC, lr_SVC, pc, cpsr, old_ro28 1:get_irqnr_and_base r0, r6, r5, lr29movner1, sp3031 routine called with r0 = irq number, r1 = struct pt_regs *3233adrsvcne, lr, 1b34bneasm_do_IRQ35ldrr0, sp, #S_PSR irqs ar

11、e already disabled36msrspsr, r037ldmiasp, r0 - pc load r0 - pc, cpsr行2027:保存进入中断之前的寄存器,把它们放在堆栈中。其中#S_FRAME_SIZE和#S_SP的定义在arch/arm/kernel/entry-header.S中:#ifdef CONFIG_CPU_32#define S_FRAME_SIZE72#define S_OLD_R068#define S_PSR64#else#define S_FRAME_SIZE68#define S_OLD_R064#define S_PSR60#endif#defin

12、e S_PC60#define S_LR56#define S_SP52#define S_IP48#define S_FP44#define S_R1040#define S_R936#define S_R832#define S_R728#define S_R624#define S_R520#define S_R416#define S_R312#define S_R28#define S_R14#define S_R00#define S_OFF8.LCirq在entry-armv.S中是这样定义的:.LCirq:.word_temp_irq这与行4处的.LCsirq定义是一样的,可见

13、整个过程利用_temp_irq作为中转,把进入中断之前的CPSR和PC(中断处理结束后要返回的地址)放入堆栈,以便中断返回时直接恢复。行2027执行的结果是:r5->old_r0cpsrpclr_svcr4->sp_svcr12r11r1sp->r0行28的get_irqnr_and_base,它是一个宏定义,作用是获取中断号(irq number),它将被保存在r0中。另外,get_irqnr_and_base还会改变cpsr寄存器中的Z位,如果确实找到了发生的中断号,则Z位被清除,否则Z位被置位。get_irqnr_and_base这个宏定义的实现是依赖具体的硬件的,对于

14、pxa270 cpu,其实现如下:.macroget_irqnr_and_base, irqnr, irqstat, base, tmpmovbase, #io_p2v(0x40000000) IIR Ctl = 0x40d00000addbase, base, #0x00d00000ldrirqstat, base, #0 ICIPldrirqnr, base, #4 ICMRandsirqstat, irqstat, irqnrbeq1001f/* 没找到中断,跳转*/rsbirqnr, irqstat, #0andirqstat, irqstat, irqnrclzirqnr, irqs

15、tatrsbirqnr, irqnr, #(31 - PXA_IRQ_SKIP)#ifdef CONFIG_CPU_BULVERDE b 1002f#endif1001:#ifdef CONFIG_CPU_BULVERDE add base, base, #0x9c ldr irqstat, base, #0 ICIP2 ldr irqnr, base, #4 ICMR2 ands irqstat, irqstat, irqnr beq 1002f rsb irqnr, irqstat, #0 and irqstat, irqstat, irqnr clz irqnr, irqstat rsb

16、 irqnr, irqnr, #31 add irqnr, irqnr, #(32 - PXA_IRQ_SKIP)1002:#endif.endm关于这段get_irqnr_and_base的实现代码比较简单,这里不作解释。行2934:如果在行28找到中断号,Z=0,则这些指令的条件都满足,则执行把sp指针赋予r1;标号1(行28)的相对地址赋予lr,以便处理完该中断后,再查询是否还有未处理的中断号;跳转到asm_do_IRQ处理相应中断。asm_do_IRQ是用C语言编码的函数,它在arch/arm/kernel/irq.c中被定义,其原型为:asmlinkage void asm_do_I

17、RQ(int irq, struct pt_regs *regs);这里牵扯到一个问题就是,在汇编中如何调用语言的函数,参数是如何传递的?为了让ARM的汇编代码可与代码一起连接,在编写ARM汇编时,应遵循一套标准,这就是ATPCS(The ARM-Thumb Procedure Call Standard)。ATPCS定义r0r3为参数传递和结果返回寄存器;若参数超过4个字型(32bit),则使用堆栈进行传递;头4个参数依次存于r0.r3,大于4个的后续字型参数通过栈传送。关于栈的使用,是使用满递减的堆栈标准,也就是栈是从高地址向低地址方向增长的(递减堆栈),栈指针寄存器指向的数据是最后压入堆栈内的有效数据(满堆栈)。所以在跳转到asm_do_IRQ函数之前,r0就必须设置为中断号(行2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论