Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2817185
  • 博文数量: 523
  • 博客积分: 11908
  • 博客等级: 上将
  • 技术积分: 5475
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-03 15:50
文章分类

全部博文(523)

文章存档

2019年(3)

2013年(4)

2012年(71)

2011年(78)

2010年(57)

2009年(310)

分类: LINUX

2012-03-03 12:50:00

 (一)       ARM7TDMI内核CPU在响应中断后会切换到异常模式下:FIQ中断是进入快中断模式,IRQ中断时进入中断模式(ARM7TDMI内核有7种模式: 用户模式,系统模式,快中断模式,中断模式,管理模式,中止模式和未定义模式,其中后5种被称为异常模式,由程序状态寄存器的M4M3M2M1M0这5位 来决定,其实ARM7的模式管理的这5位和51单片机状态寄存器的RS1RS0两位的作用相似)。 进入哪一种中断模式是由前面寄存器的配置决定的。

  (二)irq中断又有向量中断和非向量中断之分,向量中断就是不同的中断有不同的入口地址,非向量中断就只有一个入口地址,进去了在判断中断标志来识别具体是哪个中断。向量中断实时性好,非向量中断简单。 同样由寄存器来决定。

   (三)在程序中:

          0x0  - 0x1c 叫异常向量表
          0x20 - 0xc0 叫中断向量表
          RAM区用户定义中断向量表,叫二级中断向量表(有时候0x00--0xc0就叫做中断向量表)

向量模式中断
  异常向量表后紧接中断向量表,没有二级中断向量表,中断向量表里放的是中断服务程序的入口地址.
  从0x18到中断向量表的跳转是由硬件自行完成的.
   
  ENTRY
b ResetHandler ; 0x00
b HandlerUndef ; 0x04
b HandlerSWI ; 0x08
b HandlerPabort ; 0x0c
b HandlerDabort ; 0x10
b . ; 0x14
b HandlerIRQ ; 0x18
b HandlerFIQ ; 0x1c
ldr pc,=HandlerEINT0 ; 0x20  ;里面放的是中断处理函数的地址.
ldr pc,=HandlerEINT1
ldr pc,=HandlerEINT2
ldr pc,=HandlerEINT3
ldr pc,=HandlerEINT4567
ldr pc,=HandlerTICK ; 0x34
b .
b .
ldr pc,=HandlerZDMA0 ; 0x40
ldr pc,=HandlerZDMA1
ldr pc,=HandlerBDMA0
ldr pc,=HandlerBDMA1
ldr pc,=HandlerWDT
ldr pc,=HandlerUERR01 ; 0x54
b .
b .
ldr pc,=HandlerTIMER0 ; 0x60
ldr pc,=HandlerTIMER1
ldr pc,=HandlerTIMER2
ldr pc,=HandlerTIMER3
ldr pc,=HandlerTIMER4
ldr pc,=HandlerTIMER5 ; 0x74
b .
b .
ldr pc,=HandlerURXD0 ; 0x80
ldr pc,=HandlerURXD1
ldr pc,=HandlerIIC
ldr pc,=HandlerSIO
ldr pc,=HandlerUTXD0
ldr pc,=HandlerUTXD1 ; 0x94
b .
b .
ldr pc,=HandlerRTC ; 0xa0
b .
b .
b .
b .
b .
b .
ldr pc,=HandlerADC ; 0xb4

3.非向量模式中断:
  这个比较复杂,
  原理: irq request -> 0x18 -> HandlerIRQ(一个宏) -> HandleIRQ(一个内存地址,里面是IsrIRQ函数的地址) -> IsrIRQ(根据I_ISPR,来判断哪个中断发生) -> 二级中断向量表(RAM高端) -> 转到中断服务程序的入口地址(此图根据44b0init.s得来,不是下面的代码的运行方式)
 0x0  - 0x1c 叫异常向量表
          0x20 - 0xc0 叫中断向量表
          RAM区用户定义中断向量表,叫二级中断向量表

2.向量模式中断
  异常向量表后紧接中断向量表,没有二级中断向量表,中断向量表里放的是中断服务程序的入口地址.
  从0x18到中断向量表的跳转是由硬件自行完成的.
   
  ENTRY
b ResetHandler ; 0x00
b HandlerUndef ; 0x04
b HandlerSWI ; 0x08
b HandlerPabort ; 0x0c
b HandlerDabort ; 0x10
b . ; 0x14
b HandlerIRQ ; 0x18
b HandlerFIQ ; 0x1c
ldr pc,=HandlerEINT0 ; 0x20  ;里面放的是中断处理函数的地址.
ldr pc,=HandlerEINT1
ldr pc,=HandlerEINT2
ldr pc,=HandlerEINT3
ldr pc,=HandlerEINT4567
ldr pc,=HandlerTICK ; 0x34
b .
b .
ldr pc,=HandlerZDMA0 ; 0x40
ldr pc,=HandlerZDMA1
ldr pc,=HandlerBDMA0
ldr pc,=HandlerBDMA1
ldr pc,=HandlerWDT
ldr pc,=HandlerUERR01 ; 0x54
b .
b .
ldr pc,=HandlerTIMER0 ; 0x60
ldr pc,=HandlerTIMER1
ldr pc,=HandlerTIMER2
ldr pc,=HandlerTIMER3
ldr pc,=HandlerTIMER4
ldr pc,=HandlerTIMER5 ; 0x74
b .
b .
ldr pc,=HandlerURXD0 ; 0x80
ldr pc,=HandlerURXD1
ldr pc,=HandlerIIC
ldr pc,=HandlerSIO
ldr pc,=HandlerUTXD0
ldr pc,=HandlerUTXD1 ; 0x94
b .
b .
ldr pc,=HandlerRTC ; 0xa0
b .
b .
b .
b .
b .
b .
ldr pc,=HandlerADC ; 0xb4

关于向量irq中断两张向量表的跳转需要说明的部分是:ARM7TDMI 在矢量模式下,当从 0X18 地址处取指令时候,中断控制器会在数据总线上加载分支指令,这些分支指令使程序计数器能够对应到每一个中断源的向量地址。这些跳转到每一个中断源向量地址 的分支指令由中断控制器产生。 
       例如:假设 EINT0 是 IRQ 中断,EINT0 的向量地址为:0X20(见向量表),那么中断控制器必须产生0X18---0X20的分支指令。 
       中断控制器产生的机器码为: 0XEA000000。在各个中断源对应的中断向量地址中,存放着跳转到相应中断服务程序的程序代码。在相应向量地址处分支指令的机器代码如下计算: 矢量中断模式的机器指令代码=0XEA000000+((<目标地址>-<向量地址>-0X8)>>2) ,机器代码一般由反汇编后自动产生

非向量模式中断:
  这个比较复杂,
  原理: irq request -> 0x18 -> HandlerIRQ(一个宏) -> HandleIRQ(一个内存地址,里面是IsrIRQ函数的地址) -> IsrIRQ(根据I_ISPR,来判断哪个中断发生) -> 二级中断向量表(RAM高端) -> 转到中断服务程序的入口地址(此图根据44b0init.s得来,不是下面的代码的运行方式)

此处代码比上图的运行方式少了一个环节:没有HandlerIRQ这个阶段.

ENTRY
b ResetHandler   ; for debug
b HandlerUndef   ; handlerUndef
b HandlerSWI     ; SWI interrupt handler
b HandlerPabort  ; handlerPAbort
b HandlerDabort  ; handlerDAbort
b .              ; handlerReserved
b IsrIRQ
b HandlerFIQ
. . . . . .

IsrIRQ
    sub     sp,sp,#4 ; reserved for PC
    stmfd    sp!,{r8-r9}
    ldr     r9,=I_ISPR
    ldr     r9,[r9]
    mov     r8,#0x0
0   movs    r9,r9,lsr #1  ;移位,c为最后一位被移出的.如果最后一位是1,那么C置位,
    bcs     %F1           ;如果C置位,跳.
    add     r8,r8,#4
    b       %B0
1   ldr     r9,=HandleADC
    add     r9,r9,r8
    ldr     r9,[r9]
    str     r9,[sp,#8]
    ldmfd   sp!,{r8-r9,pc}

. . . . . .
HandleADC # 4
HandleRTC # 4
HandleUTXD1 # 4
HandleUTXD0 # 4
. . . . . .
HandleEINT3 # 4
HandleEINT2 # 4
HandleEINT1 # 4
HandleEINT0 # 4 ; 0xc1(c7)fff84

需要说明的是: 结合这些,再看看程序中的代码。在无矢量中断模式,通过分析IISPR/FISPR 寄存器,IRQ/FIQ 处理器将移动PC到相应的ISR。HandleXXX 地址包含每个响应的ISR程序的起始地址。

 

总之,fiq自己处理,矢量irq硬件协同快速处理,非矢量irq软件工作挺多(说得可能不太准确,请包涵   :) )

 

(四)虽然我们可以选择让多个中断源(VICIntSelect)产生FIQ,但是只应该为所有可能的FIQ中断请求指定一个中断服务例程。因此, 若有多于一个中断源归类为FIQ,则FIQ中断服务例程必须读取VICFIQStatus的内容来决定如何操作处理该中断请求。不过,我们强烈建议大家只 将一个中断归类为FIQ,因为把不止一个中断源归类为FIQ会延长中断潜伏期。
  在中断服务例程结束的地方,从外设级清除中断标志将会影响若干 VIC寄存器(VICRawIntr、VICFIQStatus和VICIRQStatus)的对应位。另外,在服务下一个中断之前,我们必须在中断返回 之前对VICVectAddr执行写操作。该写操作会清除内部中断优先级硬件中的相关中断标志。
  为了禁能VIC中的中断,我们需要向 VICIntEnClr寄存器中的对应位写1来清除VICIntEnable寄存器中的相关位。这同样适用于VICSoftInt和 VICSoftIntClear。例如,假设VICSoftInt当前值为0x0000 0005,我们要清除位0,则向VICSoftIntClear写入0x0000 0001将实现该目的。在此之后,如果想再次向VICSoftIntClear写入值来完成对VICSoftInt相同位的清除操作,就必须先向 VICSoftIntClear赋值0x0000 0000。可见,向Clear寄存器写入1对目标寄存器来说只生效一次

  假设UART0和SPI0都归类为向量IRQ(UART0的优先级比SPI0的高),而UART1和I2C归类为非向量IRQ。以下可能是设置VIC时使用的代码:

  VICIntSelect = 0x00000000;//SPI0,I2C,UART1和UART0均归类为IRQ(位10,9,7和6均为0)
  VICIntEnable = 0x000006C0;//SPI0,I2C,UART1和UART0均归使能中断(位10,9,7和6均为1)
  VICDefVectAddr = 0x........;//保存非向量IRQ服务例程的地址
  VICVectAddr0 = 0x........;//保存UART0 IRQ服务例程的起始地址
  VICVectAddr1 = 0x........;//保存SPI0 IRQ服务例程的起始地址
  VICVectCntl0 = 0x00000026;//源索引为6的中断(UART0)在0槽使能
  VICVectCntl1 = 0x0000002A;//源索引为10的中断(SPI0)在1槽使能
  当任意一个IRQ请求(SPI0,I2C,UART0或UART1)产生时,微控制器将会跳转到特殊地址0x00000018处执行。对于向量与非向量IRQ,可以在0x18地址处放置以下指令:
  LDR PC, [PC, #-0xFF0]
  该指令将VICVectAddr寄存器中提供的地址装载进PC(程序计数器)。
   对于UART0产生中断请求的情况,VICVectAddr和VICVectAddr0的值相同,而SPI0产生中断请求的情 况,VICVectAddr中是VICVectAddr1的值。如果UART0和SPI0都没有产生中断请求而UART1或I2C产生了,那么 VICVectAddr的内容将和VICDefVectAddr的一样。

http://blog.csdn.net/aquolee/article/details/3325855
阅读(1787) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~