2440_EINT按键裸机
// start.S 文件
.text
.global _start
_start:
b reset
b .
b .
b .
b .
b .
b handle_irq /* 0x18 */
b .
reset:
@shut down the watchdog
ldr r0, =0x53000000
ldr r1, =0x00000000
str r1, [r0]
@init the stack address
ldr r1, =4096
ldr r0, =0x40000000
add sp, r1, r0
bl init_led
bl init_clock
bl init_sdram
msr cpsr, #0xd2 /* CPRS,I,F disable:1101_0010,禁止2种中断开启,现在还不能允许中断 */
ldr sp, =0x34000000 /* 设置中断模式下的栈指针 */
msr cpsr, #0xd3 /* 1101_0010,禁止2种中断开启,现在还不能允许中断 */
ldr sp, =0x33F00000 /* 设置系统模式下的栈指针 */
bl copy_code2sdram /* 代码重定位 */
/* ldr是载入内存到寄存器,定义就是如此,只能是操作内存的数据,所以能实现转入到sdram中执行 */
ldr pc, =on_sdram
on_sdram:
bl init_interrupt
msr cpsr, #0x53 /* clear the irq disable bit in cpsr;IRQ允许,FIQ禁止,且模式码为:IRQ模式,T=1禁止thumb指令 */
bl main
halt_loop:
b halt_loop
/* 这里是理解中断执行流程的关键:
∵ bl执行的时候会将当前PC指针值(下一条指令的地址)存到 lr 寄存器备份;
∴ lr - 4就是 : b lalt_loop 的PC值 - 4 即: bl main ,跳转函数执行完后恢复到 pc寄存器里;
=> 下面的跳转函数执行后又跳到 bl main 了。
*/
handle_irq:
sub lr, lr, #4 @set the address(int main function) to return when handle_irq ends
stmdb sp!, {r0-r12, lr} @save the universal registers and lr_irq to the stack of irq mode
bl Eint_handler @branch to the irq handleing function achieved in function.c
ldmia sp!, {r0-r12, pc}^ @resume the universal registers and save lr to pc while copying spsr to cpsr
/* 将栈里的寄存器恢复到通用寄存器和 PC,又回到执行 main */
//function.c
1 /* gpb registers */
2 #define GPBCON (*((volatile unsigned long *)0x56000010))
3 #define GPBUP (*((volatile unsigned long *)0x56000018))
4 #define GPBDAT (*((volatile unsigned long *)0x56000014))
5
6 /* mem controler registers */
7 #define BWSCON (*((volatile unsigned long *)0x48000000))
8 #define BANKCON0 (*((volatile unsigned long *)0x48000004))
9 #define BANKCON1 (*((volatile unsigned long *)0x48000008))
10 #define BANKCON2 (*((volatile unsigned long *)0x4800000C))
11 #define BANKCON3 (*((volatile unsigned long *)0x48000010))
12 #define BANKCON4 (*((volatile unsigned long *)0x48000014))
13 #define BANKCON5 (*((volatile unsigned long *)0x48000018))
14 #define BANKCON6 (*((volatile unsigned long *)0x4800001C))
15 #define BANKCON7 (*((volatile unsigned long *)0x48000020))
16 #define REFRESH (*((volatile unsigned long *)0x48000024))
17 #define BANKSIZE (*((volatile unsigned long *)0x48000028))
18 #define MRSRB6 (*((volatile unsigned long *)0x4800002C))
19 #define MRSRB7 (*((volatile unsigned long *)0x48000030))
20
21 /* gpg registers */
22 #define GPGCON (*((volatile unsigned long *)0x56000060))
23
24 /* gph registers */
25 #define GPHCON (*((volatile unsigned long *)0x56000070))
26 #define GPHUP (*((volatile unsigned long *)0x56000078))
27
28 #define EXTINT1 (*((volatile unsigned long *)0x5600008c))
29 #define EXTINT2 (*((volatile unsigned long *)0x56000090))
30 /* interrupt related registers */
31 #define PRIORITY (*((volatile unsigned long *)0x4A00000C))
32 #define EINTMASK (*((volatile unsigned long *)0x560000A4))
33 #define INTMSK (*((volatile unsigned long *)0x4A000008))
34 #define INTMOD (*((volatile unsigned long *)0x4A000004))
35 #define INTOFFSET (*((volatile unsigned long *)0x4A000014))
36 #define SRCPND (*((volatile unsigned long *)0x4A000000))
37 #define INTPND (*((volatile unsigned long *)0x4A000010))
38 #define EINTPEND (*((volatile unsigned long *)0x560000A8))
39 #define INTSUBMSK (*((volatile unsigned long *)0x4A00001C))
40 #define SUBSRCPND (*((volatile unsigned long *)0x4A000018))
41
42
43 /* PLL related registers */
44 #define LOCKTIME (*((volatile unsigned long *)0x4C000000))
45 #define MPLLCON (*((volatile unsigned long *)0x4C000004))
46 #define CLKDIVN (*((volatile unsigned long *)0x4C000014))
47
48 /* uart0 related registers */
49 #define ULCON0 (*((volatile unsigned long *)0x50000000))
50 #define UCON0 (*((volatile unsigned long *)0x50000004))
51 #define UFCON0 (*((volatile unsigned long *)0x50000008))
52 #define UMCON0 (*((volatile unsigned long *)0x5000000C))
53 #define UBRDIV0 (*((volatile unsigned long *)0x50000028))
54 #define UTRSTAT0 (*((volatile unsigned long *)0x50000010))
55 #define URXH0 (*((volatile unsigned char *)0x50000024))
56 #define UTXH0 (*((volatile unsigned char *)0x50000020))
57 #define UFSTAT0 (*((volatile unsigned long *)0x50000018))
58
59
60 void delay(int n)
61 {
62 int i, j;
63 for(i=0; i<n; i++)
64 {
65 for(j=0; j<1000; j++) ;
66 }
67 }
68
69 void init_led(void)
70 {
71 GPBCON = 0x00015400; /* GPB8,LED8 :GPBCON[17:16] = 01 设置为输出功能 */
72 GPBUP&=~((1<<5)|(1<<6)|(1<<7)|(1<<8));
73 GPBDAT |= (0x0f<<5); /* 4个led都熄灭 */
74 }
75
76 static void light_leds(void)
77 {
78 GPBCON = 0x00015400; /* GPB8,LED8 :GPBCON[17:16] = 01 设置为输出功能 */
79 GPBDAT &= (~(0x0f<<5)); /* 4个led都熄灭 */
80 }
81
82 void init_clock(void)
83 {
84 LOCKTIME = 0xffffffff;
85 CLKDIVN = 0X03; /* fclk:hclk:pclk=1:2:4 */
86 __asm__
87 (
88 "mrc p15, 0, r1, c1, c0, 0\n"
89 "orr r1, r1, #0xc0000000\n"
90 "mcr p15, 0, r1, c1, c0, 0\n"
91 );
92 MPLLCON = (92<<12)|(1<<4)|(2<<0); /* fclk=200M, hclk=100M, pclk=50M */
93 }
94
95
96 void light_led1(void)
97 {
98 GPBDAT &= ~(1<<5); // led1点亮
99 }
100
101 void light_led2(void)
102 {
103 GPBDAT &= ~(1<<6); // led2点亮
104 }
105
106 void light_led3(void)
107 {
108 GPBDAT &= ~(1<<7); //led3点亮
109 }
110
111 void light_led4(void)
112 {
113 GPBDAT &= ~(1<<8); //led4点亮
114 }
115
116 static void black_led(void)
117 {
118 init_led();
119 }
120
121 void init_sdram(void)
122 {
123 BWSCON = 0x22011110;
124 BANKCON0 = 0x00000700;
125 BANKCON1 = 0x00000700;
126 BANKCON2 = 0x00000700;
127 BANKCON3 = 0x00000700;
128 BANKCON4 = 0x00000700;
129 BANKCON5 = 0x00000700;
130 BANKCON6 = 0x00018005;
131 BANKCON7 = 0x00018005;
132
133 //when hcls is 12MHz
134 //REFRESH = 0x008C07A3;
135
136 //when hckl is 100MHz
137 REFRESH = 0x008C04F4;
138
139 BANKSIZE = 0x000000B1;
140 MRSRB6 = 0x00000030;
141 MRSRB7 = 0x00000030;
142 }
143
144 void copy_code2sdram(void)
145 {
146 int size, i;
147 unsigned char *src, *des;
148 size = 8*1024;
149
150 des = (unsigned char*)(0x30000000);
151 src = (unsigned char *)(0x00000000);
152 for(i=0; i<size; i++)
153 {
154 *(des++) = *(src++);
155 }
156 }
157
158
159 #define EINT8 0
160 #define EINT11 6
161 #define EINT13 10
162 #define EINT14 12
163 #define EINT15 14
164 #define EINT19 22
165
166 #define LOW_LEVEL 000 //Low level 低电平触发
167
168 void init_interrupt(void)
169 {
170 /* 设置6个按键的gpio为外部中断模式 */
171 GPGCON = (2<<EINT8 | 2<<EINT11 | 2<<EINT13 | 2<<EINT14 | 2<<EINT15 | 2<<EINT19);
172
173 /* 设置触发方式:K1,K6上拉的设置为下降沿触发,其他的下拉设置为上升沿触发 */
174 EXTINT1 &= (LOW_LEVEL<<0) |(LOW_LEVEL<<12)|(LOW_LEVEL<<20)|(LOW_LEVEL<<24)|(LOW_LEVEL<<28);
175 EXTINT2 &= (LOW_LEVEL<<12);
176
177 /* 设置 EINTMASK 外部中断屏蔽寄存器 */
178 EINTMASK &= (~(1<<8 | 1<<11 | 1<<13 | 1<<14 | 1<<15 | 1<<19));
179
180 /* 设置 INTMSK 中断屏蔽寄存器使能 eint8_23 中断;
181 * 默认是屏蔽eint8_23的;
182 * 外部中断要设置专门的 EINTMASK 来打开,然后再送入INTMSK再次打开,几级开关作用;
183 * (程序里可以实验确认一下)。
184 */
185 INTMSK &= (~(1<<5));
186 /* 即使这里打开了中断使能,start.S的这里msr cpsr, #0x53才算打开中断(总开关) */
187
188
189 /* INTMOD默认的就是0x0,IRQ模式,可以显式的设置,也可以不设置就是默认为0x0 */
190
191
192 /* 设置中断优先级PRIORITY寄存器
193 * ARB_MODE1 = 0b 使用的中断少,不轮换; ARB_SEL1 = 00b:REQ1,5不变,REQ/EINT8~23放在前面。
194 */
195 PRIORITY &= (~((0x2)|(0x3 << 8 )) );
196 }
197
198 #define KEY1 0x100 /*外部中断8 */
199 #define KEY2 0x800 /*外部中断11 */
200 #define KEY3 0x2000 /*外部中断13 */
201 #define KEY4 0x4000 /*外部中断14 */
202 #define KEY5 0x8000 /*外部中断15 */
203 #define KEY6 0x90000 /*外部中断19 */
204
205
206 void Eint_handler(void)
207 {
208 unsigned long val = EINTPEND;
209
210 switch(val)
211 {
212 case KEY1:
213 {
214 black_led();
215 light_led1();
216 break;
217 }
218 case KEY2:
219 {
220 black_led();
221 light_led1();
222 light_led2();
223 break;
224 }
225 case KEY3:
226 {
227 black_led();
228 light_led1();
229 light_led2();
230 light_led3();
231 break;
232 }
233 case KEY4:
234 {
235 black_led();
236 light_led1();
237 light_led2();
238 light_led3();
239 light_led4();
240 break;
241 }
242 case KEY5:
243 {
244 black_led();
245 light_led4();
246 light_led1();
247 break;
248 }
249 case KEY6:
250 {
251 black_led();
252 light_led4();
253 light_led2();
254 break;
255 }
256
257 default:
258 break;
259 }
260
261
262 /* 清除中断标志:清除的顺序很重要,先EINTPEND,再SRCPND,最后INTND,;
263 * 因为前面会自动传给后边的xxxPND,所以先清掉前面的。
264 */
265
266 if( 5 == INTOFFSET )
267 EINTPEND |= (1<<8) |(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19);
268
269 SRCPND = 1<<5;
270 INTPND = 1<<5;
271
272 }
273
274
275 int main(void)
276 {
277 while(1)
278 {
279 /* waiting for interrupt
280 puts_uart0_fifo("Hello world\r\n");
281 puts_uart0_fifo("this is a test of uart0\r\n");
282 */
283 }
284 return 0;
285 }
浙公网安备 33010602011771号