快速掌握ATEML ARM7系列文章(3) AT91SAM7S的中断

 
    关于中断大体可以这样理解:处理器内核有两个中断接口FIQ(快速中断请求)IRQ(标准中断请求),而片内高级中断控制器利用这两个接口

  将外设的中断请求有序的传递到内核。

    而如何将多达32个中断请求只用两根线传递到内核呢?这是借助硬件软件两方面的分发处理来完成的。首先AIC为每一个外设或中断源提供了一个

  中断源向量寄存器(AIC_SVR0~AICSVR31),在配置使能相应外设时用户将设备的中断处理函数地址存入对应的源向量寄存器,而当中断请求发生时

  AIC将对应的源向量寄存器中的地址复制到中断向量寄存器(AIC_IVR)并向内核发出IRQ请求。以上是硬件实现的中断分发过程,然而在用户程序中

  也必须做相关处理才能完成IRQ的分发处理,对于内核来讲IRQ只是一个中断向量,当IRQ中断请求时内核会跳到一个固定的地址(即IRQ向量)处理

  中断,用户程序(ARM的启动代码)必须在这个IRQ中断程序中分发处理才能分辨不同的设备的中断请求,但有了上面这样硬件的预处理过程,软件分

  发处理变得比较简单,跳到AIC中断向量寄存器中地址处即可,下面具体看一下启动代码:


  PROGRAM ?RESET
  RSEG INTRAMSTART_REMAP
  RSEG INTRAMEND_REMAP

  RSEG ICODE:CODE:ROOT(2)
  CODE32 ; Always ARM mode after reset
  org 0
  reset
    B InitReset ; 0x00 Reset handler
  undefvec:
    B undefvec ; 0x04 Undefined Instruction
  swivec:
    B swivec ; 0x08 Software Interrupt
  pabtvec:
    B pabtvec ; 0x0C Prefetch Abort
  dabtvec:
    B dabtvec ; 0x10 Data Abort
  rsvdvec:
    B rsvdvec ; 0x14 reserved
  irqvec:                             ;此处是IRQ向量,它是固定的地址
    B IRQ_Handler_Entry ; 0x18 IRQ  
  fiqvec: ; 0x1c FIQ
  FIQ_Handler_Entry:

  ................................    ;此处代码省略未列出

  IRQ_Handler_Entry:                  ;IRQ处理例程

  ;- Manage Exception Entry
  ;- Adjust and save LR_irq in IRQ stack
  sub lr, lr, #4
  stmfd sp!, {lr}

  ;- Save SPSR need to be saved for nested interrupt
  mrs r14, SPSR
  stmfd sp!, {r14}

  ;- Save and r0 in IRQ stack
  stmfd sp!, {r0}

  ;- Write in the IVR to support Protect Mode
  ;- No effect in Normal Mode
  ;- De-assert the NIRQ and clear the source in Protect Mode
  ldr r14, =AT91C_BASE_AIC
  ldr r0 , [r14, #AIC_IVR]
  str r14, [r14, #AIC_IVR]

  ;- Enable Interrupt and Switch in Supervisor Mode
  msr CPSR_c, #ARM_MODE_SVC

  ;- Save scratch/used registers and LR in User Stack
  stmfd sp!, { r1-r3, r12, r14}

  ;- Branch to the routine pointed by the AIC_IVR 跳到AIC_IVR寄存器内地址处,这便是软件分发处理过程
  mov r14, pc
  bx r0

  ;- Restore scratch/used registers and LR from User Stack
  ldmia sp!, { r1-r3, r12, r14}

  ;- Disable Interrupt and switch back in IRQ mode
  msr CPSR_c, #I_BIT | ARM_MODE_IRQ

  ;- Mark the End of Interrupt on the AIC
  ldr r14, =AT91C_BASE_AIC
  str r14, [r14, #AIC_EOICR]

  ;- Restore R0
  ldmia sp!, {r0}

  ;- Restore SPSR_irq and r0 from IRQ stack
  ldmia sp!, {r14}
  msr SPSR_cxsf, r14

  ;- Restore adjusted LR_irq from IRQ stack directly in the PC
  ldmia sp!, {pc}^

    这样,我们就知道:某一片内外设使用了AIC的哪一个输入通道是与内核无关的,它与具体芯片厂家的设计有关。在AT91SAM7S中片内外设的ID号

  便是AIC中断源向量寄存器AIC_SVRn的索引,例如定时器/计数器0的ID是12所以它的中断处理函数地址应存入AIC_SVR12中。AIC其它寄存器的配置也

  是类似,一般都是设置设备ID对应位来配置相关功能。

    FIQ(快速中断请求)很大程度上可以说是为了提供从芯片外通过FIQ引脚申请中断的一个快速通道。AIC将第一个中断源通道留给了FIQ,即FIQ

  的用户中断程序入口地址应存入AIC_SVR0中以便在FIQ中断处理程序中调用。

  FIQ_Handler_Entry:   ;启动代码中快速中断的处理程序

  ;- Switch in SVC/User Mode to allow User Stack access for C code
  ; because the FIQ is not yet acknowledged

  ;- Save and r0 in FIQ_Register
  mov r9,r0
  ldr r0 , [r8, #AIC_FVR]
  msr CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC
  ;- Save scratch/used registers and LR in User Stack
  stmfd sp!, { r1-r3, r12, lr}

  ;- Branch to the routine pointed by the AIC_FVR ;跳到用户设置的FIQ处理程序,AIC_FVR返回AIC_SVR0的值
  mov r14, pc
  bx r0

  ;- Restore scratch/used registers and LR from User Stack
  ldmia sp!, { r1-r3, r12, lr}

  ;- Leave Interrupts disabled and switch back in FIQ mode
  msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ

  ;- Restore the R0 ARM_MODE_SVC register
  mov r0,r9

  ;- Restore the Program Counter using the LR_fiq directly in the PC
  subs pc,lr,#4

    相对于IRQ来讲FIQ是没有硬件分发机制的,但我们仍然可以通过设置AIC的快速强制使能寄存器(AIC_FFER)使普通外设中断变成快速中断,

  如果中断源是多个那必须用软件实现分发(即进入FIQ中断后判断中断源)。通常快速中断是不这样使用的,它的中断源一般只有一个以达到

  快速反应的目的。

    

芯艺设计室(http://www.chipart.cn) 2008.03.22  转载请注明出处!

 

芯艺设计室    蒙ICP备06005492号

Copyright© 2004-2011 ChipArt Design House All Rights Reserved