二、ARM 的异常处理


    这部分比较不好理解。
    当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。当异常中断处理程序执行完成后,程序返回到发生中断指令的下条指令处执行。在进入异常中断处理程序时,要保存被中断程序的执行现场,从异常中断处理程序退出时,要恢复被中断程序的执行现场。
1、引起异常的原因
    (1)、指令执行引起的异常
    软件中断、未定义指令(包括所要求的协处理器不存在是的协处理器指令)、预取址中止(存储器故障)、数据中止。
    (2)、外部产生的中断
    复位、FIQ、IRQ。
2、ARM中异常中断的种类
    (1)、复位(RESET)
    a、当处理器复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行,包括系统加电和系统复位。
    b、通过设置PC跳转到复位中断向量处执行称为软复位。
    (2)、未定义的指令
    当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令异常中断,可以通过改异常中断机制仿真浮点向量运算。
    (3)、软件中断
    这是一个由用户定义的中断指令(SWI)。可用于用户模式下的程序调用特权操作指令。在实时操作系统中可以通过该机制实现系统功能调用。
    (4)、指令与取终止(Prefech Abort)
    如果处理器预取的指令的地址不存在,或者该地址不允许当前指令访问,当被预取的指令执行时,处理器产生指令预取终止异常中断。
    (5)、数据访问终止(DATAABORT)
    如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问终止异常中断。
    (6)、外部中断请求(IRQ)
    当处理器的外部中断请求引脚有效,而且CPSR的寄存器的I控制位被清除时,处理器产生外部中断请求异常中断。系统中个外设通过该异常中断请求处理服务。
    (7)、快速中断请求(FIQ)
    当处理器的外部快速中断请求引脚有效,而且CPSR的F控制位被清除时,处理器产生外部中断请求异常中断。
   
3、异常的响应过程
    除了复位异常外,当异常发生时,ARM处理器尽可能完成当前指令(除了复位异常)后,再去处理异常。并执行如下动作:
    (1)、将引起异常指令的下一条指令的地址保存到新模式的R14中,若异常是从ARM状态进入,LR寄存器中保存的是下一条指令的地址(当前PC+4或PC+8,与异常的类型有关);若异常是从Thumb状态进入,则在LR寄存器中保存当前PC的偏移量,这样,异常处理程序就不需要确定异常是从何种状态进入的。例如:在软件中断异常SWI,指令MOV PC,R14_svc总是返回到下一条指令,不管SWI是在ARM状态执行,还是在Thumb状
态执行。
    (2)、将CPSR的内容保存到要执行异常中断模式的SPSR中。(注意:如果通过程序修改CPSR进入异常模式,硬件将不会将CPSR保存到SPSR中)
    (3)、设置CPSR相应的位进入相应的中断模式。
    (4)、通过设置CPSR的第7位来禁止IRQ。如果异常为快速中断和复位。则还要设置CPSR的第6位来禁止快速中断。
    (5)、给PC强制赋向量地址值。
    ARM处理器内核会自动执行以上几步,程序计数器PC总是跳转到相应的固定地址。
    如果异常发生时,处理器处于Thumb状态,则当异常向量地址加载入PC时,处理器自动切换到ARM状态,则异常处理返回时,自动切换到Thumb状态,即中断处理只在ARM状态下处理。
 
4、异常中断处理返回 /**下面引用了http://www.mcu16.com/embed/arm/中的内容**/
    异常处理完毕之后,ARM微处理器会执行以下几步操作从异常返回:
    (1)、将所有修改过的用户寄存器从处理程序的保护栈中恢复。
    (2)、将SPSR复制回CPSR中,将连接寄存器LR的值减去相应的偏移量后送到PC中。
    (3)、若在进入异常处理时设置了中断禁止位,要在此清除。
    复位异常处理程序不需要返回。
 
5、程序示例分析
    下面结合Samsung公司基于ARM7TDMI内核的S3C44B0微控制器的启动代码详细说明关于异常处理中的Reset、IRQ和FIQ处理过程及实现方法,
以下代码均在Embest IDE 集成开发环境下能够编译运行并经过实际验证。
    .text
#Embest IDE集成开发环境可以通过链接脚本文件将下面的语句定位在零起始地址,系统上
#加电后CPU从此处开始执行。
ENTRY:
     b ResetHandler        /*0x00000000; for debug*/
     b HandlerUndef          /*0x00000004; handlerUndef*/
     b HandlerSWI            /*0x00000008; SWI interrupt handler*/
     b HandlerPabort         /* 0x0000000C;handlerPAbort*/
     b HandlerDabort         /*0x00000010; handlerDAbort*/
     b .                     /* handlerReserved */
     b HandlerIRQ            /* 0x00000018*/
     b HandlerFIQ            /*0x0000001C */
    上面的代码用于在出现异常时,CPU根据不同情况利用标号自动跳转到对应的异常处理程序处,分别对应于处理器的7种不同工作模式。当复位后,由零地址的跳转指令使CPU转去执行启动代码,它是用于初始化CPU内部特殊功能寄存器和外围电路以及用来为高级语言写的软件做好运行前准备的一小段汇编语言,这部分汇编代码也可以被成为嵌入式系统的Bootloader。运行完ootloader代码后,会自动跳转至利用高级语言编写的系统应用程序或是开始运行操作系统内核。而对于中断的处理在系统启动代码中对于初学者是较难理解的。
    当CPU接收到中断请求信号之后且允许CPU响应中断请求,则对于FIQ和非矢量IRQ中断CPU会根据中断控制器设定的工作模式去自动执行
0x0000001C 或0x00000018处的跳转指令。执行
    b    HandlerIRQ
#跳转到
    HandlerIRQ     HANDLER     HandleIRQ
#这个宏定义的动作是要跳转到HandleIRQ中存放的地址去运行。
#然后在复位初始化代码(ResetHandler)中会看到有:
    /* Setup IRQ handler*/
    ldr     r0,=HandleIRQ
    ldr     r1,=IsrIRQ
    str     r1,[r0]
    这里是把IsrIRQ的地址放到了HandleIRQ中。因此程序会跳转到IsrIRQ去执行。
#ARM7TDMI内核只支持FIQ和IRQ两个中断请求,当有多个中断请求信号同时有效的时#候,是利用软件的方式来完成优先级判定,然后再跳转到相应的中断服务程序。在IsrIRQ中,CPU会读取中断挂起寄存器的数值来判定中断来源和优先级。而S3C44B0中集成的中断控制器提供了一种更为快速有效的中断响应方式:矢量中断利用中断控制器的硬件方式直接提供对中断服务的快速响应:当多重中断请求信号发生时,由硬件优先级判定逻辑确定哪个中断请求将被响应,同时硬件逻辑还利用向量表中的跳转指令使CPU直接跳转到相应的中断服务程序入口出。这样在很大程度上减小了中断响应的延迟。
    那么在程序设计上,就需要我们在矢量中断表中对应的地址上放置各个中断请求对应的服务程序入口地址,如:
VECTOR_BRANCH:
    ldr pc,=HandlerEINT0    /*0x00000020*/
    ldr pc,=HandlerEINT1    /*0x00000024*/
    ldr pc,=HandlerEINT2    /*0x00000028*/
    ldr pc,=HandlerEINT3    /*0x0000002C*/
    ldr pc,=HandlerEINT4567    /*0x00000030*/
    ldr pc,=HandlerTICK    /*0x00000034 */
    b . 
    b . 
    ldr pc,=HandlerZDMA0    /*0x00000040*/
    ldr pc,=HandlerZDMA1    /*0x00000044*/
        ……
    a、中断向量表指定了个异常中断及其处理程序的对应关系。他通常存放在存储地址的低端。在ARM体系中,异常中断向量表的大小为32字节,其中每个异常中断占据4个字节大小,保留了4个字节空间。
    b、每个异常中断对应的中断向量表中的4个字节的空间中存放了一个跳转指令或者一个向PC寄存器中赋值的数据访问指令。通过这两种指令,程序将跳转到相应的异常中断处理程序处执行。
    c、当几个异常中断同时发生时,系统并不能按照一定的次序来处理这些异常中断,例如:当FIQ、IRQ和第三个其他中断同时发生,FIQ比IRQ优先级高,IRQ会忽略,直到FIQ返回到用户代码为止。

各个异常中断的中断向量地址以及中断的处理优先级
 ——————————————————————————————————————
    中断向量地址   |  异常中断类型   |   异常中断模式   |  优先级(6最低)  |
 —————————|—— ——————|—————————|———— —————|
      0x00         |   复位          |     特权模式     |       1           |
      0x04         |   未定义的指令  |     UND终止模式  |         6         |
      0x08         |   软件中断      |     特权模式     |          6        |
      0x0C         |   指令预取终止  |     终止模式     |         5         |
      0x10         |   数据访问终止  |     终止模式     |         2         |
      0x14         |   保留          |     未使用       |        未使用     |
      0x18         |   外部中断请求  |     IRQ模式      |          4        |
      0x1C         |   快速中断请求  |     FIQ模式      |          3        |
 ——————————————————————————————————————

7、总结 
    S3C44B0利用两个向量表高效而可靠的实现了对异常的处理,掌握了S3C44B0微处理器的异常模式以及对异常处理中复位、FIQ和IRQ响应的过程,可以在很大程度上帮助我们理解ARM7TDMI内核对异常处理的工作原理,有利于理解S3C44B0的启动代码(或Bootloader),还可以更有效的利用芯片的硬件资源编写出精简而由高效的嵌入式程序代码。对嵌入式系统整体设计会起到很大的帮助,是进行嵌入式系统开发的基础。
上一篇:ps如何快速消除黑眼圈或者眼袋


下一篇:UDA1341控制