新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > S3C2440中断代码的深层次分析

S3C2440中断代码的深层次分析

作者: 时间:2016-12-01 来源:网络 收藏
小结:
我们可以将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))
// Interrupt vector(中断向量)
#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
#define pISR_EINT1 (*(unsigned *)(_ISR_STARTADDRESS+0x24))
#define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28))
#define pISR_EINT3 (*(unsigned *)(_ISR_STARTADDRESS+0x2c))
#define pISR_EINT4_7(*(unsigned *)(_ISR_STARTADDRESS+0x30))
#define pISR_SPI1 (*(unsigned *)(_ISR_STARTADDRESS+0x94))
#define pISR_RTC (*(unsigned *)(_ISR_STARTADDRESS+0x98))
#define pISR_ADC (*(unsigned *)(_ISR_STARTADDRESS+0x9c))
从上面的代码中我们可以知道pISR_EINT0之类的实质上就是一个地址,如果我们在这个地址中填充处理函数的地址值也就形成了函数指针,实际上只需要将函数名赋值给对应的中断向量即可。这样也就找到了适当的处理方式.基本的形式如下所示:
Void main()
{
pISR_EINT0 = (U32)Button_ISR;
While(1)
{
}
}
/*中断服务函数*/
static void _irq Button_ISR(void)
{
}
几个分析的比较清晰的网址可以去看看:
http://blog.sina.com.cn/s/blog_8c134b590100yke9.html
http://hi.baidu.com/%C9%B3%BC%D3%BB%C6%BD%F0%CA%A5%B6%B7%CA%BF/blog/item/fbc56f137f475a085baf5334.html
总结:
问题?在其中的代码中,我并没有看到返回地址的操作问题,我找了很多的代码,但是好像都不是特别的准确。也就是没有找到对应的subs pc, lr, =0x04操作。
代码中经典的片段就是如何实现了代码的跳转问题:
sub sp,sp, #0x04;为保存PC值预留空间
stmfd sp!,{r0};保存需要使用到的寄存器值,需要使用多少,就压多少的堆栈
…//使用r0进行相关的操作
ldr r0,[r0];
str r0, [sp,#0x04]; //这个操作类似于函数调用中的问题
ldmfd sp!,{r0, pc};//出栈操作,实现了对PC值的赋值
上一页 1 2 下一页

评论


技术专区

关闭