本帖最后由 维C1° 于 2013-10-27 16:55 编辑
;@******************************************************************************
;@ File:head.S
;@ 功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
;@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用,所以不用定义
;@******************************************************************************
IMPORT disable_watch_dog
IMPORT init_led
IMPORT init_irq
IMPORT main
IMPORT EINT_Handle
IMPORT close_leds
AREA head, CODE, READONLY ;该伪指令定义了一个代码段,段名为head,属性只读
ENTRY
b Reset
HandleUndef
b HandleUndef ;@ 0x04: 未定义指令中止模式的向量地址
HandleSWI
b HandleSWI ;@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandlePrefetchAbort
b HandlePrefetchAbort ;@ 0x0c: 指令预取终止导致的异常的向量地址
HandleDataAbort
b HandleDataAbort ;@ 0x10: 数据访问终止导致的异常的向量地址
HandleNotUsed
b HandleNotUsed ;@ 0x14: 保留
b HandleIRQ ;@ 0x18: 中断模式的向量地址
HandleFIQ
b HandleFIQ ;@ 0x1c: 快中断模式的向量地址
Reset
ldr sp, =4096 ;@ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog ;@ 关闭WATCHDOG,否则CPU会不断重启
msr cpsr_c, #0xd2 ;@ 进入中断模式
ldr sp, =3072 ;@ 设置中断模式栈指针
msr cpsr_c, #0xdf ;@ 进入系统模式
ldr sp, =4096 ;@ 设置系统模式栈指针,
;@ 其实复位之后,CPU就处于系统模式,
;@ 前面的“ldr sp, =4096”完成同样的功能,此句可省略
bl init_led ;@ 初始化LED的GPIO管脚
bl init_irq ;@ 调用中断初始化函数,在init.c中
msr cpsr_c, #0x5f ;@ 设置I-bit=0,开IRQ中断
ldr lr, = halt_loop ; @ 设置返回地址
ldr pc, = main ;@ 调用main函数
halt_loop
b halt_loop
HandleIRQ
sub lr, lr, #4 ; @ 计算返回地址
stmdb sp!, { r0-r12,lr } ; @ 保存使用到的寄存器
; @ 注意,此时的sp是中断模式的sp
; @ 初始值是上面设置的3072
bl close_leds
ldr lr, =int_return ; @ 设置调用ISR即EINT_Handle函数后的返回地址
ldr pc, =EINT_Handle ; @ 调用中断服务函数,在interrupt.c中
int_return
ldmia sp!, { r0-r12,pc }^ ; @ 中断返回, ^表示将spsr的值复制到cpsr
END
其中中断初始化程序如下
void init_irq( )
{
rGPFCON &=~(0x33f);
rGPFCON |=0x22a; //设置GPF0、1、2、4为中断输入功能
rSRCPND = 0x17; //清除ENIT0、1、2、4的中断标志位
rINTPND = 0x17; //清除ENIT0、1、2、4的中断标志位
rEINTPEND=(1<<4); //清除ENIT4的中断标志位
rINTMSK &= ~0x17; //ENIT0、1、2、4中断服务有效(这里就是使能外部中断)
rEINTMASK &= ~(1<<4);//EINT4中断服务有
}
出现的问题:程序编译成功,下载到板子上,按下按键没有反应,程序进不了中断,是中断入口地址有问题吗?我在HandleIRQ工作模式下增加了一句 bl close_leds,关灯,来测试能否进入中断,但还是没有任何反应,另外,当发生异常时,程序是自动进入相应的工作模式的不是吗? |