Chinaunix首页 | 论坛 | 博客
  • 博客访问: 283629
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 600
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-27 08:37
个人简介

从linux了解世界

文章分类
文章存档

2017年(5)

2016年(51)

2015年(2)

我的朋友

分类: 嵌入式

2016-01-06 11:23:58

最近对比stm32和2440的中断处理,有很多困惑,经过几天的思考和实验终于搞明白了。
stm32和2440虽然都是arm架构,但是stm32在中断上比较特殊,发生不同的中断,硬件上会直接给pc强行赋值,不同的中断对应不同的值。但是2440则是只要有中断就跳到一个固定地址,不论中断是什么跳到的地址都一样。我想这也是为什么stm32在裸机上应用的越来越多的原因之一。(没有深入研究32的中断处理流程,理解有误望告解
s3c2440在没有中断向量表时,每次发生中断都要在中断函数中判断一下是什么中断再跳转,因此我参照stm32的启动文件在自己之前做的启动文件基础上设置了二级向量表实现中断跳转。之前的启动文件可以在前几篇博客下载,mdk自带的启动代码最后会跳到一个_main中做了一些用户看不到的工作,_main还不是开源的,所以启动代码有很多地方不理解,就自己写了一个启动代码除了硬件的初始化,实现了zi段清零和加载程序到sdram执行。这次又添加了中断向量表。
程序的最开始肯定是第一级的异常向量表,这是由硬件决定的,发生7种异常(还有一种保留)分别强制pc取值:
               B         Reset_Addr         
                LDR     PC, =Undef_Addr
                LDR     PC, =SWI_Addr
                LDR     PC, =PAbt_Addr
                LDR     PC, =DAbt_Addr
                LDR     PC,    =HandleNotUsed
                LDR     PC, =IRQ_INT
                LDR     PC, =FIQ_Addr
在IRQ_INT中实现二级向量表跳转
IRQ_INT
                SUB        SP,SP,#4       ;reserved for PC
                STMDB    SP!,{R0-R1}                  
                LDR    R1,=INTOFFSET
                LDR    R1,[R1]
                LDR    R0,=VECTOR
                ADD    R0,R0,R1,LSL #2
                LDR    R0,[R0]
                STR    R0,[SP,#8]
                LDMIA    SP!,{R0-R1,PC} 
在程序的最后是中断向量表(只用外部中断举个例子):
VECTOR    DCD        HandleEINT0
                DCD        HandleEINT1
                DCD        HandleEINT2
                DCD        HandleEINT3
                DCD        HandleEINT4_7
                DCD        HandleEINT8_23
EINT_Handler  PROC
                EXPORT  HandleEINT0               [WEAK]
                EXPORT  HandleEINT1               [WEAK]
                EXPORT  HandleEINT2               [WEAK]
                EXPORT  HandleEINT3               [WEAK]
                EXPORT  HandleEINT4_7           [WEAK]
                EXPORT  HandleEINT8_23          [WEAK]  
HandleEINT0
HandleEINT1
HandleEINT2
HandleEINT3
HandleEINT4_7
HandleEINT8_23      
                LDR        PC,    =HALT
                ENDP
举例说明下weak的作用,当c文件中声明了HandleEINT0函数,则在vector这个标号代表的地址里存入的是c函数HandleEINT0地址,当c文件中没有HandleEINT0函数时,vector这个标号代表的地址里存入的是本文件中HandleEINT0这个标号代表的地址,也就是LDR        PC,    =HALT这条指令的地址。(halt是一段汇编写的蜂鸣器响的死循环
这样在c语言中只要根据中断表的名字写中断函数就可以了,比如void HandleEINT8_23()__irq{}(__irq参照上一篇博客)。
最后还要说一下很有迷惑性的细节问题,当我用汇编写了:
TEST
0000:DCD    0X01
0001:EXPORT    TEST
在c语言中想引用TEST这个标号地址也就是0的时候,这样写:
exterm int TEST
int a=TEST;
这时的a=1,想要实现要这样写a=&TEST
想明白了吧!仔细想想c编译的过程,每一个符号对应的都是地址,a=TEST的意思是从TEST地址中取出数放入a地址中,因此即使在汇编中TEST是0,在c语言也会变成1了!!!这个问题是我在用c语言实现中断向量表时遇到的,浪费了好多时间,最后还是决定简化c语言,把初级工作都在启动代码中用汇编实现。
selfsetup.rar
阅读(2514) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~