S3C44B0的向量和非向量中断和的详细源码分析

来源:互联网 发布:OVI浏览器java 编辑:程序博客网 时间:2024/06/06 01:20

S3C44B0的向量中断和非向量中断模式的详细源码分析

 

1)向量中断

    中讲到当发生IRQ中断时,中断控制器会在数据总线上加载分支指令跳到相应中断源的向量地址,即一级中断向量表中对应的中断向量入口地址。

 

 

ldr pc,=HandlerEINT0    ;   0x20

ldr pc,=HandlerEINT1

……

ldr pc,=HandlerTIMER0   ;   0x60

ldr pc,=HandlerTIMER1

……

ldr pc,=HandlerADC      ;   0xb4

……

 

由上述代码可知,程序会跳转到HandlerXXX中,定义如下:

 

 

HandlerFIQ          HANDLER HandleFIQ

HandlerIRQ          HANDLER HandleIRQ

HandlerUndef        HANDLER HandleUndef

HandlerSWI          HANDLER HandleSWI

HandlerDabort       HANDLER HandleDabort

HandlerPabort       HANDLER HandlePabort

HandlerADC          HANDLER HandleADC

HandlerRTC          HANDLER HandleRTC

……

HandlerEINT1          HANDLER HandleEINT1

HandlerEINT0          HANDLER HandleEINT0

 

HandlerXXX   HANDLER HandleXXX为一个汇编宏,定义如下:

 

MACRO

$HandlerLabel       HANDLER $HandleLabel

$HandlerLabel

 

;由于ADS仅支持FD(满递减)型堆栈

     sub     sp,sp,#4   ;将堆栈退一个字用于保存下面用到的R0

     stmfd   sp!,{r0}   ;R0压入堆栈

     ldr     r0,=$HandleLabel   ;HandleLabel的地址赋给R0

     ldr     r0,[r0]   ;HandleLabel的地址指向的内容(实际的执行地址)赋给R0

     str     r0,[sp,#4] ;将对应的中断函数首地址入栈保护

     ldmfd   sp!,{r0,pc} ;将中断函数的首地址出栈,放入PC

     MEND

 

2)非向量中断

 

前面讲过,一旦产生IRQ中断,微控制器会切换到IRQ模式,并且跳转到一级向量表0x0000018地址处执行程序;而FIQ则跳到0x000001C地址处。即 

 

ENTRY         

  

b ResetHandler       ;复位异常   0x0000 0000
     ……
    b HandlerIRQ       ;
外部中断   0x0000 0018
    b HandlerFIQ       ;
快速中断   0x0000 001C
     ……

 

 

然后跳转到宏HandlerIRQ    HANDLER HandleIRQ 或 HandlerFIQ HANDLER HandleFIQ

 

由以下代码可知,HandleIRQ最终对应的是IsrIRQ地址标号。

;****************************************************

;*   Setup IRQ handler                              

;****************************************************

    ldr      r0,=HandleIRQ        ;This routine is needed

ldr      r1,=IsrIRQ             str      r1,[r0]

  

上述代码位于ResetHandler为标号的汇编代码段内,板子上电或复位后,都要从位于0x0执行b ResetHandler 的指令跳转到ResetHandler为标号的汇编代码段处执行,也就将HandleIRQ初始化为IsrIRQIsrIRQ代码段如下:

 

 

IsrIRQ ;using I_ISPR register.

    sub      sp,sp,#4       ;reserved for PC

    stmfd   sp!,{r8-r9}

    ;IMPORTANT CAUTION

    ;if I_ISPC is not used properly, I_ISPR can be 0 in this routine.

    ldr      r9,=I_ISPR

ldr      r9,[r9]

 

    cmp     r9, #0x0 ;If the IDLE mode work-around is used, r9 may be 0 sometimes.

    beq     %F2 ;相等就向后搜索跳转标号2.

    mov      r8,#0x0

0

    movs    r9,r9,lsr #1

    bcs      %F1 ;>= 就向后搜索跳转标号1.

    add      r8,r8,#4

    b        %B0 ;向前搜索跳转标号0.

1

    ldr      r9,=HandleADC

    add      r9,r9,r8 ;HandleADCr9)为基址,r8对应所发生中断源的偏移量

    ldr      r9,[r9]   ;结果为二级中断向量表中对应中断标号地址HandleXXX

    str      r9,[sp,#8]

    ldmfd   sp!,{r8-r9,pc}

2

    ldmfd   sp!,{r8-r9}

    add     sp,sp,#4

    subs    pc,lr,#4

 

     上述这段程序就是用来处理非向量中断(比向量中断方式多执行的代码段),具体判断I_ISPR中各位是否置1 置1表示目前此中断等待响应(每次只能有一位置1),从最高优先级中断位开始判断,检测到等待服务,中断就将pc置为中断服务函数首地址。这段代码就是向量中断和非向量中断区别的根本所在,向量中断利用硬件计算,直接通过一级中断向量表中0X20-0XC0中断向量入口地址跳转到二级中断向量表中对应的HandleXXX地址,省掉了这段代码的操作。

0 0
原创粉丝点击