|  | 
 
| 首先,在2410init.s 文件的最前面,存放着一些异常跳转的指令,必须保证他们在如下地址。 如果是从Nor Flash或Nand Flash启动,那么2410init开始在0x00000000地址,他们可以保证满
 足,如果是从SDRAM调试,那么就必须经过MMU地址映射
 b ResetHandler        ;地址0x00000000
 b HandlerUndef        ;地址0x00000004
 b HandlerSWI          ;地址0x00000008
 b HandlerPabort       ;地址0x0000000c
 b HandlerDabort       ;地址0x00000010
 b . ;reserved        ;地址0x00000014
 b HandlerIRQ          ;地址0x00000018
 b HandlerFIQ          ;地址0x0000001c
 再看后面代码
 HandlerFIQ      HANDLER HandleFIQ
 HandlerIRQ      HANDLER HandleIRQ
 HandlerUndef    HANDLER HandleUndef
 HandlerSWI      HANDLER HandleSWI
 HandlerDabort   HANDLER HandleDabort
 HandlerPabort   HANDLER HandlePabort
 这是调用HANDLER宏,上面的调用都会被宏展开,注意HANDLER前后的文字是不一样的,一个是HandlerXXX一各是HandleXXX。HandlerXXX再最前面的跳转里已经出现了,那HandleXXX是什么呢,稍后说明,先看看宏定义
 $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
 宏的作用就是保存返回地址,以便退出异常模式时能继续执行程序,跳转到异常向量所指向的地
 址执行异常处理程序,然后返回,那么HandleXXX肯定是异常向量的地址了,在2410init.s文件的最后可以找到
 ^   _ISR_STARTADDRESS
 HandleReset #   4
 HandleUndef #   4
 HandleSWI   #   4
 HandlePabort    #   4
 HandleDabort    #   4
 HandleReserved #   4
 HandleIRQ   #   4
 HandleFIQ   #   4
 上面符号^ 是MAP的简写形式,再option.s里有定义   _ISR_STARTADDRESS EQU 0x33ffff00,这是一个内存地址。
 在程序真正开始有,有一段代码,就是设置这个内存空间,让其指向IsrIRQ
 ldr r0,=HandleIRQ       ;This routine is needed
 ldr r1,=IsrIRQ          ;hjhhhhh
 str r1,[r0]
 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}
 其中HandleEINT0是第一个中断的向量地址,其他的从这个偏移得来,如下
 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
 分析中断处理的整个过程:首先执行了这段代码
 ldr r0,=HandleIRQ       ;This routine is needed
 ldr r1,=IsrIRQ          ;hjhhhhh
 str r1,[r0]
 中断来了后,产生中断异常,跳转到0x00000018
 0x00000018 放着一条指令
 b HandlerIRQ          ;地址0x00000018
 跳转到了HanderIRQ
 中断宏展开后,如下:
 HandlerIRQ
 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,=$HandleIRQ; load the address of HandleXXX to r0
 ;这个地址是 _ISR_STARTADDRESS+0x1c
 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)
 系统这时候已经取得了HandleIRQ空间的值,准备跳过去。再最前面,已经设置了HandleIRQ指向了IsrIRQ
 所以,程序跳到IsrIRQ。
 再IsrIRQ中取得向量地址,并跳过去执行中断程序!
 我是沈阳的 欢迎和我探讨 或者需要家教的联系我qq:1092819587我可以交有linux和无linux的arm,cpld,mc51,dsp这些的整个板子的软硬件开发,以及高速pcb的制作,原理图设计。有过几次带本科生和研究生家教的经验。祝您好运!
 | 
 |