现在的位置: 首页 > 综合 > 正文

ColdFire与ARM处理器中断响应分析

2013年03月01日 ⁄ 综合 ⁄ 共 2920字 ⁄ 字号 评论关闭
ColdFire与ARM处理器中断响应分析2007-10-22

一.ARM处理器中断分析(以S3C2410的IRQ及timer0中断为例)
1. 中断初始化过程
1> 中断向量表起始地址定义
C文件中的宏定义:
#define _ISR_STARTADDRESS 0x33ffff00
汇编文件中的定义:
_ISR_STARTADDRESS EQU 0x33ffff00
2> IRQ中断及具体外设中断源地址定义
C文件中的宏定义:
。。。。。。
#define pISR_IRQ (*(unsigned *)(_ISR_STARTADDRESS+0x18))
。。。。。。
#define pISR_TIMER0 (*(unsigned *)(_ISR_STARTADDRESS+0x48))
。。。。。。。
汇编文件中的定义:
。。。。。。
pISR_IRQ EQU (_ISR_STARTADDRESS+0x18)
。。。。。。
pISR_TIMER0 EQU (_ISR_STARTADDRESS+0x48)
。。。。。。
AREA RamData, DATA, READWRITE
 
^ _ISR_STARTADDRESS
。。。。。。
HandleIRQ # 4 //注:位于_ISR_STARTADDRESS+0x18处
。。。。。。
HandleTIMER0 # 4
。。。。。。
END
3> 相关的子程序段
内核中断都要用到的宏定义:
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
 
IRQ中断处理程序断:
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}
4> 系统启动时的初始化过程
ResetHandler
//系统复位后,从这开始执行
。。。。。。
ldr r0,=HandleIRQ
ldr r1,=IsrIRQ //将IRQ中断处理程序IsrIRQ入口地址保存在向量表HandleIRQ位置
str r1,[r0]
。。。。。。
pISR_TIMER0 = (int)Timer0Done;//该语句为C语言,在应用程序中初始化
//将定时器0的中断处理程序地址保存在向量表该中断源位置
2. 中断响应过程
当产生timer0中断请求时,PC指向IRQ中断入口(地址:0x00000018)处,执行跳转指令(b HandlerIRQ)到宏定义(HandlerIRQ HANDLER HandleIRQ)处,即相当于如下程序:
HandlerLabel
sub sp,sp,#4
stmfd sp!,{r0}
ldr r0,=HandleIRQ
ldr r0,[r0]
str r0,[sp,#4]
ldmfd sp!,{r0,pc}
执行这段程序后,PC将指向存放在中断向量表HandleIRQ处的IsrIRQ程序,如下:
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}
上述的INTOFFSET为中断偏移寄存器,该值保存了请求挂起的中断源的偏移值(每个中断源都对应一个唯一值,参考S3C2410 datasheet的P14-16页表格,如timer0的偏移值为10),指示是哪个中断源产生请求处理,例如timer0产生中断请求,则该值就为10。由于EINT0的偏移值为0,而中断向量表是根据偏移值排列的,故上述的程序将向量表的HandlerEINT0再加上INTOFFSET值,查表得到pISR_TIMER0位置处的timer0中断处理程序Timer0Done的地址,所以执行这段程序后PC指向了Timer0Done,也就是用户最终的中断处理程序。
二.ColdFire中断分析(以MCF52235的EPORT0的IRQ4为例
1. 中断向量表初始化
1> 中断函数定义
__interrupt__ void
irq4_handler(void)
{
。。。。。。
}
2> 向量表定义
/*
* Exception Vector Table
*/
VECTOR_TABLE:
_VECTOR_TABLE:
INITSP: .long ___SP_INIT /* Initial SP */
INITPC: .long 0x00000400 /* Initial PC */
vector02: .long _asm_exception_handler /* Access Error */
。。。。。。
vector44: .long _irq4_handler //64+4(IRQ4的中断源号)=0x44
。。。。。。
vectorFF: .long _irq_handler
3> 系统启动时的对中断向量表的初始化
/* Copy the vector table to RAM */
if (__VECTOR_RAM != VECTOR_TABLE)
{
for (n = 0; n < 256; n++)
__VECTOR_RAM[n] = VECTOR_TABLE[n];
}
mcf5xxx_wr_vbr((uint32)__VECTOR_RAM);//将向量表地址写入内核向量寄存器
 
2. 中断响应过程
当IRQ4中断源产生中断时,PC将直接指向中断向量表的IRQ4处的服务程序地址:irq_handler。注:由于接触ColdFire也不是很久,所以不一定正确,还请熟悉ColdFire的朋友指证。不过我在单步仿真的情况下,触发IRQ4时,观察PC值确时是如此的。
三.总结
由上述分析,ColdFire处理器很像8位单片机(如:51系列等)那样,一个中断源占用一个中断入口,只是该中断入口是跟随内核的VBR值的不同,而可以不同。当产生某个中断源请求时,PC直接指向该中断源的处理程序。相比之下,ARM的中断响应处理要复杂些,无论是哪个中断源请求,都必须先进入IRQ(假设中断源被设成IRQ模式)的中断入口,再根据具体中断源的偏移寄存器INTOFFSET值,找到最终中断源的处理程序。

抱歉!评论已关闭.