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 }

 

posted on 2019-06-09 08:07  Red_Point  阅读(336)  评论(0)    收藏  举报

导航