首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

S3C2440中断代码的深层次分析(3)

S3C2440中断代码的深层次分析(3)

还是一句一句的分析:

sub
sp,sp,#4
;
为保存PC值预留一个栈区域,这个区域与上面的处理过程是异曲同工的。


stmfd
sp!,{r8-r9}
;
保存r8,r9中的值,因为接下来将使用这两个寄存器

ldr
r9,=INTOFFSET;
这是一个伪指令操作,实质上是将寄存器INTOFFSET的地址加载到r9中。

ldr
r9,[r9];
得到寄存器中的值,这个寄存器中的值恰好保存了当前最高优先级中断的中断号(优先级是可以调节的,而中断号是一个固定值,因此选择中断号比较恰当),这样也就知道了具体是那个中断源产生了中断。


ldr
r8,=HandleEINT0;
这句的ldr是伪指令,意思是将标号的地址加载到r8

add
r8,r8,r9,lsl #2;
从指令的意义分析:r8 = r8 + r9>>2 = r8+r9*4;

其实这两句结合一下S3C2440的中断资料就不难分析得出,因为HandleEINT0实质上是指存储外部中断0处理函数地址的地方,那么我们可以将这一块内存地址看做是一个IRQISR中断向量表,而EINT0恰好是中断优先级最高的中断,那么可以将这个地址HandleEINT0作为IRQ中断向量表的入口地址,其他中断号的地址,只需要通过偏移地址就能得到,由于指针的大小恰好为4个字节,因此得到的相应中断号的入口地址是
HandleEINT0 = HandleEINT0 + INTOFFSET*4
这些地址中都保存了对应中断处理函数的函数地址。

ldr
r8,[r8]
是指将r8的内容加载到r8中,也就是将对应中断处理函数的地址加载到r8中。


str
r8,[sp,#8]
;这句代码的作用实质上就是和上面的分析一样,也就是将r8的值保存到之前为PC预留的区域中。

ldmfd
sp!,{r8-r9,pc};
这句也恰好验证了上面的分析,PC中的值恰好就是之前的sp+8处的内容,这样中断处理函数的地址就到了PC中。

小结:
我们可以将ARM中采用2级向量表的形式实现异常的中断处理,其中第一级是CPU中定义好的向量表,也就是异常向量表。在这一级的向量表中,实现跳转到对应的异常公共处理函数,另外每一种异常问题都存在自己的子问题,这时候采用第二级的向量表就可以解决各种子问题。第一级的向量表一般来说都是CPU定义好的,而第二级向量表则是我们在程序设计中人工实现的。

5、那么又是如何得到C语言中的函数呢,实质上已经很简单了,具体的分析如下:
//S3c2440init.s

^
_ISR_STARTADDRESS
; _ISR_STARTADDRESS=0x33FF_FF00

HandleReset
#
4

HandleUndef #
4

HandleSWI
#
4

HandlePabort
#
4

HandleDabort
#
4

HandleReserved
#
4

HandleIRQ
#
4

HandleFIQ
#
4


这边就可以看做第二级中断向量表

;@0x33FF_FF20

HandleEINT0
#
4

HandleEINT1
#
4


HandleUART0
#
4

….
HandleSPI1
#
4

HandleRTC
#
4

HandleADC
#
4


_ISR_STARTADDRESS
s3c2440中是一个具体的地址值,这个地址值可以在option.h中找到。因此依据这个值我们就可以知道我们的二级向量表的实际位置,这种处理的方式存在一定的巧妙性,同时中断地址的选择也需要我们恰当的设置。这里的“^ 其实就是 MAP ,这段程序的意思是,从 _ISR_STARTADDRESS 开始,预留一个变量,每个变量一个标号,预留的空间为 4个字节,也就是 32BIT,其实这里放的是真正的C写的处理函数的地址,说白了,就是函数指针,这样做就很灵活了。

//option.h
#define _ISR_STARTADDRESS
0x33ffff00

同时在s3c2440addr.h中又可以找到下面的定义:
//s3c2440addr.h
// Exception vector(异常向量,不是CPU的异常向量)
#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))
继承事业,薪火相传
返回列表