VxWorks基于AT91RM9200处理器的中断处理
3VxWorks中断模块实现机制
3.1 异常中断向量表的生成及实现
在usrInit()函数中通过intVecBaseSet((FUNCPTR*)VEC_BASE_ADRS)函数对异常中断向量表的基址进行设置, VEC_BASE_ADRS在configall.h中定义为程序运行空间的起始地址,但是在ARM中并没有中断基址寄存器,由于ARM9有重影射机制,可以将程序运行空间的起始地址影射成0地址,这也符合ARM体系结构通常都是把异常中断向量表放在0地址处的惯例,异常中断向量表可以从反汇编 bootrom_uncmp后的0地址处看到。当有内置的外设中断或外部中断产生时,系统首先跳转到异常中断向量表的0x18处,此处是IRQ中断向量的位置,该内存中放置的是一条跳转指令,因为excVecInit()对中断向量表初始化后,生成了一个exeEnterTbl,在这个表中列出了异常向量和对应入口函数的结构表,exeEnterTbl结构如图2所示。
图2 excEnterTbl的结构
由于ARM9用了重影射机制,因此重影射之后,系统将LOCAL_MEM_LOCAL_ADRS影射成0地址,中断向量表从0地址处开始。从 excVecInit()的反汇编代码可以看出,系统把指令ldr pc,[pc,#244]的反汇编代码放在了从0x00000004开始的每个异常中断向量地址处,也就是将excEnterTbl中每个异常处理函数的入口地址都放在了(0xF4+0x8+0x4+所对应异常相对于未定义指令异常(0x00000004)的偏移)的内存中,这样就将异常向量和异常处理入口函数关联起来了。
3.2 中断向量表的结构及生成
那么当系统产生中断后,VxWorks是如何设置中断向量表,并且将中断向量和中断处理入口程序关联起来的呢?和异常向量表有点类似,但是中断向量表是VxWorks操作系统动态分配的一段连续的内存空间,这个空间的结构如图3所示。
图3 VxWorks中断向量表的结构
因为是动态分配,所以在这段内存空间中,操作系统只给当前中断分配了中断号、中断处理函数的入口和被传递的参数。每个中断源按照中断号顺序排列,在为每个中断源分配的内存空间中头4个字节是中断向量表的初始化函数的入口,该函数对于每个中断源来说是通用的,然后顺序放置的是中断号、中断处理函数入口和被传递的参数.通过intconnect()函数可以将中断向量和中断处理函数关联起来,因此在系统获知了发生中断的中断号时,就可以找到相应的中断处理函数去处理该中断。当发生IRQ异常时,系统强制把程序指针拉到0x18处,在0x18处是这样一条指令ldrpc,[pc,#244],IRQ异常相对于未定义指令异常的偏移是0x14,所以相当于把0x114地址处的内容赋给pc,而0x114处的内容正是IRQ异常向量处理的入口函数intEnt的地址,因此程序跳转到intent处去执行。
4 中断处理跟踪调试的部分反汇编代码
通过使用ARM Developer Site仿真器,在0x18处设置断点后单步执行来分析中断处理的过程。中断处理函数的入口处代码如下:
2070b174[0xe59fb410] ldr r11,0x2070b58c; /*=#0x207a40c8,0x207a40c8是中断向量表的位置*/
2070b178[0xe59dc018] ldr r12,[r13,#0x18] /*将0x207b1ce8中的内容给r12应该是中断号!!!*/
2070b17c[0xe59bb000] ldr r11,[r11,#0] /*0x207a40c8处的内容是0x21ffbef8*/
2070b180[0xe08b318c] add r3,r11,r12,lsl #3 /*将0x21ffbef8(内存地址)给r3,0x21ffbef8的内容是向量0x207064b0,这是debug口中断处理函数的入口*/
2070b184[0xe79ba18c] ldr r10,[r11,r12,lsl#3]
2070b188[0xe5930004] ldr r0,[r3,#4] /*相应的参数传递给r0*/
2070b18c[0xe1a0e00f] mov r14,pc
2070b190[0xe1a0f00a] mov pc,r10 /* r10=0x207064b0,跳转到debug口中断处理函数处执行*/
0x21ffbef8(中断向量表基址)处的情况是:
21ffbef8[0x2070b434] dcd 0x2070b434 4.p
21ffbefc[0x00000000] dcd 0x00000000....
21ffbf00[0x207064b0] dcd 0x207064b0.dp
21ffbf04[0x207a9990] dcd 0x207a9990..z
21ffbf08[0x2070b434] dcd 0x2070b434 4.p
21ffbf0c[0x00000002] dcd 0x00000002....
21ffbf10[0x2070b434] dcd 0x2070b434 4.P
21ffbf14[0x00000003] dcd 0x00000003....
21ffbf18[0x2070b434] dcd 0x2070b434 4.P
21ffbf1c[0x00000004] dcd 0x00000004....
5 结语
Vxworks操作系统首先调用excVecInit()生成一个异常中断向量表excEnterTbl,当有IRQ中断发生时,根据 excEnterTbl中0x00000018处的指令ldr pc,[pc,#244]跳转到0x00000114处,即IRQ异常中断的入口处intEnt执行,随后通过读AIC_IVR寄存器得到当前优先级最高的中断,返回这个中断号,并跳转到intConnect()函数给该中断号关联的中断处理程序入口去执行。在这个过程中,中断向量表的生成是 Vxworks动态分配的,在AT91RM9200中,为0到31号中断源在中断向量表中都分配了空间,该空间的格式固定。中断处理结束后,通过往 AIC_EIOC寄存器中写任意值,从中断中返回。
评论