Tiny4412之外部中断

 一:外部中断  

   在之前我们学习按键驱动的时候,我们检测按键有没有按下是通过轮循的方式(也就是我们说的死循环),这样虽然可以检测实现按键,但太浪费系统资源了,不论我们按键中断有没有发生,cpu都要一直进行检测;这样操作系统就不能做其他事情了,因此这样肯定是不可取得,因此我们可以通过外部中断解决它;

  要处理一个中断,我们需要了解模式,而了解模式,有需要了解mmu;在学习这些之后我们就可以返回来处理我们按键驱动的时候留下的问题了;

  通过之前的按前驱动我们已经了解了按前驱动在板子上的位置以及按键的电路图以及他的引脚作用,下面我们就如何实现这个程序的步骤:

  我们知道控制按键的寄存器为:

 

外部中断对应的是:

0xf = EXT_INT43[2]

在EXT_INT43[2]中我们选择边沿触发方式:

通过key在核心板的引脚图我们可以知道外部中断源为26,中断号为64

需要我们配置的寄存器:

(1) EXT_INT43PEND (2)EXT_INT43MASK  (3)EXT_INT43CON

需要注意的是:中断状态:EXT_INT43_PEND[2],特别注意的是,要清中断,将值赋值为1.

  实现一个外部中断大致需要五步:

  (1)cpu允许中断

  (2)启用GIC

  (3)配置外部中断寄存器(xeint)

  (4)配置gpio(General Purpose Input Output (通用输入/输出)简称为GPIO,每个GPIO端口可通过软件分别配置成输入或输出)

  (5)外部中断源

下面是实现的具体代码:

 1 #ifndef __BUNFLY_H
 2 #define __BUNFLY_H
 3 
 4 #define ICCICR_CPU0    (*(volatile unsigned long *)0x10480000)
 5 #define ICCPMR_CPU0    (*(volatile unsigned long *)0x10480004)
 6 #define ICDDCR        (*(volatile unsigned long *)0x10490000)
 7 #define ICDIPR0_CPU0    (*(volatile unsigned long *)0x10490400)
 8 #define ICDIPTR0_CPU0    (*(volatile unsigned long *)0x10490800)
 9 #define ICDISER0_CPU0    (*(volatile unsigned long *)0x10490100)
10 #define ICDSGIR        (*(volatile unsigned long *)0x10490f00)
11 #define ICCEOIR_CPU0    (*(volatile unsigned long *)0x10480010)
12 #define ICCIAR_CPU0    (*(volatile unsigned long *)0x1048000c)
13 #define ICDIPR2_CPU0    (*(volatile unsigned long *)0x10490408)
14 #define ICDIPTR2_CPU0    (*(volatile unsigned long *)0x10490808)
15 #define ICDIPR3_CPU0    (*(volatile unsigned long *)0x1049040c)
16 #define ICDIPTR3_CPU0    (*(volatile unsigned long *)0x1049080c)
17 #define ICDIPR16_CPU0    (*(volatile unsigned long *)0x10490440)
18 #define ICDIPTR16_CPU0    (*(volatile unsigned long *)0x10490840)
19 #define ICDIPR18_CPU0    (*(volatile unsigned long *)0x10490448)
20 #define ICDIPTR18_CPU0    (*(volatile unsigned long *)0x10490848)
21 #define ICDISER2_CPU0    (*(volatile unsigned long *)0x10490108)
22 
23 #define WTCON         (*(volatile unsigned long *)0x10060000)
24 #define WTDAT         (*(volatile unsigned long *)0x10060004)
25 #define WTCNT         (*(volatile unsigned long *)0x10060008)
26 #define WTCLRINT     (*(volatile unsigned long *)0x1006000C)
27 
28 #define EXT_INT43_CON    (*(volatile unsigned long *)0x11000e0c)
29 #define EXT_INT43_MASK    (*(volatile unsigned long *)0x11000f0c)
30 #define EXT_INT43_PEND    (*(volatile unsigned long *)0x11000f4c)
31 #define GPX3CON (*(volatile unsigned long *)0x11000c60)
32 
33 #define GPM4CON    (*(volatile unsigned long *)0x110002e0)
34 #define GPM4DAT (*(volatile unsigned long *)0x110002e4)
35 
36 #endif    //__BUNFLY_H
  1 #include "bunfly.h"
  2 
  3 int (*printf)(char *, ...) = 0xc3e114d8;
  4 void enable_mmu();
  5 void init_table(unsigned long *addr);
  6 void memcpy(unsigned char *dest, unsigned char *src, int len);
  7 extern unsigned long vector_start;
  8 void do_irq();
  9 
 10 int main()
 11 {
 12     memcpy(0x70000000, vector_start, 0x10000);
 13     enable_mmu();
 14     
 15     *(unsigned long *)0x47000000 = do_irq;
 16     
 17     //step 1: cpu permit interrupt
 18     __asm__ __volatile__ (
 19         "mrs r0, cpsr\n"
 20         "bic r0, r0, #0x80\n"
 21         "msr cpsr, r0\n"
 22         ::: "r0"
 23     );
 24     
 25     //step 2: GIC (cgi) enable
 26     ICCICR_CPU0 = 1;//总开关
 27     ICCPMR_CPU0 = 0xff;//总优先级(门槛)
 28     ICDDCR = 1; //本中断开关
 29 
 30     ICDIPR16_CPU0 = (0 << 0); //本中断优先级
 31     ICDIPTR16_CPU0 = (1 << 0); //目标cpu
 32     ICDISER2_CPU0 = (1 << 0); //启用本中断
 33     
 34     //step 3: Xeint
 35     EXT_INT43_CON = (4 << 8);//Triggers Both edge (设置为边沿触发)
 36     EXT_INT43_MASK = 0; //开启中断
 37     
 38     //step 4: set gpio
 39     GPX3CON = (0xf << 8); //0xF = EXT_INT43[2] (gpio配置为外部中断)
40 41 //step 5: interrupt source 42 43 printf("welcome back\n"); 44 } 45 46 void do_irq() 47 { 48 unsigned long data = ICCIAR_CPU0; 49 int irq = data & 0x3ff; //获得中断号 50 int cpu = (data >> 10) & 0x7; //获得目标cpu 51 ICCEOIR_CPU0 = irq | (cpu << 10); //清除中断 52 EXT_INT43_PEND |= (1 << 2); //清中断 53 printf("key 1 down, cpu is %d, irq is %d\n", cpu, irq); 54 } 55 56 void enable_mmu() 57 { 58 unsigned long addr = 0x50000000; 59 init_table(addr); 60 unsigned long mmu = 0; 61 mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8); 62 63 __asm__ __volatile__ ( 64 "mov r0, #3\n" 65 "MCR p15, 0, r0, c3, c0, 0\n" 66 "MCR p15, 0, %0, c2, c0, 0\n" 67 "MCR p15, 0, %1, c1, c0, 0\n" 68 : 69 : "r" (addr), "r" (mmu) 70 : 71 ); 72 } 73 74 void init_table(unsigned long *addr) 75 { 76 unsigned long va = 0; 77 unsigned long phys = 0; 78 79 for(va = 0x40000000; va < 0x80000000; va+=0x100000) 80 { 81 phys = va; 82 addr[va >> 20] = phys | 2; 83 } 84 85 for(va = 0x10000000; va < 0x14000000; va+=0x100000) 86 { 87 phys = va; 88 addr[va >> 20] = phys | 2; 89 } 90 91 for(va = 0x0; va < 0x10000000; va+=0x100000) 92 { 93 phys = va + 0x70000000; 94 addr[va >> 20] = phys | 2; 95 } 96 } 97 98 __asm__ ( 99 "vector:\n" 100 " b reset\n" 101 " b undefined\n" 102 " b swi\n" 103 " b pre_abt\n" 104 " b data_abt\n" 105 " .word 0x0\n" 106 " b irq\n" 107 " b fiq\n" 108 109 "reset:\n" 110 "undefined:\n" 111 " mov sp, #0x47000000\n" 112 " stmdb sp!, {r0-r12, lr}\n" 113 114 "ldr r3, =0x47000004\n" 115 "ldr r2, [r3]\n" 116 "blx r2\n" 117 118 " mov sp, #0x47000000\n" 119 " ldmdb sp, {r0-r12, pc}^\n" 120 "swi:\n" 121 " mov sp, #0x47000000\n" 122 " stmdb sp!, {r0-r12, lr}\n" 123 124 " mov sp, #0x47000000\n" 125 " ldmdb sp, {r0-r12, pc}^\n" 126 "pre_abt:\n" 127 "data_abt:\n" 128 " mov sp, #0x47000000\n" 129 " sub lr, lr, #4\n" 130 " stmdb sp!, {r0-r12, lr}\n" 131 132 "ldr r3, =0x47000008\n" 133 "ldr r2, [r3]\n" 134 "blx r2\n" 135 136 " mov sp, #0x47000000\n" 137 " ldmdb sp, {r0-r12, pc}^\n" 138 "irq:\n" 139 " mov sp, #0x47000000\n" 140 " sub lr, lr, #4\n" 141 " stmdb sp!, {r0-r12, lr}\n" 142 143 "mov r3, #0x47000000\n" 144 "ldr r2, [r3]\n" 145 "blx r2\n" 146 147 " mov sp, #0x47000000\n" 148 " ldmdb sp, {r0-r12, pc}^\n" 149 "fiq:\n" 150 151 ".global vector_start\n" 152 "vector_start:\n" 153 ".word vector\n" 154 ); 155 156 void memcpy(unsigned char *dest, unsigned char *src, int len) 157 { 158 int i = 0; 159 for(i = 0; i < len; i++) 160 dest[i] = src[i]; 161 }

  下面我们通过外部中断(KEY1)控制watchdog,在通过watchdog控制led灯,当key1按下时,led灯开始闪烁,再次按下停止闪烁:

  下面贴出代码:

  

 1 #ifndef __BUNFLY_H
 2 #define __BUNFLY_H
 3 
 4 #define ICCICR_CPU0    (*(volatile unsigned long *)0x10480000)
 5 #define ICCPMR_CPU0    (*(volatile unsigned long *)0x10480004)
 6 #define ICDDCR        (*(volatile unsigned long *)0x10490000)
 7 #define ICDIPR0_CPU0    (*(volatile unsigned long *)0x10490400)
 8 #define ICDIPTR0_CPU0    (*(volatile unsigned long *)0x10490800)
 9 #define ICDISER0_CPU0    (*(volatile unsigned long *)0x10490100)
10 #define ICDSGIR        (*(volatile unsigned long *)0x10490f00)
11 #define ICCEOIR_CPU0    (*(volatile unsigned long *)0x10480010)
12 #define ICCIAR_CPU0    (*(volatile unsigned long *)0x1048000c)
13 #define ICDIPR2_CPU0    (*(volatile unsigned long *)0x10490408)
14 #define ICDIPTR2_CPU0    (*(volatile unsigned long *)0x10490808)
15 #define ICDIPR3_CPU0    (*(volatile unsigned long *)0x1049040c)
16 #define ICDIPTR3_CPU0    (*(volatile unsigned long *)0x1049080c)
17 #define ICDIPR16_CPU0    (*(volatile unsigned long *)0x10490440)
18 #define ICDIPTR16_CPU0    (*(volatile unsigned long *)0x10490840)
19 #define ICDIPR18_CPU0    (*(volatile unsigned long *)0x10490448)
20 #define ICDIPTR18_CPU0    (*(volatile unsigned long *)0x10490848)
21 #define ICDISER2_CPU0    (*(volatile unsigned long *)0x10490108)
22 
23 #define WTCON         (*(volatile unsigned long *)0x10060000)
24 #define WTDAT         (*(volatile unsigned long *)0x10060004)
25 #define WTCNT         (*(volatile unsigned long *)0x10060008)
26 #define WTCLRINT     (*(volatile unsigned long *)0x1006000C)
27 
28 #define EXT_INT43_CON    (*(volatile unsigned long *)0x11000e0c)
29 #define EXT_INT43_MASK    (*(volatile unsigned long *)0x11000f0c)
30 #define EXT_INT43_PEND    (*(volatile unsigned long *)0x11000f4c)
31 #define GPX3CON (*(volatile unsigned long *)0x11000c60)
32 
33 #define GPM4CON    (*(volatile unsigned long *)0x110002e0)
34 #define GPM4DAT (*(volatile unsigned long *)0x110002e4)
35 
36 #endif    //__BUNFLY_H

 

  1 #include "bunfly.h"
  2 
  3 void (*udelay)(int) = 0xc3e25f90;
  4 int (*printf)(char *, ...) = 0xc3e114d8;
  5 void enable_mmu();
  6 void init_table(unsigned long *addr);
  7 void memcpy(unsigned char *dest, unsigned char *src, int len);
  8 extern unsigned long  vector_start;
  9 void do_irq();
 10 void led_on();
 11 void led_off();
 12 void wdt_on();
 13 void wdt_off();
 14 
 15 int main()
 16 {    
 17     memcpy(0x70000000, vector_start, 0x1000);    
 18     enable_mmu();
 19 
 20     *(unsigned long *)0x47000000 = do_irq;
 21 
 22     //step 1: cpu permit interrupt
 23     __asm__ __volatile__(
 24         "mrs r0, cpsr\n"
 25         "bic r0,r0, #0x80\n"
 26         "msr cpsr, r0\n"
 27         :::"r0"
 28     );
 29 
 30     //step 2: GIC (cgi) enable
 31     ICCICR_CPU0 = 1; //总开关
 32     ICCPMR_CPU0 =0xff;//总优先级
 33     ICDDCR = 1; //本中断开关
 34 
 35     //KEY
 36     ICDIPR16_CPU0 = (1 << 0);//本中断优先级
 37     ICDIPTR16_CPU0 = (1 << 0);//目标cpu
 38     ICDISER2_CPU0 = (1 << 0);//启用本中断
 39 
 40     //WDT
 41     ICDIPR18_CPU0 = (1 << 24);
 42     ICDIPTR18_CPU0 = (1 << 24);
 43     ICDISER2_CPU0 = (1 << 11);    
 44 
 45     //step 3: Xeint
 46     EXT_INT43_CON = (0x2 << 8);
 47     EXT_INT43_MASK = 0;
 48         
 49     //step 4: set gpio    
 50     GPX3CON = (0xf << 8);
 51 
 52     //step 5: interrupt source
 53     
 54     printf("welcom back\n");
 55     
 56 }
 57 
 58 void do_irq()
 59 {
 60     unsigned long data = ICCIAR_CPU0;
 61     int irq = data & 0x3ff;
 62     int cpu = (data >> 10) & 0x7;
 63     ICCEOIR_CPU0 = irq | (cpu << 10);
 64     static int flags = 1;
 65 
 66     if(64 == irq) {
 67         printf("key 1 down\n");
 68         if(EXT_INT43_PEND & (0x1 << 2)) {
 69             EXT_INT43_PEND |= (1 << 2);
 70             if(flags) {
 71                 wdt_on();
 72                 flags = 0;    
 73             }
 74             else {
 75                 wdt_off();
 76                 led_off();
 77                 flags = 1;
 78             }
 79         }
 80     }
 81 
 82     if(75 == irq) {
 83         WTCLRINT = 0;//清中断
 84         printf("wang wang wang ...\n");
 85         if(flags) {
 86             led_on();
 87             flags = 0;
 88         }
 89         else {
 90             led_off();
 91             flags = 1;
 92         }
 93     }
 94 }
 95 
 96 void led_on()
 97 {
 98     GPM4CON &= ~0xffff;
 99     GPM4CON |= 0x1111;
100     GPM4DAT &= ~0xf;
101 }
102 
103 void led_off()
104 {
105 
106     GPM4CON &= ~0xffff;
107     GPM4CON |= 0x1111;
108     GPM4DAT |= 0xf;
109 }
110 
111 void wdt_on()
112 {
113     WTCNT = 0x8000;
114     WTDAT = 0x8000; 
115     WTCON = 0 | (1 << 2) | (2 << 3) | (1 << 5) | (50 << 8);
116 }
117 
118 void wdt_off()
119 {
120     WTCON = 0;
121 }
122 
123 void memcpy(unsigned char *dest, unsigned char *src, int len)
124 {
125     int i = 0;
126     for(i = 0; i < len; i++) {
127         dest[i] = src[i];
128     }
129 }
130 
131 void enable_mmu()
132 {
133     /*构建表*/
134     unsigned long addr = 0x50000000;
135     init_table(addr);
136     /*打开mmu*/
137     unsigned long mmu = 0;
138     mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8);
139     __asm__ __volatile__ (
140         "mov r0, #3\n"
141         "MCR p15, 0, r0, c3, c0, 0\n"//设置为管理员
142         "MCR p15, 0, %0, c2, c0, 0\n"//设置表的地址
143         "MCR p15, 0, %1, c1, c0, 0\n"//开启mmu
144         :    
145         :    "r" (addr), "r" (mmu)
146         :
147     );
148 
149 }
150 
151 __asm__(
152 
153 "vector: \n"
154 "    b reset\n"
155 "    b und\n"
156 "    b swi\n"
157 "    b pre_abt\n"
158 "    b data_abt\n"
159 "    .word 0x0\n"
160 "    b irq\n"
161 "    b fiq\n"
162 "reset:\n"
163 "und:\n"
164 "    mov sp, #0x47000000\n"
165 "    stmdb sp!, {r0-r12, lr}\n"
166 
167 "    ldr r3, =0x47000004\n"
168 "    ldr r2, [r3]\n"
169 "    blx r2\n"
170 
171 "    mov sp, #0x47000000\n"
172 "    ldmdb sp, {r0-r12, pc}^    \n"
173 
174 "swi:\n"
175 "    mov sp, #0x47000000\n"
176 "    stmdb sp!, {r0-r12, lr}^\n"
177 
178 "    mov sp, #0x47000000\n"
179 "    ldmdb sp, {r0-r12, pc}^    \n"
180 
181 "pre_abt:\n"
182 
183 "data_abt:\n"
184 "    mov sp, #0x47000000\n"
185 "    sub lr, lr, #4\n"
186 "    stmdb sp!, {r0-r12, lr}\n"
187 
188 "    ldr r3, =0x47000008\n"
189 "    ldr r2, [r3]\n"
190 "    blx r2\n"
191 
192 "    mov sp, #0x47000000\n"
193 "    ldmdb sp, {r0-r12, pc}^    \n"
194 "irq:\n"
195 
196 "    mov sp, #0x47000000\n"
197 "    sub lr, lr, #4\n"
198 "    stmdb sp!, {r0-r12, lr}\n"
199 
200 "    ldr r3, =0x47000000\n"
201 "    ldr r2, [r3]\n"
202 "    blx r2\n"
203 
204 "    mov sp, #0x47000000\n"
205 "    ldmdb sp, {r0-r12, pc}^    \n"
206 
207 "fiq:\n"
208 
209     ".global vector_start\n"
210 "vector_start: \n"
211     ".word vector \n "
212 
213 );
214 
215 void init_table(unsigned long *addr)
216 {
217     unsigned long va = 0;
218     unsigned long phys = 0;
219 
220     //0x40000000-0x80000000 -> 0x40000000-0x80000000    
221     for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
222         phys = va;
223         addr[va >> 20] = phys | 2;
224     }
225 
226     //0x10000000-0x14000000 -> 0x10000000-0x140000000    
227     for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
228         phys = va;
229         addr[va >> 20] = phys | 2;
230     }
231     //0x10000000-0x14000000 -> 0x10000000-0x140000000    
232     for(va = 0x0; va < 0x10000000; va += 0x100000) {
233         phys = va + 0x70000000;
234         addr[va >> 20] = phys | 2;
235     }
236             
237 }

 

posted @ 2015-09-04 13:04  zhangwju  阅读(1503)  评论(0编辑  收藏  举报