GPFCON EQU 0x56000050 GPFDAT EQU 0x56000054 GPGCON EQU 0x56000060 GPGDAT EQU 0x56000064
SRCPND EQU 0X4A000000 INTMSK EQU 0X4A000008 PRIORITY EQU 0x4A00000C INTPND EQU 0X4A000010 INTOFFSET EQU 0x4A000014 EINTMASK EQU 0x560000a4 EINTPEND EQU 0x560000a8
AREA KEY_LED_INT, CODE, READONLY ;这里表示此区域是只读代码"KEY_LED" EXPORT _ENTRY ;引入程序入口 _ENTRY
b START ;程序从START开始执行 b . ;0x4 b . ;0x8 b . ;0xc b . ;0x10 b . ;0x14 b IRQ_HANDLER ;0x00000018中断入口 b . ;0x1c
;程序从这里开始运行 START ldr sp, =4096 ;初始化当前模式(系统模式)栈指针 msr cpsr_c, #0x92 ;设置当前模式为中断模式 ldr sp, =3072 ;初始化中断模式的栈指针 bl INIT_CONF ;跳转到中断初试化 msr cpsr_c, #0x5f ;定义当前模式为系统模式,并开启中断允许 LOOP ;将LED熄灭 ldr r0, =GPFDAT mov r1, #0xff str r1, [r0] b LOOP
INIT_CONF ;GPIO的配置 ;这里包括K1~K4中断配置和LED1~LED4的配置 ldr r0, =GPFCON ldr r1, =0x55aa str r1, [r0] ;K5和K6的配置,配置成中断模式 ldr r0, =GPGCON ldr r1, =0x00800080 str r1, [r0] ;初始化将led都熄灭 ldr r0, =GPFDAT mov r1, #0xf0 str r1, [r0] ;初始化中断屏蔽位 ldr r0, =INTMSK ldr r1, = 0xffffffd0 str r1, [r0]
;初始化外中断屏蔽位 ldr r0, =EINTMASK ldr r1, = 0xf7f7ff ; str r1, [r0] ;函数返回 mov pc, lr IRQ_HANDLER ;返回地址等于中断地址减4 sub lr, lr, #4 ;保存现场 stmdb {r0-r12,lr} ;得到offset寄存器的值,它反映了触发中断的中断号 ldr r0, =INTOFFSET ldr r2, [r0] ;得到LED的状态数据寄存器 ldr r0, =GPFDAT ldr r1, [r0] ;判断是否触发了INT0,即按键1的中断 cmp r2, #0 ;是则重新布置LED状态 moveq r1, #0xef beq INIT_OVER ;INT1,按键2 cmp r2, #1 moveq r1, #0xdf beq INIT_OVER ;INT2,按键3 cmp r2, #2 moveq r1, #0xcf beq INIT_OVER ;INT3, 按键4 cmp r2, #3 moveq r1, #0xbf beq INIT_OVER ;INT5,它可能是按键5和6发生了中断,按键5和6引脚比较特殊 cmp r2, #5 ;如果不是,跳转到结束标志 bne INIT_OVER ;如果是,就看EINTPEND的值,它必定有一个中断被置1 ldr r2, =EINTPEND ldr r3, [r2] ;如果是11号引脚发生中断,即按键5发生了中断 tst r3, #0x800 ;2^11 movne r1, #0xaf bne INIT_OVER ; 如果是19号引脚发生中断,即按键6发生了中断 tst r3, #0x80000 ;2^19 movne r1, #0x9f bne INIT_OVER INIT_OVER ;更新LED状态 str r1, [r0] ;清除所有中断 ldr r0, =EINTPEND mov r1, #0xfffffff str r1, [r0] ldr r0, =INTPND mov r1, #0xff str r1, [r0] ldr r0, =SRCPND mov r1, #0xff str r1, [r0]
;恢复现场 ldmia {r0-r12,pc}^ END
|