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

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

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

1、搞清楚ARM中的MACRO伪指令,这个伪指令就是我们在汇编中的宏定义,我们都知道宏的实现能够避免代码的重复型以及代码的可修复性。关于ARM汇编中的宏定义基本的形式如下:

MACRO


{$label} macroname {$parameter} {$parameter}…


Code


MEND

       其中$label 宏指令被展开时,label可被替换为相应的符号,一般为一个标号

macroname
所定义的宏的名称


$parameter
宏指令的参数,当宏指令被展开时被替换成对应的值。

2、依据上面的定义我们可以知道当前这段代码定义了一个宏指令,HANDLER,其中标号为$HandlerLabel,参数为$HandleLabel
基本的实现代码分析如下:
sub
sp,sp,#4;
在栈中预留一个区域,用来保存PC的值

stmfd
sp!,{r0}
;
由于r0还需要被使用,因此需要被压栈

ldr
r0,=$HandleLabel ;
这里的ldr是一个伪指令,主要是将标号$HandleLabel的地址加载到r0中,这也是压栈r0的原因。

ldr
r0,[r0]
;
这是ARMldr指令,主要是将$HandleLabel对应地址中的内容加载到r0中。如果在$HandleLabel中保存的是一个中断处理函数的地址,那么只需要将这个值加载到PC即可实现了中断任务跳转,实际上这个过程就是采用了异常处理的第二种方式:

即加载PC的方式,而不是简单的跳转方式。

str
r0,[sp,#4]
;store the contents(ISR) of HandleXXX to stack

ldmfd
sp!,{r0,pc}
OP the work register and pc(jump to ISR)

这两句代码正是这段代码的精髓。基本形式如下:
str
r0,[sp,#4]
,是指将r0的内容,也就是异常处理函数的地址保存到栈中的SP-4位置处,这个位置也恰好是之前sub
sp,sp,#4;
用来预留给保存PC值的位置,这时将异常处理函数的地址保存在这个地址处,接下来的ldmfd
sp!,{r0,pc}
刚好就是将栈中的内容加载到R0PC中,这样也就实现了将异常处理函数地址加载到PC.实现了跳转过程。


                                
            
            
            高地址
            
            SP_0/SP_3
            
            
            
            SP_1
            
            Handle_addr
            
            SP_2
            
            R0
            
            
            
            低地址
            

从上面的分析可以知道这种中断处理的方式,并不是中断处理中的简单跳转方式(因为跳转范围的局限性)而是采用更新PC值的形式实现的。

接下来分析IRQ,这种在我们实际开发中使用比较多的中断形式进行分析。
首先可以发现存在:
1b
HandlerIRQ
;handler for IRQ interrupt

这种情况下发生在中断产生过程中,是在IRQ向量中执行的,也就是在0x18处执行,其中HandlerIRQ实质上是一个标号,对应一个具体的地址。其中保存的内容就是对应IRQ处理函数的地址。但是在代码中只有一个HandlerIRQ,形式如下
HandlerIRQ
HANDLER HandleIRQ


2HandlerIRQ
HANDLER HandleIRQ

根据上面的宏定义,可以将这句代码进行扩展,得到如下的形式:
HandlerIRQ


sub
sp,sp,#4


stmfd
sp!,{r0}

ldr
r0,= HandleIRQ


ldr
r0,[r0]


str
r0,[sp,#4]


ldmfd
sp!,{r0,pc}


继承事业,薪火相传
返回列表