armlinux的中断系统.docx

上传人:b****5 文档编号:14325545 上传时间:2023-06-22 格式:DOCX 页数:12 大小:21.46KB
下载 相关 举报
armlinux的中断系统.docx_第1页
第1页 / 共12页
armlinux的中断系统.docx_第2页
第2页 / 共12页
armlinux的中断系统.docx_第3页
第3页 / 共12页
armlinux的中断系统.docx_第4页
第4页 / 共12页
armlinux的中断系统.docx_第5页
第5页 / 共12页
armlinux的中断系统.docx_第6页
第6页 / 共12页
armlinux的中断系统.docx_第7页
第7页 / 共12页
armlinux的中断系统.docx_第8页
第8页 / 共12页
armlinux的中断系统.docx_第9页
第9页 / 共12页
armlinux的中断系统.docx_第10页
第10页 / 共12页
armlinux的中断系统.docx_第11页
第11页 / 共12页
armlinux的中断系统.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

armlinux的中断系统.docx

《armlinux的中断系统.docx》由会员分享,可在线阅读,更多相关《armlinux的中断系统.docx(12页珍藏版)》请在冰点文库上搜索。

armlinux的中断系统.docx

armlinux的中断系统

浅析armlinux中断irq分发例程的派发流程之根基文章来源应用程序运行在user模式,对应arm的cpsr&15的值为0,而内核代码运行在svc模式,对应arm的cpsr&15的值为3,所以,如果应用程序在运行期间,即usr模式下,arm发生了irq中断,那么中断处理代码得知后会调用__irq_usr分发处理例程处理irq中断,如果在系统调用syscall之类使程序运行在内核空间执行内核程序的时候,即svc模式下,arm发生了irq中断,那么中断处理代码得知后会调用__irq_svc分发处理例程处理irq中断,中断程序是怎么识别svc和usr模式,进而派发相应的__irq_usr和__irq_svc分发例程的呢,来看看代码部分:

..LCvswi:

    .word    :

    .word    :

    .word    :

    .word    __temp_abt__stubs_end:

        .equ    __real_stubs_start, .LCvectors + :

    swi    SYS_ERROR0        b    __real_stubs_start + (vector_undefinstr - __stubs_start)        ldr    pc, __real_stubs_start + (.LCvswi - __stubs_start)        b    __real_stubs_start + (vector_prefetch - __stubs_start)        b    __real_stubs_start + (vector_data - __stubs_start)        b    __real_stubs_start + (vector_addrexcptn - __stubs_start)..vector_IRQ:

    @        @savemodespecificregisters        @        ldr    r13, .LCsirq    ord__irq_usr域和.word__irq_svc域        ldr    lr, [pc, lr, lsl #2]ord    __irq_usr            @0 (USR_26 / USR_32)ord    __irq_invalid            @1 (FIQ_26 / FIQ_32)        .word    __irq_invalid            @2 (IRQ_26 / IRQ_32)        .word    __irq_svc                @3 (SVC_26 / SVC_32)ord    __irq_invalid            @4         .word    __irq_invalid            @5        .word    __irq_invalid            @6        .word    __irq_invalid            @7        .word    __irq_invalid            @8        .word    __irq_invalid            @9        .word    __irq_invalid            @a        .word    __irq_invalid            @b        .word    __irq_invalid            @c        .word    __irq_invalid            @d        .word    __irq_invalid            @e        .word    __irq_invalid            @f....LCvswi:

    .word    :

    .word    :

    .word    :

    .word    __temp_abt

 

ARMLINUX的中断系统

0 概述

本文描述ARMPXA255系统中断部分的实现原理和代码分析。

1ARM系统异常中断介绍

 异常中断种类

ARM支持7类异常中断,所以中断向量表设8个条目,每个条目4字节,共32字节。

 

异常名称

中断向量

异常中断模式

优先级

复位

0x0

特权模式

1

未定义的指令

0x4

未定义指令中止模式

6

软件中断

0x8

特权模式

6

指令预取中止

0x0c

中止模式

5

数据访问中止

0x10

中止模式

2

保留

0x14

 

 

外部中断请求IRQ

0x18

IRQ模式

4

快速中断请求FIQ

0x1c

FIQ模式

3

 

GPIO引脚

PXA255拥有81个GPIO引脚。

另外各个外围模块有自己的中断线。

ThePXA255processorenablesandcontrolsits81GPIOpinsthroughtheuseof27registerswhichconfigurethepindirection(inputoroutput),pinfunction,pinstate(outputsonly),pinleveldetection(inputsonly),andselectionofalternatefunctions.

由InterruptControllerPendingRegister(ICPR)寄存器可知:

前8个中断保留,其它的都分配相应的外围模块。

且其中8和9是反映GPIO0/1的。

IS10用来指示GPIO2-80是否有中断触发

这样,ARMlinux的IRQ中断数组structirqdescirq_desc[NR_IRQS]中NR_IRQS应该为:

#define    NR_IRQS              (IRQ_GPIO(80)+1)  cvectors处给出了ARM启动时的中断向量表内容。

系统通过R1-R7,ip,lr等8个寄存器做中转,把向量表转存到r0(是传入的参数,即向量表的基址)对应的地址中。

另外,在向量表基址后面512字节处,拷贝了向量表具体的处理代码。

.LCvectors:

     swi  SYS_ERROR0

              b     __real_stubs_start+(vector_undefinstr-__stubs_start)

              ldr   pc,__real_stubs_start+(.LCvswi-__stubs_start)

              b     __real_stubs_start+(vector_prefetch-__stubs_start)

              b     __real_stubs_start+(vector_data-__stubs_start)

              b     __real_stubs_start+(vector_addrexcptn-__stubs_start)

              b     __real_stubs_start+(vector_IRQ-__stubs_start)

              b     __real_stubs_start+(vector_FIQ-__stubs_start)

ENTRY(__trap_init)

              stmfd      sp!

{r4-r6,lr}

 

              adr   r1,.LCvectors               @setupthevectors

              ldmia      r1,{r1,r2,r3,r4,r5,r6,ip,lr}

              stmia       r0,{r1,r2,r3,r4,r5,r6,ip,lr}

 

              add  r2,r0,#0x200

              adr   r0,__stubs_start            @copystubsto0x200

              adr   r1,__stubs_end

1:

           ldr   r3,[r0],#4

              str    r3,[r2],#4

              cmp r0,r1

              blt   1b

              LOADREGS(fd,sp!

{r4-r6,pc})

 

  IRQ中断处理流程

  区分系统模式

下面我们以IRQ为例,分析中断处理的过程。

根据向量表,其跳转到:

vector_IRQ

把lr值减4后保存到.Lcsirq位置。

再保存spsr的值到.Lcsirq后4字节的位置。

再通过设置spsr_c切换系统到特权模式。

最后一步就是跳转到优先级最高的中断对应的处理函数。

这里要解释一下,

and  lr,lr,#15   取出lr(实际是spsr)的低4位。

即M0-M3,也就是原来系统所处的处理器模式。

ldr  lr,[pc,lr,lsl#2] 将lr的值乘4后加到PC,再将其所指地址赋给lr。

注意,这里的pc值为当前指针,其加上模式值后,就会指向.LCtab_irq:

表中的对应项。

应该只有用户模式和特权模式会产生IRQ中断,所以就只有两个有效的对应指针:

__irq_usr和__irq_svc。

 

vector_IRQ:

    @

              @savemodespecificregisters

              @

              ldr   r13,.LCsirq

              sub  lr,lr,#4

              str    lr,[r13]                 @savelr_IRQ

              mrs  lr,spsr

              str    lr,[r13,#4]                  @savespsr_IRQ

              @

              @nowbranchtothereleventMODEhandlingroutine

              @

              mov r13,#I_BIT|MODE_SVC

              msr  spsr_c,r13                    @switchtoSVC_32mode

 

              and  lr,lr,#15

              ldr   lr,[pc,lr,lsl#2]

              movs       pc,lr                            @Changesmodeandbranches

.LCtab_irq:

     .word      __irq_usr               @  0  (USR_26/USR_32)

              .word      __irq_invalid                @  1  (FIQ_26/FIQ_32)

              .word      __irq_invalid                @  2  (IRQ_26/IRQ_32)

              .word      __irq_svc                     @  3  (SVC_26/SVC_32)

              .word      __irq_invalid                @  4

              .word      __irq_invalid                @  5

              .word      __irq_invalid                @  6

 

 

.LCsirq:

   .word      __temp_irq

__temp_irq:

    .word      0                          @savedlr_irq

              .word      0                          @savedspsr_irq

              .word      -1                         @old_r0

 

 用户模式下的IRQ处理

上一小节根据IRQ发生时系统模式的不同跳转到不同的处理函数。

处理流程如下:

首先从堆栈中留出S_FRAME_SIZE大小的空间,保存了r0-r12.

再把用户模式下的sp,lr值保存起来。

(note:

表面位置在下一句之后,但保存位置却更靠栈顶)。

再把原来保存在.Lcirq中的lr_irq,spsr_irq,old_r0保存到堆栈中。

 

get_irqnr_and_base是一个宏,负责从中断的寄存器中读取ICIP,ICMR值,再判断是否中断,判断方法是:

首先看是否存在中断,没有返回0。

若系统有中断,判断ICIP的8-15位,若在低位中找到中断,不再查找高位的中断标志。

其中,r0返回最小的中断号,r6等于ICIP&ICMR。

R5是ICMR寄存器的虚拟地址。

Lr没有使用。

由此可以得到:

中断号越小,中断程序越优先执行。

  然后,通过对lr的赋值,目的是实现中断的串行化处理。

  然后,针对找出的中断号,调用do_IRQ处理函数。

get_current_tasktsk 把sp的低13清0。

 tsk .req       r9    @currenttask

 

 

__irq_usr:

       sub  sp,sp,#S_FRAME_SIZE   Cirq

              add  r8,sp,#S_PC

              ldmia      r4,{r5-r7}                 @getsavedPC,SPSR

              stmia       r8,{r5-r7}                 @savepc,psr,old_r0

              stmdb      r8,{sp,lr}^

              alignment_trapr4,r7,__temp_irq

              zero_fp

1:

           get_irqnr_and_baser0,r6,r5,lr

              movne     r1,sp  @将当前堆栈指针赋给r1

              adrsvc     ne,lr,1b@通过设置lr,使实现了对中断的串行处理

              @

              @routinecalledwithr0=irqnumber,r1=structpt_regs*

              @

              bne  do_IRQ

              mov why,#0

              get_current_tasktsk

              b     ret_to_user

 

do_irq处理

主要的处理流程为:

desc=irq_desc+irq;    vector_FIQ:

    disable_fiq

              subs pc,lr,#4

 

PXA255开发板中断的初始化

start_kernel()函数的初始化过程中,调用init_IRQ()进行开发板具体中断的初始化。

{   

for(irq=0;irq

              irq_desc[irq].probe_ok=0;

              irq_desc[irq].valid    =0;

              irq_desc[irq].noautoenable=0;

              irq_desc[irq].mask_ack=dummy_mask_unmask_irq;

              irq_desc[irq].mask     =dummy_mask_unmask_irq;

              irq_desc[irq].unmask   =dummy_mask_unmask_irq;

       }

 

       init_arch_irq();

       init_dma();

其中关键函数为:

init_arch_irq();

在/arch/arm/函数中有定义:

init_arch_irq=mdesc->init_irq;

而mdesc->init_irq就是在/match-pxa/中定义的。

staticvoid__initxhyper255_init_irq(void)

{

       pxa_init_irq();

       set_GPIO_IRQ_edge(0,GPIO_RISING_EDGE);  /*EthernetInterrupt*/

#ifdefCONFIG_ARCH_XHYPER255B

       set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(IRQ_GPIO_ADS7843),GPIO_FALLING_EDGE);/*ADS7843touchcontroller*/

       set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(IRQ_GPIO_EZHOST),  GPIO_RISING_EDGE);  /*EZ-HostUSBHOSTcontroller*/

#elifdefined(CONFIG_ARCH_XHYPER255A)

       set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(IRQ_GPIO_ADS7843),GPIO_FALLING_EDGE);/*ADS7843touchcontroller*/

#endif

}

通过调用pxa_init_irq()完成PXA255的中断初始化。

包括:

设置相关寄存器:

       /*disableallIRQs*/

       ICMR=0;          */

 

       for(irq=IRQ_GPIO0;irq<=IRQ_GPIO1;irq++){

              irq_desc[irq].valid  =0;

              irq_desc[irq].probe_ok   =1;

              irq_desc[irq].mask_ack  =pxa_mask_and_ack_GPIO_0_1_irq;

              irq_desc[irq].mask  =pxa_mask_GPIO_0_1_irq;

              irq_desc[irq].unmask     =pxa_unmask_GPIO_0_1_irq;

       }

 

       for(irq=IRQ_GPIO_2_80;irq<=IRQ_RTCAlrm;irq++){

              irq_desc[irq].valid  =1;

              irq_desc[irq].probe_ok   =0;

              irq_desc[irq].mask_ack  =pxa_mask_irq;

              irq_desc[irq].mask  =pxa_mask_irq;

              irq_desc[irq].unmask     =pxa_unmask_irq;

       }

       /*Thosearereserved*/

       irq_desc[PXA_IRQ(15)].valid=0;

       irq_desc[PXA_IRQ(16)].valid=0;

 

       for(irq=IRQ_GPIO

(2);irq<=IRQ_GPIO(80);irq++){

              irq_desc[irq].valid  =0;

              irq_desc[irq].probe_ok   =1;

              irq_desc[irq].mask_ack  =pxa_mask_and_ack_GPIO_2_80_irq;

              irq_desc[irq].mask  =pxa_mask_GPIO_2_80_irq;

              irq_desc[irq].unmask     =pxa_unmask_GPIO_2_80_irq;

       }

设置ARM的ICPR的第10位,用来指示GPIO2-80引脚是否有中断发生。

GPIO[80:

2]EdgeDetectInterruptPending

0–InterruptNOTpendingduetoedgedetectonone(ormore)ofGPIO[80:

2].

1–Interruptpendingduetoedgedetectonone(ormore)ofGPIO[80:

2].

注意,GPIO2-GPIO80这些引脚是没有直接接中断线的,它们是否有边沿触发,完全通过ICPR的第10来判断。

当发现GPIO2-80引脚有中断时,首先触发的是ICPR中的第10位中断,该中断通过调用setu

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2