ARM裸机开发(二)中断编程
以下裸机程序基于GT2440,编译器为arm-linux-gcc-4.4.3。
程序布局:源代码由interrupt.S和led.c两个文件组成,interrupt负责初始化工作,led.c里定义了中断处理程序。
程序流程:首先安装异常向量表,在复位异常里关闭看门狗,然后进入普通中断模式,设置普通中断的栈指针(为C语言写的中断处理程序做准备),接着设为特权模式,初始化中断(设置IO管脚,开启中断),最后CPU一直死循环等待外部中断触发。当外部中断到来时,先保护现场,跳到led.c里的handle_irp()函数,在该函数里将四个LED点亮,接着返回,最后恢复现场,返回到死循环。
interrupt.S:
1 //寄存器物理地址宏定义 2 #define WTCON 0x53000000 3 4 #define GPFCON 0x56000050 5 #define nGPF_INT2 (0x02<<4) 6 #define nGPF_INT0 (0x02<<0) 7 #define EXINT0 0x56000088 8 9 #define SRCPND 0X4A000000 10 #define INTMOD 0X4A000004 11 #define INTMSK 0x4A000008 12 #define PRIORITY 0x4A00000C 13 #define INTPND 0X4A000010 14 #defind INTOFFSET 0x4A000014 15 16 17 .section .text 18 .global _start 19 _start: 20 @异常向量表 21 b reset 22 b underfinded_instruction 23 b soft_interrupt 24 b abort_prefetch 25 b abort_data 26 b reserved 27 b irq 28 b fiq 29 30 31 @复位异常 32 reset: 33 bl disable_watchdog @跳到关闭看门狗程序 34 msr cpsr_c,#0xd2 @进入普通中断模式 35 ldr sp,=3072 @设置栈指针 36 msr cpsr_c,#0xdf @设为特权模式 37 38 bl init_int @跳到中断初始化程序 39 loop: 40 b loop @死循环 41 42 43 @关闭看门狗 44 disable_watchdog: 45 ldr r0,=WTCON 46 bic r1,r0,#0x20 47 str r1,[r0] 48 49 mov pc,lr 50 51 52 @中断初始化 53 init_int: 54 @开启EXINT2 55 ldr r0,=INTMSK 56 ldr r1,[r0] 57 bic r1,r1,#0x04 58 str r1,[r0] 59 @GPF2设为外部中断功能 60 ldr r0,=GPFCON 61 ldr r1,=nGPF_INT2 62 str r1,[r0] 63 @EXINT2下降沿触发中断 64 ldr r0,=EXINT0 65 mov r1,#0x0200 66 str r1,[r0] 67 msr cpsr_c,#0x5f @打开cpu中断 68 69 mov pc,lr 70 71 72 @普通中断异常入口 73 irq: 74 sub lr,lr,#4 @修正返回地址 75 stmdb sp!,{r0-r12,lr} @寄存器入栈 76 ldr lr,=int_return @设置中断处理程序返回地址 77 ldr pc,=handle_irq @跳到中断处理程序(led.c里) 78 int_return: 79 ldmia sp!,{r0-r12,pc}^ @中断异常返回,寄存器出栈和恢复cpsr寄存器 80 81 82 83 underfinded_instruction: 84 b underfinded_instruction 85 soft_interrupt: 86 b soft_interrupt 87 abort_prefetch: 88 b abort_prefetch 89 abort_data: 90 b abort_data 91 reserved: 92 b reserved 93 fiq: 94 b fiq
led.c:
1 #define GPBCON (*(volatile unsigned long *)0x56000010) 2 #define GPBDAT (*(volatile unsigned long *)0x56000014) 3 #define GPBUP (*(volatile unsigned long *)0x56000018) 4 5 #define nGPB_OUTPUT ((1<<10)|(1<<12)|(1<<14)|(1<<16)) 6 7 #define SRCPND (*(volatile unsigned long *)0X4A000000) 8 #define INTPND (*(volatile unsigned long *)0X4A000010) 9 10 void handle_irq() 11 { 12 GPBCON = nGPB_OUTPUT;//IO设为输出 13 GPBDAT = 0x0;//输出低电平 14 15 //清中断源 16 SRCPND = 0x04; 17 INTPND = 0x04; 18 }
Makefile:
1 interrupt.bin: 2 arm-linux-gcc -c -o interrupt.o interrupt.S 3 arm-linux-gcc -c -o led.o led.c 4 arm-linux-ld -Ttext 0x00000000 interrupt.o led.o -o interrupt_elf 5 arm-linux-objcopy -O binary -S interrupt_elf interrupt.bin 6 rm -f interrupt_elf interrupt.o led.o 7 8 clean: 9 rm -f interrupt.bin
执行make之后通过BIOS下载到nand flash,从nand flash启动。