新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM中外部中斷

        ARM中外部中斷

        作者: 時間:2016-11-20 來源:網絡 收藏
        在整個ARM體系結構中,為了處理外部中斷,依次學習了MMU,模式跳轉,異常,GIC,看門狗程序,這些都是為了處理外部中斷

        具體如下:

        本文引用地址:http://www.104case.com/article/201611/318704.htm

        處理外部中斷有五個步驟:

        30 //step 1: cpu cpsr
        31 __asm__ __volatile__(
        32 "mrs r0, cpsrn"
        33 "bic r0, r0, #0x80n"http://設置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 *)0x66 = do_irq;19 20     //發生異常時會進入異常模式跳轉到0 4地址處理異常事件   21     unsigned long source_addr=data_abort_init();22     //異常事件處理函數23     printf("swi_souce addr is %xn",source_addr);24     //將異常處理地址的值放到0x6425     memcopy(0x60,source_addr,0x1);26 27     enable_mmu();28     //內存映射將0x04映射到0x6004    29 30      //step 1: cpu cpsr31       __asm__ __volatile__(32           "mrs r0, cpsrn"33           "bic r0, r0, #0x80n"http://設置CPSR的I位,將IRQ位打開34           "msr cpsr, r0n"35           ::: "r0"36       );37 38     //setp1:GIC39     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 gpio49     GPX3CON = (0xf << 8);//是GPXCON為外部中斷功能50 51     //step 4: extern52     EXT_INT43CON = (2 << 8);//設置上升沿觸發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關閉置一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()函數中有一個清中斷的操作,否則,將會告訴中斷控制器處理好了中斷,以免一直觸發外部中斷:

        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 }

        當程序運行成功了之后,按下按鍵,LED和蜂鳴器就會工作,再按下按鍵,LED和蜂鳴器就會停止!

        接下來,將以前的中斷問題綜合起來:寫了一個用外部中斷來控制LED燈閃爍的例子

        流程圖是:

        主要是do_rirq()函數:代碼如下:

        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     //發生異常時會進入異常模式跳轉到0 4地址處理異常事件   25     unsigned long source_addr=data_abort_init();26     //異常事件處理函數27     printf("swi_souce addr is %xn",source_addr);28     //將異常處理地址的值放到0x6429     memcopy(0x60,source_addr,0x1);30 31     enable_mmu();32     //內存映射將0x04映射到0x6004    33 34      //step 1: cpu cpsr35       __asm__ __volatile__(36           "mrs r0, cpsrn"37           "bic r0, r0, #0x80n"http://設置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);//優先級,最高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);//設置上升沿觸發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關閉置一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 

        運行成功:

        發現當按下按鍵是觸發外部中斷,LED和蜂鳴器工作,當再次按下按鍵的時候,停止工作!看門狗在這里的作用就是

        不斷的使LED和蜂鳴器閃爍和鳴叫。

        到這里,ARM體系結構到一段落



        關鍵詞: ARM外部中

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 商南县| 于田县| 昭觉县| 九台市| 贡山| 达孜县| 彭山县| 龙游县| 山西省| 庄河市| 宁陵县| 南岸区| 宝鸡市| 榆中县| 灵寿县| 翼城县| 寿阳县| 耿马| 若羌县| 秦安县| 佛学| 阳高县| 板桥市| 北流市| 靖安县| 安国市| 湛江市| 上杭县| 会宁县| 栾川县| 长治市| 梧州市| 门源| 句容市| 大关县| 大田县| 水城县| 顺平县| 赞皇县| 新余市| 获嘉县|