昨天好好看可看2410的中断,说不上感觉难与不难,以下是自己的理解,可能理解不太全面,希望大家多多指正。 2410的中断可以认为分为两部分,一般情况查找2次才找到具体的中断函数。关于中断的跳转流程一共涉及这么几个文件: 2419init.s,2410addr.inc,还有就是用户的程序文件,这里用户的程序文件里干的活就是把用户中断程序入口地址和2410addr.inc里的查表地址联系起来。如果我们用到EINT0中断,那么在用户的初始化函数中就要有下面这样一句: pISR_EINT1=(U32)Eint1Int; 然后在其他的地方实现中断函数形式如此: static void __irq Eint1Int(void) 而pISR_EINT1在哪呢?在2410addr.inc中呢, pISR_RESET EQU (_ISR_STARTADDRESS+0x0) pISR_UNDEF EQU (_ISR_STARTADDRESS+0x4) pISR_SWI EQU (_ISR_STARTADDRESS+0x8) pISR_PABORT EQU (_ISR_STARTADDRESS+0xc) pISR_DABORT EQU (_ISR_STARTADDRESS+0x10) pISR_RESERVED EQU (_ISR_STARTADDRESS+0x14) pISR_IRQ EQU (_ISR_STARTADDRESS+0x18) pISR_FIQ EQU (_ISR_STARTADDRESS+0x1c) pISR_EINT0 EQU (_ISR_STARTADDRESS+0x20) /////////////////////////////////////////////// pISR_EINT1 EQU (_ISR_STARTADDRESS+0x24) //////////////////////////////////////////////// pISR_EINT2 EQU (_ISR_STARTADDRESS+0x28) pISR_EINT3 EQU (_ISR_STARTADDRESS+0x2c) pISR_EINT4_7 EQU (_ISR_STARTADDRESS+0x30) 注意两行斜线中间的部分。也就是说把用户的中断程序入口地址放在ISR_STARTADDRESS+0X24这个地方。在option.inc中有_ISR_STARTADDRESS的定义,在文件的顶部有这样的定义:_ISR_STARTADDRESS EQU 0x33ffff00,也就是说pISR_EINT0的值是0x33ffff24,只要PC指到这个地方就能正确执行中断了。怎样保证PC能正确指到这个地方呢,听我继续往下说。到这里我们就该看2410init.s了。在这个文件最下面有这样的内容: 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 HandleEINT0 # 4 HandleEINT1 # 4 HandleEINT2 # 4 HandleEINT3 # 4 HandleEINT4_7 # 4 HandleEINT8_23 # 4 这内容是和刚才2410addr.inc里一一对应的,也就是说HandleEINT1 # 4和pISR_EINT1是对应的,他们对应的是同一个地址。换句话说就是说pc发生中断后,只要pc跳到HandleEINT1这个标志的地方就能正常执行。而发生异常后,程序首先到flash 0地址查找异常原因,如果是中断异常就执行b HandlerIRQ ;handler for IRQ interrupt 然后就跳到HandlerIRQ HANDLER HandleIRQ这一行,这行是宏定义,具体展开内容是下面的样子: 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标志地址处的内容给PC。其实这就是第一次查表过程。在大概7,8和类似的宏定义下面紧接着是这样的一段代码: IsrIRQ 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 ldr r8,[r8] str r8,[sp,#8] ldmfd sp!,{r8-r9,pc} 这就是第2次查表过程,第二次查表的结果就是把我们放在HandleEINT1标志地址处的中断入口地址给PC。那么这段代码和HandleIRQ怎么联系起来的呢。系统启动的执行过程是先执行b ResetHandler,然后从ResetHandler处执行,从这里往下看,有这么几句代码: ; Setup IRQ handler ldr r0,=HandleIRQ ldr r1,=IsrIRQ str r1,[r0] 上面刚不是说HandlerIRQ HANDLER HandleIRQ的意思是让PC指向HandleIRQ地址处吗,而HandleIRQ地址处是什么内容呢,这段代码的意思就是让指向HandleIRQ的pc执行IsrIRQ的内容,而IsrIRQ的内容实现的是让PC指向HandleEINT1处的内容,而通过上面我们已经知道这个地方的内容是中断程序,这样就实现中断的跳转了。不知道说的乱不乱毛窝自己感觉挺乱的,希望对大家有帮助,可能我的描述有一些术语用的还不是特别清楚。希望大家批评指正。
阅读(2507) | 评论(0) | 转发(0) |