原创 ARM的中断分析

2008-12-1 20:33 6081 9 8 分类: 模拟

      对于学习ARM的朋友来说,中断处理是一块硬骨头,尤其是中断向量表以及中断的跳转。下面主要对中断向量表的建立问题及重映射问题进行探讨。近来做一些东西用到中断时,总会出现一些问题。


      各种Bootloader的初始化相关代码摘要,首先来看下面的程序:
         ^ DRAM_BASE                     //DRAM的基地址
HandleReset # 4                              // 空留4个单元
HandleUndef # 4
HandleSwi    # 4
HandlePrefetch # 4                       //用于填充地址的
HandleAbort # 4
HandleReserv # 4
HandleIrq    # 4
HandleFiq # 4
  注: 这里的^是RMAP,#是FIELD,分配的意思
  就是在SDARM的BANK0开始的地方定义了一个中断向量表,相当于0地址的FLASH。空留单元用于存放中断程序的入口地址。

ExceptionHandlerTable                             //实际的映射地址
     DCD UserCodeArea
     DCD SystemUndefinedHandler
     DCD SystemSwiHandler
     DCD SystemPrefetchHandler
     DCD SystemAbortHandler
     DCD SystemReserv
     DCD SystemIrqHandler
     DCD SystemFiqHandler
        这个表中存放的是汇编程序中中断处理函数的入口地址,每一项对应一个中断函数。这次的跳转后就进入了C服务程序。 


        从初始化程序的开始处来看:(各种Bootloader的初始化代码)
  AREA Init, CODE, READONLY     //相当于init进程
  ENTRY                                               //入口

     B Reset_Handler
     B Undefined_Handler                      //无条件的跳转
     B SWI_Handler
     B Prefetch_Handler
     B Abort_Handler
     NOP  Reserved vector
     B IRQ_Handler
     B FIQ_Handler

    
FIQ_Handler
     SUB sp, sp, #4          
     STMFD sp!, {r0}       FD满递减堆栈  执行寄存器压栈操作.
LDR r0, =HandleFiq    汇编里的处理函数地址,然后跳到C中,在DRAM。
LDR r0, [r0]          中断向量地址给R0.
     STR r0, [sp, #4]         中断向量地址给PC
     LDMFD sp!, {r0, pc}


   稍微解释一下:
  首先执行了压栈,然后给出了中断入口地址.这个HandleFiq就是我们前面的在DRAM中建立的中断向量其中一个的地址。
在HandleFiq开始的四个字节中,放着汇编中断处理函数的入口地址。

       那么汇编中断处理函数的地址是如何放到DRAM中断向量表里的呢?

  上面的第一个表就起作用了。看下面这段程序:
EXCEPTION_VECTOR_TABLE_SETUP
     LDR r0, =HandleReset 
     LDR r1, =ExceptionHandlerTable
     MOV r2, #8 
    
ExceptLoop
     LDR r3, [r1], #4
     STR r3, [r0], #4
     SUBS r2, r2, #1       //填充8个地址        
     BNE ExceptLoop   //从表里取出来给了HandleReset后面的空间
       这一段把ExceptionHandlerTable里的中断处理函数的地址拷给了SDRAM里的中断向量表。这样两者就联系起来了。
     在执行程序开始的跳转之后就自然跳到了*****Handler.真正的处理函数如下:

       它实际上只调用了C语言的中断处理函数,其他什么也没做。
SystemFiqHandler
     IMPORT ISR_FiqHandler
     STMFD sp!, {r0-r7, lr}
     BL ISR_FiqHandler                    //真正的中断处理服务函数
     LDMFD sp!, {r0-r7, lr}
     SUBS pc, lr, #4

        它实际上只调用了C语言的中断处理函数,其他什么也没做。写中断处理服务程序其实就只写C中相应的处理部分就好了。



void ISR_FiqHandler(void)
{
       IntOffSet = (U32)INTOFFSET;
       (IntOffSet>>2)
       (*InterruptHandlers[IntOffSet>>2])(); // Call interrupt service routine
}


      其实就是将中断向量表重映射,以提高中断的响应速度。代码在SDRAM的运行速度要比在FLASH中运行速度快。
 

文章评论0条评论)

登录后参与讨论
我要评论
0
9
关闭 站长推荐上一条 /2 下一条