DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 285|回复: 0
打印 上一主题 下一主题

ARM中断实现过程的个人笔记

[复制链接]
跳转到指定楼层
楼主
发表于 2012-1-27 19:26:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  
         
   
决定开始学习嵌入式后,最先做的事情就是要熟悉ARM指令及其伪指令伪操作。ARM指令的助记符其实都是其具体功能的单次缩写,所以学习的过程中最好利用网络,从一些文献或书籍中找到ARM指令助记符的全称,这样方便记忆。学完之后,我做了整理了一个有关这方面的笔记.
  
    接下来的学习过程中,比较难以理解的是ARM的中断过程和存储系统。ARM中断的实现有些书上看一两遍也不见得能够完全理解,当然可能只对于像我一样跨专业的朋友来说存在这个问题。这次只谈中断。由于是初学者,难免会出错,敬请各位指正。
  
    当一个程序正常执行过程中,CPU可能检测到有某个中断源发出中断请求,这时ARM硬件实现了程序强制跳转,在这之前保存了相关信息,以便程序正常返回。如果是发生了Reset中断,程序实现系统初始化设置。
    开始比较难以理解的是中断产生后,程序都进行了哪些操作。我就从跟踪PC作为分析的主线。以发生FIQ中断为例。(只以ROM起始地址为0为例,不为0的情况参照存储地址映射)
    最简单的是中断发生后,PC=0x08,在此地址处存放一个跳转指令,跳转到相关处理程序。当然多数情况中断处理程序可能比较复杂,并且要处理多种中断的情况下,采用一步映射两步跳转(我自己起的名字,不一定妥当)。如下图所示:
     
一步映射指,在RAM地址中建立一个中断向量表,图中该表起始地址为0x400000,在该表中存放的是中断处理函数的入口地址。两步跳转是指,当中断发生时,由于系统硬件强制程序跳转到了0x08处,在该地址处是一个跳转指令,跳转到中断函数地址解析程序IRQ_Handler,完成一步跳转。解析程序(IRQ_Handler)的作用无非是把中断向量表内中断处理函数(SystemIrqHandler)的入口地址赋值给 PC,如图所示PC=0x003000280,完成第二步跳转,开始处理中断。在中断处理函数的最后,恢复中断开始时保存的相关寄存器的值,完成中断。
  
下面以一个实例来具体说明中断建立及实现的过程。
  
首先通过伪指令建立一个中断向量表,用于存放中断程序的入口地址(如上图中的中断向量表,注意,此时表中还未赋值):  
;/* EXCEPTION HANDLER VECTOR TABLE */  
  
^ DRAM_BASE  
HandleReset # 4  
HandleUndef # 4  
HandleSwi # 4  
HandlePrefetch # 4  
HandleAbort # 4  
HandleReserv # 4  
HandleIrq # 4  
HandleFiq # 4  
  
  
然后定义一个连续的数据段,并把中断处理函数的入口地址值赋给各字单元
ExceptionHandlerTable  
DCD UserCodeArea  
DCD SystemUndefinedHandler  
DCD SystemSwiHandler  
DCD SystemPrefetchHandler  
DCD SystemAbortHandler  
DCD SystemReserv  
DCD SystemIrqHandler  
DCD SystemFiqHandler  
  
  
下面从程序的开始处分析:  
AREA Init, CODE, READONLY  
ENtrY  
/* ROM起始地址向量表 */
B Reset_Handler  
B Undefined_Handler  
B SWI_Handler  
B Prefetch_Handler  
B Abort_Handler  
NOP Reserved vector  
B IRQ_Handler  
B FIQ_Handler  
/* B跳转范围限于+ -32M内*/
  
  
/* 以下是地址解析程序 */
IRQ_Handler  
SUB sp, sp, #4  
STMFD sp!, {r0} FD满递减堆栈 执行寄存器压栈操作.  
LDR r0, =HandleIrq  //对应程序开始处以伪指令定义的向量表
LDR r0, [r0]  //中断处理函数的地址赋给R0.  
Str r0, [sp, #4]  //中断处理函数的地址入栈  
LDMFD sp!, {r0, pc} //实现程序跳转,目前没明白为什么又给r0赋值?  
  
  
上面提到了还没有给中断向量表赋值,下面代码把中断处理函数的地址放到DRAM中断向量表里
EXCEPTION_VECTOR_TABLE_SETUP  
LDR r0, =HandleReset  
LDR r1, =ExceptionHandlerTable  
MOV r2, #8  
ExceptLoop  
LDR r3, [r1], #4  
Str r3, [r0], #4  
SUBS r2, r2, #1 Down Count  
BNE ExceptLoop ;;  
  
  
下面是中断处理函数  
SystemIrqHandler  
IMPORT ISR_IrqHandler  
STMFD sp!, {r0-r7, lr}  
BL ISR_IrqHandler  
LDMFD sp!, {r0-r7, lr}  
SUBS pc, lr, #4  
  
它实际上只调用了下面的C语言的中断处理函数,其他什么也没做。  
void ISR_IrqHandler(void)  
{  
IntOffSet = (U32)INTOFFSET;  
(IntOffSet>>2)  
(*InterruptHandlers[IntOffSet>>2])(); // Call interrupt service routine  
}  
  
以上编程思路是,先在系统初始化时重新建立一个中断向量表,并把相关的中断处理函数的地址放到中断向量表中。当系统监测到有中断源请求服务后,硬件实现pc跳转到地址0x08处,执行一个跳转指令B IRQ_Handler  , 然后执行地址解析程序,把中断向量表中的中断处理函数的入口地址赋给pc,开始响应中断。在中断处理函数的最后,执行
LDMFD sp!, {r0-r7, lr}  
SUBS pc, lr, #4  
实现中断的返回。

         
          [/td]
        [/tr]
      
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2025-7-27 07:31 , 耗时 0.105542 秒, 18 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表