1.启动程序start.S
前面已介绍过,S5PV210本身的固化代码(iROM)在上电后配置好IRQ中断的栈,以及系统模式所使用的栈,所以在启动代码中可以不用设置这些栈(如果重新配置也可以),所以实验的启动程序比较简单,主要是当中断发生时先保存现场,跳到中断服务程序执行中断处理,处理结束再恢复现场。具体代码示例如下:
01 .text
02 .global _start/*声明一个全局的标号*/
03 .global IRQ_handle
04_start:
06mrs r0,cpsr
07bic r0,r0,#0x00000080/*使能IRQ中断bit[7]=0 */
08msr cpsr,r0
09bl main
10 halt_loop:
11bhalt_loop/*死循环,不让程序跑飞*/
12
13 IRQ_handle:
14sub lr, lr, #4/*计算返回地址*/
15stmdb sp!, {r0-r12, lr} /*保存用到的寄存器*/
16bl irq_handler/*跳到中断服务函数*/
17ldmia sp!, {r0-r12, pc}^/*中断返回, ^表示将spsr的值复制到cpsr */
2.初始化阶段
初始化阶段重点讲下外部中断控制寄存器的配置方法,以及中断向量控制寄存器的设置,关于LED相关的引脚配置不作重复介绍。
……
08 #define GPH0CON*((volatile unsigned int *)0xE0200C00)
09 #define GPH0DAT*((volatile unsigned int *)0xE0200C04)
10 #define EXT_INT_0_CON*((volatile unsigned int *)0xE0200E00)
11 #define EXT_INT_0_MASK*((volatile unsigned int *)0xE0200F00)
12
13 #define VIC0IRQSTATUS*((volatile unsigned int *)0xF2000000)
14 #define VIC0INTSELECT*((volatile unsigned int *)0xF200000C)
15 #define VIC0INTENABLE*((volatile unsigned int *)0xF2000010)
16 #define VIC0VECTADDR0*((volatile unsigned int *)0xF2000100)
17 #define VIC0VECTADDR1*((volatile unsigned int *)0xF2000104)
18 #define VIC0ADDRESS*((volatile unsigned int *)0xF2000F00)
19
20 extern void IRQ_handle(void);
……
38 //配置中断引脚
39 void init_key(void)
40 {
41//配置GPIO引脚为中断功能
42GPH0CON &= ~(0xFF<<0);
43GPH0CON |= (0xFF<<0); // key1:bit[3:0];key2:bit[7:4]
44//配置EXT_INT[0]、EXT_INT[1]中断为下降沿触发
45EXT_INT_0_CON &= ~(0xFF<<0);
46EXT_INT_0_CON |= 2|(2<<4);
47//取消屏蔽外部中断EXT_INT[0]、EXT_INT[1]
48EXT_INT_0_MASK &= ~0x3;
49 }
50//清中断挂起寄存器
51 void clear_int_pend()
52 {
53EXT_INT_0_PEND |= 0x3; // EXT_INT[0]、EXT_INT[1]
54 }
55 //初始化中断控制器
56 void init_int(void)
57 {
58//选择中断类型为IRQ
59VIC0INTSELECT = ~0x3; //外部中断EXT_INT[0]、EXT_INT[1]为IRQ
60//清VIC0ADDRESS
61VIC0ADDRESS = 0x0;
62//设置EXT_INT[0]、EXT_INT[1]对应的中断服务程序的入口地址
63VIC0VECTADDR0 = (int)IRQ_handle;
64VIC0VECTADDR1 = (int)IRQ_handle;
65//使能外部中断EXT_INT[0]、EXT_INT[1]
66VIC0INTENABLE |= 0x3;
67 }
68 //清除需要处理的中断的中断处理函数的地址
69 void clear_vectaddr(void)
70 {
71VIC0ADDRESS = 0x0;
72 }
73 //读中断状态
74 unsigned long get_irqstatus(void)
75 {
76return VIC0IRQSTATUS;
77 }
3.主程序
开发板上电后就会跳到主程序main执行,主程序main中主要是对各初始化函数的调用,另外main.c中还定义了一个中断处理函数,也就是当相应的中断发生后,CPU需要跳过去执行的具体内容,这里主要是点灯或灭灯。
01 extern void init_leds(void);//其他源文件中定义的函数在此声明
02 extern void clear_int_pend();
03 extern void led1_on_off();
04 extern void led2_on_off();
05 extern void init_key(void);
06 extern void init_int(void);
07 extern void clear_vectaddr(void);
08 extern unsigned long get_irqstatus(void);
09 void irq_handler()
10 {
11volatile unsigned char key_code = get_irqstatus() & 0x3;// VIC0's status
12clear_vectaddr();/*清中断向量寄存器*/
13clear_int_pend();/*清pending位*/
14if (key_code == 1)/* key1 */
15led1_on_off();
16else if (key_code == 2) /* key2 */
17led2_on_off();
18else
19{
20led1_on_off();
21led2_on_off();
22}
23 }
24 int main(void)
25 {
26int c = 0;
27
28init_leds();/*初始化GPIO引脚*/
29init_key();/*初始化按键中断*/
30init_int();/*初始化中断控制器、使能中断*/
31
32while (1);
33 }
4.编写Makefile
01 objs := start.o init.o main.o
02
03 int.bin: $(objs)
04arm-linux-ld -Ttext 0xD0020010 -o int.elf $^
05arm-linux-objcopy -O binary -S int.elf $@
06arm-linux-objdump -D int.elf > int.dis
07
08 %.o : %.c
09arm-linux-gcc -c -O2 $< -o $@
10
11 %.o : %.S
12arm-linux-gcc -c -O2 $< -o $@
13
14 clean:
15rm -f *.o *.elf *.bin *.dis
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:宋体; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4
将以上编写好的源代码上传到宿主机上编译生成可执行的目标文件int.bin,然后烧写到开发板上电测试。
实验最终结果是:当按下“KEY1”,LED1灯会被点亮或熄灭;当按下“KEY2”,LED2灯会被点亮或熄灭。/* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:宋体; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;}
/* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:宋体; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;}