先把代码贴上,后续再去进行详细介绍,总共需要这么几个文件:
head.S, init.c, interrupt.c, main.c, Makefile
详情可以从这个地方下载:
mini2440 按键中断点亮led灯裸机代码http://www.jyguagua.com/bbs/forum.php?mod=viewthread&tid=184&fromuid=1
head.S内容:
@******************************** @file: head.S @功能:初始化,设置中断模式,系统模式,设置好中断处理函数 @******************************** .extern main .text .global _start _start: @******************************* @这段代码只核心写中断向量 @******************************* b Reset @0x04:未定义指令终止模式的向量地址 HandleUndef: b HandleUndef @定义软中断的向量地址 HandleSWI: b HandleSWI @定义欲取址中断异常向量地址 HandlePrefectchAbort: b HandlePrefectchAbort @定义数据中止异常 HandleDataAbort: b HandleDataAbort @定义保留向量地址 HandleNotUsed: b HandleNotUsed @定义中断的向量地址 b HandleIRQ @定义快中断的向量地址 HandleFIQ: b HandleFIQ @reset的处理函数 Reset: ldr sp, =4096 @先设置栈指针,以下都是C语言需要设置栈指针 bl disable_watch_dog @跳到init.c文件去执行 msr cpsr_c, #0xd2 @进入中断模式 ldr sp, =3072 @中断模式的栈指针定义 msr cpsr_c, #0xdf @进入系统模式 ldr sp, =4096 @设置系统模式的栈指针 bl init_led @初始化led,使其均输出状态而且熄灭,在init.c bl init_irq @调用init.c中的init_irq函数,初始化中断各个寄存器配置 msr cpsr_c, #0x5f @开启IRQ中断 ldr lr, =halt_loop @设置返回地址 ldr pc, =main @跳到main函数执行 halt_loop: b halt_loop HandleIRQ: sub lr, lr, #4 @计算中断的返回地址 stmdb sp!, {r0-r12, lr} @保存使用到的寄存器 ldr lr, =int_return ldr pc, =EINT_Handle @调用中断处理函数 int_return: ldmia sp!, {r0-r12, pc}^
init.c 内容:
/*初始化GPIO引脚为外部中断 * GPIO引脚用作外部中断,默认为低电平触发,IRQ方式 * */ #define WTCON (*(unsigned long *)0x53000000) #define GPGCON (*(unsigned long *)0x56000060) #define EINTMASK (*(unsigned long *)0x560000a4) #define INTMSK (*(unsigned long *)0X4A000008) /*led寄存器*/ #define GPBCON (*(unsigned long *)0x56000010) #define GPBDAT (*(unsigned long *)0x56000014) #define GPBUP (*(unsigned long *)0x56000018) void disable_watch_dog(void) { //关闭看门狗 WTCON = 0; } void init_led(void) { //设置led引脚为输出引脚,初始化都熄灭而且上拉电阻disable GPBCON = (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16); GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8); GPBUP |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8); } void init_irq() { GPGCON = (10) | (10 << 6) | (10 << 10) | (10 << 12); //设置EINT8, 11, 13, 14 INTMSK &= (~(1 << 5)); //开启总中断屏蔽 EINTMASK &= (~(1 << 8)) & (~(1 << 11)) & (~(1 << 13)) & (~(1 << 14)); //开启对应的外部中断 }
interrupt.c内容:
#define INTOFFSET (*(unsigned long *)0x4A000014) #define EINTPEND (*(unsigned long *)0x560000a8) #define GPBCON (*(unsigned long *)0x56000010) #define GPBDAT (*(unsigned long *)0x56000014) #define GPBUP (*(unsigned long *)0x56000018) #define INTPND (*(unsigned long *)0X4A000010) #define SRCPND (*(unsigned long *)0X4A000000) void EINT_Handle() { unsigned long oft = INTOFFSET; unsigned long val; switch (oft) { case 5: { GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8); //判断到底是哪个按键按下的 val = EINTPEND; if (val & (1 << 8)) { //点亮第一个灯 GPBDAT &= ~(1 << 5); } if (val & (1 << 11)) { //点亮第二个灯 GPBDAT &= ~(1 << 6); } if (val & (1 << 13)) { //点亮第三个灯 GPBDAT &= ~(1 << 7); } if (val & (1 << 14)) { //点亮第四个灯 GPBDAT &= ~(1 << 8); } break; } default: break; } //清除中断 if (oft == 5) { EINTPEND = (1 << 8) | (1 << 11) | (1 << 13) | (1 << 14); } SRCPND = 1 << oft; INTPND = 1 << oft; }
main.c内容如下:
int main() { while(1); return 0; }
Makefile的内容如下:
objs := head.o init.o interrupt.o main.o int.bin: $(objs) arm-linux-ld -Ttext 0x00000000 -o int_elf $^ arm-linux-objcopy -O binary -S int_elf $@ arm-linux-objdump -D -m arm int_elf > int.dis %.o:%.c arm-linux-gcc -Wall -O2 -c -o $@ $< %.o:%.S arm-linux-gcc -Wall -O2 -c -o $@ $< clean: rm -f int.bin int_elf int.dis *.o
文章的脚注信息由WordPress的wp-posturl插件自动生成