在整个ARM体系结构中,为了处理外部中断,依次学习了MMU,模式跳转,异常,GIC,看门狗程序,这些都是为了处理外部中断
具体如下:
处理外部中断有五个步骤:
30 //step 1: cpu cpsr
31 __asm__ __volatile__(
32 'mrs r0, cpsrn'
33 'bic r0, r0, #0x80n'//设置CPSR的I位,将IRQ位打开
34 'msr cpsr, r0n'
35 ::: 'r0'
36 );
37
38 //setp1:GIC
39 ICCICR_CPU0 = 1;
40 ICCPMR_CPU0 = 0xff;
41
前面的代码不解释,和以前的差不多
外部中断号为:64
42 //step2:设置中断号
43 ICDDCR = 1;//总开关
44 ICDIPR16_CPU0 = (0x0 << 0);//ICD一共40个寄存器,第16个寄存器,第0位
45 ICDIPTR16_CPU0 = (0x1 << 0);//优先级,最高
46 ICDISER2_CPU0 = (1 << 0);//一共五个,第2个使能中断
47
第二步为设置中断号:
详细看代码注释:寄存器参考手册第594页
48 //step 3: set gpio
49 GPX3CON = (0xf << 8);//是GPXCON为外部中断功能
查看到使用外部中断功能的对应外部寄存器:EXT_INT43:
51 //step 4: extern
52 EXT_INT43CON = (2 << 8);//设置上升沿触发
53 EXT_INT43MASK = 0;//使能中断
设置外部中断控制器:寄存器参考手册第366页
55 //step 5: source
56 外部中断源这里设置由外部按键K触发:
1 #include'regs.h'
2
3 int (*printf)(char *, ...) = 0xc3e114d8;
4 int(*delay)(int)=0xc3e25f90;
5
6 void init_ttb(unsigned long *addr);
7 void enable_mmu(void);
8 unsigned long data_abort_init();
9 void memcopy(unsigned long* dest,unsigned long* source,int len);
10 void do_irq();
11 void pwm_on(void);
12 void pwm_off(void);
13 void led_on(void);
14 void led_on(void);
15
16 int main()
17 {
18 *(unsigned long *)0x66000000 = do_irq;
19
20 //发生异常时会进入异常模式跳转到0000 0004地址处理异常事件
21 unsigned long source_addr=data_abort_init();
22 //异常事件处理函数
23 printf('swi_souce addr is %xn',source_addr);
24 //将异常处理地址的值放到0x60000004
25 memcopy(0x60000000,source_addr,0x1000);
26
27 enable_mmu();
28 //内存映射将0x00000004映射到0x6000000004
29
30 //step 1: cpu cpsr
31 __asm__ __volatile__(
32 'mrs r0, cpsrn'
33 'bic r0, r0, #0x80n'//设置CPSR的I位,将IRQ位打开
34 'msr cpsr, r0n'
35 ::: 'r0'
36 );
37
38 //setp1:GIC
39 ICCICR_CPU0 = 1;
40 ICCPMR_CPU0 = 0xff;
41
42 //step1:设置中断号
43 ICDDCR = 1;
44 ICDIPR16_CPU0 = (0x0 << 0);//ICD第16个寄存器,第0位
45 ICDIPTR16_CPU0 = (0x1 << 0);//优先级,最高
46 ICDISER2_CPU0 = (1 << 0);//一共五个,第2个使能中断
47
48 //step 3: set gpio
49 GPX3CON = (0xf << 8);//是GPXCON为外部中断功能
50
51 //step 4: extern
52 EXT_INT43CON = (2 << 8);//设置上升沿触发
53 EXT_INT43MASK = 0;//使能中断
54
55 //step 5: source
56 //
57 printf('welcome back! n');
58 }
59
60 void pwm_on(void)
61 {
62 GPD0CON &= ~0xffff;
63 GPD0CON |= 0x1;//配置寄存器为2
64 GPD0DAT |= 0x1;//date=0xf
65 }
66
67 void pwm_off(void)
68 {
69 GPD0CON &= ~0xffff;
70 GPD0CON |= 0x0;
71 // GPD0DAT &=0x0 ;//date=0xf
72
73 }
74 void led_off(void)
75 {
76 GPM4CON &= ~0xffff;//清零
77 GPM4CON |= 0x0000;//0---3位清零
78 GPM4DAT |= 0x0;//date=0xf关闭置一
79 }
80 void led_on(void)
81 {
82 GPM4CON &= ~0xffff;
83 GPM4CON |= 0x1111;//配置寄存器3-0-----3-3全为1111,全为输出模式
84 GPM4DAT &= ~0xf;//打开置0-4位为0000
85 }
86
87 void do_irq()
88 {
89 printf('key 1 downn');
90 static int flag=1;
91 if(flag)
92 {
93 printf('wtc_onn');
94 led_on();
95 pwm_on();
96 flag=0;
97 }
98 else if(flag == 0)
99 {
100 printf('wtc_offn');
101 led_off();
102 pwm_off();
103 flag=1;
104 }
105 EXT_INT43PEND = (1 << 2);//清中断
106 }
107
108 void memcopy(unsigned long* dest, unsigned long* source,int len)
109 {
110 int i=0;;
111 for(i=0;i
113 }
114
115 unsigned long data_abort_init()
116 {
117 unsigned long source;
118 __asm__ __volatile__(
119 'ldr %0, =voliate_startn'
120 : '=r' (source)
121 );
122 return source;
123
124 }
125
126 __asm__(
127
128 'voliate_start:n'
129 //跳转目录
130 ' b resetn'
131 ' b undefinedn'
132 ' b swin'
133 ' b pre_abtn'
134 ' b data_abtn'
135 ' .word 0n'//占位符号,一个位占4个字节
136 ' b irqn'
137 ' b fiqn'
138 'n'
139
140 //跳转要分三部:
141 //1:将PC保存到新模式下的lr中;
142 //2:将CPSR保存在SPSR中
143 //3:初始化SP
144 //前两步由硬件完成,而第三部需要手动完成
145 'reset:n'
146
147 'undefined:n'
148 'mov sp, #0x66000000n'//初始化SP
149 'stmfd sp!, {r0-r12, lr}n'//初始化sp,入栈保护寄存器
150 //打印一句话
151 'ldr r0, =und_stringn'
152 'ldr r2, shown'
153 'blx r2n'
154 //跳回来分两部
155 //1:将CPSR保存在SPSR中
156 //2:将PC保存到新模式下的lr中;
157 'mov sp, #0x66000000n'//
158 'ldmea sp, {r0-r12, pc}^n'//
159
160 'swi:n'
161
162 'pre_abt:n'
163 'data_abt:n'
164 'sub lr, lr, #4n'
165 'mov sp, #0x66000000n'//初始化SP
166 'stmfd sp!, {r0-r12, lr}n'//初始化sp,入栈保护寄存器
167 //打印一句话
168 'ldr r0, =data_stringn'
169 'ldr r2, shown'
170 'blx r2n'
171 //跳回来分两部
172 //1:将CPSR保存在SPSR中
173 //2:将PC保存到新模式下的lr中;
174 'mov sp, #0x66000000n'//
175 'ldmea sp, {r0-r12, pc}^n'//
176
177 'irq:n'
178 'sub lr, lr, #4n'
179 'mov sp, #0x66000000n'//初始化SP
180 'stmfd sp!, {r0-r12, lr}n'//初始化sp,入栈保护寄存器
181 //打印一句话
182 'mov r2, #0x66000000n'
183 'ldr r1, [r2]n'
184 'blx r1n'
185
186 'mov sp, #0x66000000n'//
187 'ldmea sp, {r0-r12, pc}^n'//
188 'fiq:n'
189 'show:n'
190 '.word 0xc3e114d8n'
191
192 'und_string:n'
193 '.asciz 'This is UND! ' n'
194 'data_string:n'
195 '.asciz 'This DATA_ABORT! ' n'
196 'irq_string:n'
197 '.asciz 'This IRQ! ' n'
198
199 );
200
201 void init_ttb(unsigned long *addr)
202 {
203 unsigned long va = 0;//定义虚拟地址
204 unsigned long pa = 0;//定义物理地址
205
206 //40000000-------80000000 ==== 40000000------80000000