关于中断的具体的启动代码解释:
可以这么理解,44B0 中断系统中有两张中断转移表,经过二重转移才跳到中断处理程序。第一张中断向量表由硬件决定,所在区域为ROM(flash),地址空间从0X00开始,其中0X00-0X 1C为异常向量入口地址,0X20-0XC0为中断向量入口地址。另一张中断向量表在RAM 中,可以随便改,其位置在程序连接后才定。由于 RAM 放在地址空间的高端(距离中断向量超过了 32M),为了从第一张中断向量表跳到第二张中断向量表,故在第一张中断向量表对应位置上写上 ldr PC,# interrupt_service 如:ldr PC,=HandlerEINT4567。
(1) 一级中断向量表
以下为汇编代码片断,详见44B0数据手册11章——中断控制器)
AREA Init,CODE,READONLY ; 说明:关键字ENTRY 告诉编译器保留这段代码;从代码看Init段就是要写入0x00地址的原始中断向量,因此把这个文件编译生成的44binit.O和Init填入ADS-Linker-Layout页对应项中。【这样编译器会把该段代码编译到0X0地址。】
ENTRY ;ENTRY 程序入口标号需要顶格式写,否则出错。
b ResetHandler ;复位异常 0x0000 0000 b HandlerUndef ; 未定义异常 0x0000 0004 b HandlerSWI ; 软件中断异常 0x0000 0008 b HandlerPabort ; 指令预取异常 0x0000 000C b HandlerDabort ; 数据预取异常 0x0000 0010 b . ; 保留 0x0000 0014 b HandlerIRQ ; 外部中断外设中断都是在这里扩展的 0x0000 0018 b HandlerFIQ ; 快速中断 0x0000 001C
VECTOR_BRANCH ldr pc,=HandlerEINT0 ;mGA H/W interrupt vector table 0x00000020 ldr pc,=HandlerEINT1 ; ldr pc,=HandlerEINT2 ; ……
……
b . ldr pc,=HandlerADC ;mGKB 0x0000 00C0 b . ; b . ; b . ; b . ; b . ;mGKB b . b . ;0xe0=EnterPWDN ldr pc,=EnterPWDN
LTORG
通过这段代码, 就在44B0的ROM中以0x00为起始地址的地方建立起了一张中断向量表,而且这个表的顺序完全符合44B0数据手册中对中断向量地址的定义要求。
2、二级中断向量表
^ _ISR_STARTADDRESS ;一般为 #define _ISR_STARTADDRESS 0xc7fff00
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;Do not use the label 'IntVectorTable',
;because armasm.exe can not recognize this label correctly.
;the value is different with an address you think it may be.
;IntVectorTable
HandleADC # 4
HandleRTC # 4
……
……
HandleEINT2 # 4
HandleEINT1 # 4
HandleEINT0 # 4 ;0xc1(c7)fff84
END
这段第一行 “^” 符号表示在RAM区开辟空间,就是伪代码中的MAP。
^ _ISR_STARTADDRESS 表示在RAM 的_ISR_STARTADDRESS处开辟一段空间。这里开辟的空间是用来存放中断服务程序及其他异常处理程序地址的。每个中断或其他异常都开辟4个字节的空间,这是因为RAM区的程序地址要4个字节才能放得下。而中断程序的地址是应用程序在使用这个中断时,将中断服务程序的地址存入这对应的空间内。
3、 中断向量表最终指向
一般在44B.H 等头文件能找到对应于二级中断向量表的宏定义:片断如下
#define pISR_RESET (*(unsigned *)(_ISR_STARTADDRESS+0x0))
#define pISR_UNDEF (*(unsigned *)(_ISR_STARTADDRESS+0x4))
#define pISR_SWI (*(unsigned *)(_ISR_STARTADDRESS+0x8))
#define pISR_PABORT (*(unsigned *)(_ISR_STARTADDRESS+0xc))
#define pISR_DABORT (*(unsigned *)(_ISR_STARTADDRESS+0x10))
#define pISR_RESERVED (*(unsigned *)(_ISR_STARTADDRESS+0x14))
#define pISR_IRQ (*(unsigned *)(_ISR_STARTADDRESS+0x18))
#define pISR_FIQ (*(unsigned *)(_ISR_STARTADDRESS+0x1c))
#define pISR_ADC (*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_RTC (*(unsigned *)(_ISR_STARTADDRESS+0x24))
#define pISR_UTXD1 (*(unsigned *)(_ISR_STARTADDRESS+0x28))
#define pISR_UTXD0 (*(unsigned *)(_ISR_STARTADDRESS+0x2c))
……
……
#define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x7c))
#define pISR_EINT1 (*(unsigned *)(_ISR_STARTADDRESS+0x80))
#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x84))
一般在C 文件中将自定义的中断服务子程序地址放进对应宏中,如:
pISR_TIMER0 = (int) time_interrupt()