中断实验(2)
2011-11-30 09:20
78 查看
接上一篇文章,上面写到外部中断的3层屏蔽。由于我们今天用到的器材TQ2440,的4个按键K1~K4使用的是
EINT0、EINT1、EINT2、EINT4,这四个中断,其中三个都只需要打开最后一级屏蔽。
下面我们一边对着代码一边介绍怎样打开屏蔽。最后实现中断。首先,我们的程序包含4个需要自己编写的文件,head.S init.c interrupt.c main.c
首先看head.S,是用汇编写成的,基本定义了整个程序的框架。
EINT0、EINT1、EINT2、EINT4,这四个中断,其中三个都只需要打开最后一级屏蔽。
下面我们一边对着代码一边介绍怎样打开屏蔽。最后实现中断。首先,我们的程序包含4个需要自己编写的文件,head.S init.c interrupt.c main.c
首先看head.S,是用汇编写成的,基本定义了整个程序的框架。
.extern main .text .global _start_start: b Reset @一开始先定义中断向量表,这个必须按照arm说明书上规定的终端向量位置来写,如果写的位置不对,是无法进行中断跳转的,比如在地址0x0位置就一定是 “复位中断” HandleUndef: b HandleUndef @0x04 未定义指令终止模式的向量地址 HandleSWI: @0x08 管理模式的向量地址,通过SWIft指令进入此向量地址 b HandleSWI HandlePrefetchAbort: b HandlePrefetchAbort @0x0c指令预取终止导致的异常的向量地址 HandleDataAbort: b HandleDataAbort @0x10数据访问终止导致的异常的向量地址 HandleNotUsed: b HandleNotUsed @0x14保留 b HandleIRQ @0x18这个就是我们要用到的IRQ中断,0x18是它的向量地址,有人可能要问为什么这里的写法和上面不同,没有HandleIRQ:这个标签。这是因为我们会在下面详细定义,如果像上面那样写,其实是相当于,假如发生了DataAbort中断,就只能在一个死循环里不断运行。 HandleFIQ: @0x1c快中断模式的向量地址 b HandleFIQ Reset: @这里就开始详细定义系统复位指令 ldr r0,=0x53000000 @下面这3句汇编实现了一个功能:关看门狗 mov r1,#0x0 str r1,[r0] msr cpsr_c,#0xd2 @在arm汇编中,唯一能更改cpsr的指令就是msr, cpsr_c是CPSR的低8位, 下面我们来认真分析一下,首先把0xd2换算成2进制,就是110 10010,可参见CPSR各bit的定义,可知CPSR的低5位是工作模式位,如果定义为10010就是进入IRQ(中断模式), 于是这条指令的意义就是进入中断模式 ldr sp,=3072 @进入中断模式后,这里设置了中断模式下的栈指针,请注意,中断模式是有自己的堆栈寄存器的,就是r13,在这里设置好堆栈指针是因为我们后面会用到 msr cpsr_c,#0xdf @回到系统模式 ldr sp,=1024*4 @设置系统模式的栈指针,注意,在这里设置栈指针也是为后面使用C语言服务。 bl init_irq @跳转到init_irq,这里直接跳转到了C语言的标签,init_irq,其实就是init_irq函数, 这个函数会在后文详细解释,作用是初始化IRQ中断 msr cpsr_c,#0x5f @这里打开了IRQ中断,同样把0x5f换算成2进制,010 11111,后5位不变,依然在系统模式下,前3位,第一位就是IRQ禁止位,设置为0就是打开IRQ中断。 ldr lr,=halt_loop @设置返回地址,arm的返回地址都放在lr寄存器中,lr寄存器就是r14 ldr pc,=main @调用main函数 halt_loop: @下面是一个死循环 b halt_loop HandleIRQ: @注意,这里就是我们前面提到的,详细定义处理IRQ中断的标签。 sub lr, lr,#4 @计算返回地址,由于进入异常工作模式时,连接寄存器中保存了前一工作模式的一个指令地址,将它减去一个适当的值,最后付给pc寄存器就可以完成退出中断,具体减去的值需要查表 stmdb sp!, { r0-r12,lr } @这一条指令一步就完成了保存现场的任务,将R0~R12还有lr的数据保存在堆栈寄存器中,堆栈寄存器在保存第一个值之前增加,增长方式为向下增长。sp指针我们在之前定义过了,现在就用到了 ldr lr,=int_return @设置调用EINT_Hanle函数后的返回地址 ldr pc,=EINT_Handle @调用中断服务函数,同样是一个C函数,在interrupt.c中,之后会详细介绍. int_return: ldmia sp!, { r0-r12,pc }^ @中断返回,^表示将spsr的值复制到cpsr,同样,相当于一步恢复现场
相关文章推荐
- zedboard的裸机中断实验(一)
- nios II--实验4——按键中断硬件部分
- 51单片机 外部中断实验
- NIOSII按键中断实验
- STM32学习-定时器中断实验
- 实验十五_安装新的int 9中断例程
- Linux 第五周 实验: 分析system_call中断处理过程
- 简单外中断实验(最近又要搞arm相关的东西,复习一下中断)
- arm11 s3c6410 外部中断实验代码
- 【51单片机实验】INT0中断计数
- 嵌入式成长轨迹44 【Zigbee项目】【CC2430基础实验】【定时器中断】
- 汇编语言----实验16--编写包含多个功能子程序的中断例程
- 2013-10-07 实验之按键中断控制Led
- 实验:PIO外部中断
- Zigbee之旅(九):几个重要的CC2430基础实验——系统睡眠及中断唤醒
- 王爽《汇编语言》实验12:编写0号中断的处理程序 解答
- Windows CE6.0中断实验过程
- 外部中断设计实验
- ZigBee基础实验——中断
- S3C2440中断体系结构:外部中断实验