ARM中外部中斷
具體如下:
本文引用地址:http://www.ex-cimer.com/article/201611/318704.htm處理外部中斷有五個步驟:
30 //step 1: cpu cpsr
31 __asm__ __volatile__(
32 "mrs r0, cpsrn"
33 "bic r0, r0, #0x80n"http://設(shè)置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:設(shè)置中斷號
43 ICDDCR = 1;//總開關(guān)
44 ICDIPR16_CPU0 = (0x0 << 0);//ICD一共40個寄存器,第16個寄存器,第0位
45 ICDIPTR16_CPU0 = (0x1 << 0);//優(yōu)先級,最高
46 ICDISER2_CPU0 = (1 << 0);//一共五個,第2個使能中斷
47
第二步為設(shè)置中斷號:
詳細(xì)看代碼注釋:寄存器參考手冊第594頁
48 //step 3: set gpio
49 GPX3CON = (0xf << 8);//是GPXCON為外部中斷功能
查看到使用外部中斷功能的對應(yīng)外部寄存器:EXT_INT43:
51 //step 4: extern
52 EXT_INT43CON = (2 << 8);//設(shè)置上升沿觸發(fā)
53 EXT_INT43MASK = 0;//使能中斷
設(shè)置外部中斷控制器:寄存器參考手冊第366頁
55 //step 5: source
56 外部中斷源這里設(shè)置由外部按鍵K觸發(fā):
代碼如下
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 *)0x66 = do_irq;19 20 //發(fā)生異常時會進(jìn)入異常模式跳轉(zhuǎn)到0 4地址處理異常事件 21 unsigned long source_addr=data_abort_init();22 //異常事件處理函數(shù)23 printf("swi_souce addr is %xn",source_addr);24 //將異常處理地址的值放到0x6425 memcopy(0x60,source_addr,0x1);26 27 enable_mmu();28 //內(nèi)存映射將0x04映射到0x6004 29 30 //step 1: cpu cpsr31 __asm__ __volatile__(32 "mrs r0, cpsrn"33 "bic r0, r0, #0x80n"http://設(shè)置CPSR的I位,將IRQ位打開34 "msr cpsr, r0n"35 ::: "r0"36 );37 38 //setp1:GIC39 ICCICR_CPU0 = 1;40 ICCPMR_CPU0 = 0xff;41 42 //step1:設(shè)置中斷號43 ICDDCR = 1;44 ICDIPR16_CPU0 = (0x0 << 0);//ICD第16個寄存器,第0位45 ICDIPTR16_CPU0 = (0x1 << 0);//優(yōu)先級,最高46 ICDISER2_CPU0 = (1 << 0);//一共五個,第2個使能中斷47 48 //step 3: set gpio49 GPX3CON = (0xf << 8);//是GPXCON為外部中斷功能50 51 //step 4: extern52 EXT_INT43CON = (2 << 8);//設(shè)置上升沿觸發(fā)53 EXT_INT43MASK = 0;//使能中斷54 55 //step 5: source56 //57 printf("welcome back! n");58 }59 60 void pwm_on(void)61 {62 GPD0CON &= ~0xffff;63 GPD0CON = 0x1;//配置寄存器為264 GPD0DAT = 0x1;//date=0xf65 }66 67 void pwm_off(void)68 {69 GPD0CON &= ~0xffff;70 GPD0CON = 0x0;71 // GPD0DAT &=0x0 ;//date=0xf72 73 }74 void led_off(void)75 {76 GPM4CON &= ~0xffff;//清零77 GPM4CON = 0x0;//03位清零78 GPM4DAT = 0x0;//date=0xf關(guān)閉置一79 }80 void led_on(void)81 {82 GPM4CON &= ~0xffff;83 GPM4CON = 0x1;//配置寄存器3-0--3-3全為1,全為輸出模式84 GPM4DAT &= ~0xf;//打開置0-4位為085 }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;;for(i=0;i> 20] = pa 2;210 //2的目的是將0-2位置為10此時將是小頁模式4K211 }212 213 //00-10 ==== 6070214 for(va=0x00; va<=0x10; va+=0x100){215 pa = va+0x60;216 addr[va >> 20] = pa 2;217 }218 219 //10-14 ==== 1014220 for(va=0x10; va<=0x14; va+=0x100){221 pa = va;addr[va >> 20] = pa 2;223 }224 225 //30-40 ==== 5060226 for(va=0x30; va<0x40; va+=0x100){227 pa = va + 0x20;228 addr[va >> 20] = pa 2;229 }230 }231 232 void enable_mmu(void)233 234 {235 unsigned long addr = 0x70;236 init_ttb(addr);237 //step:初始化頁表238 239 unsigned long mmu = 1 (1 << 1) (1 << 8);240 //將MMU的第0,1,8位置1241 __asm__ __volatile__(242 "mov r0, #3n"243 "MCR p15, 0, r0, c3, c0, 0n"http://manager244 "MCR p15, 0, %0, c2, c0, 0n"http://addr 245 "MCR p15, 0, %1, c1, c0, 0n"http:// enable mmu246 :247 : "r" (addr), "r" (mmu)248 : "r0"249 );250 printf("MMU is enable!n");251 }252 253 254
需要注意的是:在do_irq()函數(shù)中有一個清中斷的操作,否則,將會告訴中斷控制器處理好了中斷,以免一直觸發(fā)外部中斷:
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 }
當(dāng)程序運行成功了之后,按下按鍵,LED和蜂鳴器就會工作,再按下按鍵,LED和蜂鳴器就會停止!
接下來,將以前的中斷問題綜合起來:寫了一個用外部中斷來控制LED燈閃爍的例子
流程圖是:
主要是do_rirq()函數(shù):代碼如下:
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 }
接下來是整個程序的代碼:
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 wtc_on();12 void wtc_off();13 void pwm_on(void);14 void pwm_off(void);15 void led_on(void);16 void led_on(void);17 18 19 20 int main()21 {22 *(unsigned long *)0x66 = do_irq;23 24 //發(fā)生異常時會進(jìn)入異常模式跳轉(zhuǎn)到0 4地址處理異常事件 25 unsigned long source_addr=data_abort_init();26 //異常事件處理函數(shù)27 printf("swi_souce addr is %xn",source_addr);28 //將異常處理地址的值放到0x6429 memcopy(0x60,source_addr,0x1);30 31 enable_mmu();32 //內(nèi)存映射將0x04映射到0x6004 33 34 //step 1: cpu cpsr35 __asm__ __volatile__(36 "mrs r0, cpsrn"37 "bic r0, r0, #0x80n"http://設(shè)置CPSR的I位,將IRQ位打開38 "msr cpsr, r0n"39 ::: "r0"40 );41 42 //setp1:GIC43 ICCICR_CPU0 = 1;44 ICCPMR_CPU0 = 0xff;45 46 //6447 ICDDCR = 1;48 ICDIPR16_CPU0 = (0x0 << 0);//ICD第16個寄存器,第0位49 ICDIPTR16_CPU0 = (0x1 << 0);//優(yōu)先級,最高50 ICDISER2_CPU0 = (1 << 0);//一共五個,第2個使能中斷51 52 //7553 ICDIPR18_CPU0 = (0x0 << 24);54 //ICDIPTR0_CPU0 = 1;55 ICDIPTR18_CPU0 = (0x1 << 24);56 //ICDISER0_CPU0 = (1 << 0);57 ICDISER2_CPU0 = (1 << 11);58 59 //step 3: set gpio60 GPX3CON = (0xf << 8);//是GPXCON為外部中斷功能61 62 //step 4: extern63 EXT_INT43CON = (2 << 8);//設(shè)置上升沿觸發(fā)64 EXT_INT43MASK = 0;//使能中斷65 66 /////////////////////////狗67 68 //step 5: sourcevoid pwm_on(void)69 70 71 72 printf("welcome back! n");73 }74 75 void pwm_on(void)76 {77 GPD0CON &= ~0xffff;78 GPD0CON = 0x1;//配置寄存器為279 GPD0DAT = 0x1;//date=0xf80 }81 82 void pwm_off(void)83 {84 GPD0CON &= ~0xffff;85 GPD0CON = 0x0;86 // GPD0DAT &=0x0 ;//date=0xf87 88 }89 void led_off(void)90 {91 GPM4CON &= ~0xffff;//清零92 GPM4CON = 0x0;//03位清零93 GPM4DAT = 0x0;//date=0xf關(guān)閉置一94 }95 void led_on(void)96 {97 GPM4CON &= ~0xffff;98 GPM4CON = 0x1;//配置寄存器3-0--3-3全為1,全為輸出模式99 GPM4DAT &= ~0xf;//打開置0-4位為0100 }101 102 void wtc_on()103 {104 //step 3: interrupt source watchdog105 WTCON = 0 (1 << 2) (3 << 3) (1 << 5) (20 << 8);106 WTCNT = 0x8;107 WTDAT = 0x2;108 }109 110 void wtc_off(){112 WTCON = 0;113 }114 115 void do_irq()116 {117 // pwm_on();118 // led_on();119 // delay(6);120 // pwm_off();121 // led_off();122 123 unsigned long data = ICCIAR_CPU0;124 unsigned long irq_id = data & 0x3ff;125 unsigned long cpu_id = (data >> 10) & 0x7;126 ICCEOIR_CPU0 = irq_id (cpu_id << 10);127 printf("irq is %d, cpu is %dn", irq_id, cpu_id);128 if(irq_id==64)//如果按鍵中斷129 {130 if(EXT_INT43PEND & (1 << 2))131 {132 EXT_INT43PEND = (1 << 2);//清中斷133 printf("key 1 downn");134 static int flag=1;135 if(flag)136 {137 printf("wtc_onn");138 wtc_on();139 flag=0;140 }141 else if(flag == 0)142 {143 printf("wtc_offn");144 wtc_off();145 led_off();146 pwm_off();147 flag=1;148 }149 }150 }151 if(irq_id==75)//如果DOG中斷152 {153 printf("dog dog dog n");154 static int flag=1;155 if(flag)156 {157 led_on();158 pwm_on();159 flag=0;160 }161 else162 {163 led_off();164 pwm_off();165 flag=1;166 }167 WTCLRINT = 100;//清狗中斷168 }169 170 }171 172 void memcopy(unsigned long* dest, unsigned long* source,int len)173 {174 int i=0;;175 for(i=0;i> 20] = pa 2;280 //2的目的是將0-2位置為10此時將是小頁模式4K281 }282 283 //00-10 ==== 6070284 for(va=0x00; va<=0x10; va+=0x100){285 pa = va+0x60;286 addr[va >> 20] = pa 2;287 }288 289 //10-14 ==== 1014290 for(va=0x10; va<=0x14; va+=0x100){291 pa = va;292 addr[va >> 20] = pa 2;293 }294 295 //30-40 ==== 5060296 for(va=0x30; va<0x40; va+=0x100){297 pa = va + 0x20;298 addr[va >> 20] = pa 2;299 }300 }301 302 void enable_mmu(void)303 304 {305 unsigned long addr = 0x70;306 init_ttb(addr);307 //step:初始化頁表308 309 unsigned long mmu = 1 (1 << 1) (1 << 8);310 //將MMU的第0,1,8位置1311 __asm__ __volatile__(312 "mov r0, #3n"313 "MCR p15, 0, r0, c3, c0, 0n"http://manager314 "MCR p15, 0, %0, c2, c0, 0n"http://addr 315 "MCR p15, 0, %1, c1, c0, 0n"http:// enable mmu316 :317 : "r" (addr), "r" (mmu)318 : "r0"319 );320 printf("MMU is enable!n");321 }322
運行成功:
發(fā)現(xiàn)當(dāng)按下按鍵是觸發(fā)外部中斷,LED和蜂鳴器工作,當(dāng)再次按下按鍵的時候,停止工作!看門狗在這里的作用就是
不斷的使LED和蜂鳴器閃爍和鳴叫。
到這里,ARM體系結(jié)構(gòu)到一段落
評論