Chinaunix首页 | 论坛 | 博客
  • 博客访问: 203928
  • 博文数量: 28
  • 博客积分: 2510
  • 博客等级: 少校
  • 技术积分: 315
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-03 11:16
文章分类

全部博文(28)

文章存档

2008年(28)

我的朋友
最近访客

分类: WINDOWS

2008-09-24 21:12:02

最开始的代码,大家都很熟悉 ,最基本的中断跳转

b ResetHandler

b HandlerUndef ;handler for Undefined mode
 b HandlerSWI ;handler for SWI interrupt
 b HandlerPabort ;handler for PAbort
 b HandlerDabort ;handler for DAbort
 b .  ;reserved
 b HandlerIRQ ;handler for IRQ interrupt
 b HandlerFIQ ;handler for FIQ interrupt

跳转的标号是一系列的宏

LTORG  
HandlerFIQ      HANDLER HandleFIQ
HandlerIRQ      HANDLER HandleIRQ
HandlerUndef    HANDLER HandleUndef
HandlerSWI      HANDLER HandleSWI
HandlerDabort   HANDLER HandleDabort
HandlerPabort   HANDLER HandlePabort

该宏在文件的最前面实现,做了一些跳转前的处理。如下:

MACRO
$HandlerLabel HANDLER $HandleLabel

$HandlerLabel
 sub sp,sp,#4        ;decrement sp(to store jump address)
 stmfd sp!,{r0}        ;PUSH the work register to stack(lr does't push because it return to original address)
 ldr     r0,=$HandleLabel;load the address of HandleXXX to r0
 ldr     r0,[r0]         ;load the contents(service routine start address) of HandleXXX
 str     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stack
 ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
 MEND

以HandleIRQ跳转为例说明中断的二级跳转流程,以上的宏代码说明IRQ跳转到了标号HandleIRQ处,该标号如下定义:(是一系列的中断以及二级中断入口地址)

AREA RamData, DATA, READWRITE

        ^   _ISR_STARTADDRESS    ;(该值自己定义,是存放中断向量表的地址)
HandleReset  #   4
HandleUndef  #   4
HandleSWI    #   4
HandlePabort    #   4
HandleDabort    #   4
HandleReserved  #   4
HandleIRQ    #   4
HandleFIQ    #   4

;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable(二级IRQ中断向量表)
HandleEINT0    #   4
HandleEINT1    #   4
HandleEINT2    #   4
HandleEINT3    #   4
HandleEINT4_7 #   4
HandleEINT8_23 #   4
HandleRSV6 #   4
HandleBATFLT    #   4
HandleTICK    #   4
HandleWDT #   4
HandleTIMER0  #   4
HandleTIMER1  #   4
HandleTIMER2  #   4
HandleTIMER3  #   4
HandleTIMER4  #   4
HandleUART2   #   4
HandleLCD  #   4
HandleDMA0 #   4
HandleDMA1 #   4
HandleDMA2 #   4
HandleDMA3 #   4
HandleMMC #   4
HandleSPI0 #   4
HandleUART1 #   4
HandleRSV24 #   4
HandleUSBD #   4
HandleUSBH #   4
HandleIIC    #   4
HandleUART0  #   4
HandleSPI1  #   4
HandleRTC  #   4
HandleADC  #   4

而HandleIRQ由以下代码赋值,可以看出跳转到了IsrIRQ:

dr r0,=HandleIRQ       ;This routine is needed
 ldr r1,=IsrIRQ          ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c放置中断跳转
 str r1,[r0]

IsrIRQ  ;真正的IRQ中断的入口
 sub sp,sp,#4       ;reserved for PC留出一个位置保存中断入口地址
 stmfd sp!,{r8-r9}  
 
 ldr r9,=INTOFFSET
 ldr r9,[r9]                   ;读入中断偏移码
 ldr r8,=HandleEINT0    ;二级跳转表的首地址
 add r8,r8,r9,lsl #2         ;R8=R8+R9X4得到相应的中断入口地址
 ldr r8,[r8]
 str r8,[sp,#8]             ;中断入口地址送进SP(第一个代码留出的4字节空间)
 ldmfd sp!,{r8-r9,pc}

到此为止,中断已经顺利的进入了中断向量表,用C语言编写服务程序已变的非常简单。如EINT0中断的ISR

void Eint0(void)

{      }

pISR_EINT0=(U32)Eint0;  //用中断入口指向函数指针即可。

阅读(2342) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~