ARM中外部中断

发布者:笑脸猫最新更新时间:2016-05-12 来源: eefocus关键字:ARM  外部中断 手机看文章 扫描二维码
随时随地手机看文章
在整个ARM体系结构中,为了处理外部中断,依次学习了MMU,模式跳转,异常,GIC,看门狗程序,这些都是为了处理外部中断

具体如下:

ARM中外部中断

处理外部中断有五个步骤:

 30      //step 1: cpu cpsr
 31       __asm__ __volatile__(
 32           "mrs r0, cpsr\n"
 33           "bic r0, r0, #0x80\n"//设置CPSR的I位,将IRQ位打开
 34           "msr cpsr, r0\n"
 35           ::: "r0"
 36       );
 37 
 38     //setp1:GIC
 39     ICCICR_CPU0 = 1;
 40     ICCPMR_CPU0 = 0xff;
 41

  前面的代码不解释,和以前的差不多

ARM中外部中断

外部中断号为: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个使能中断

 


 47ARM中外部中断

ARM中外部中断

ARM中外部中断

  第二步为设置中断号:

 详细看代码注释:寄存器参考手册第594页


 48     //step 3: set gpio
 49     GPX3CON = (0xf << 8);//是GPXCON为外部中断功能
 ARM中外部中断

查看到使用外部中断功能的对应外部寄存器:EXT_INT43:


 51     //step 4: extern
 52     EXT_INT43CON = (2 << 8);//设置上升沿触发
 53     EXT_INT43MASK = 0;//使能中断
 ARM中外部中断

    ARM中外部中断

设置外部中断控制器:寄存器参考手册第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 %x\n",source_addr);
 24     //将异常处理地址的值放到0x64
 25     memcopy(0x60,source_addr,0x1);
 26 
 27     enable_mmu();
 28     //内存映射将0x04映射到0x6004    
 29 
 30      //step 1: cpu cpsr
 31       __asm__ __volatile__(
 32           "mrs r0, cpsr\n"
 33           "bic r0, r0, #0x80\n"//设置CPSR的I位,将IRQ位打开
 34           "msr cpsr, r0\n"
 35           ::: "r0"
 36       );
 37 
 38     //setp1:GIC
 39     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 gpio
 49     GPX3CON = (0xf << 8);//是GPXCON为外部中断功能
 50 
 51     //step 4: extern
 52     EXT_INT43CON = (2 << 8);//设置上升沿触发
 53     EXT_INT43MASK = 0;//使能中断
 54 
 55     //step 5: source
 56     //
 57     printf("welcome back! \n");
 58 }
 59 
 60 void pwm_on(void)
 61     {
 62         GPD0CON &= ~0xffff;
 63         GPD0CON = 0x1;//配置寄存器为2
 64         GPD0DAT = 0x1;//date=0xf
 65     }
 66 
 67 void pwm_off(void)
 68     {
 69         GPD0CON &= ~0xffff;
 70         GPD0CON = 0x0;
 71     //  GPD0DAT &=0x0 ;//date=0xf
 72 
 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位为0
 85     }
 86 
 87 void do_irq()
 88     {
 89             printf("key 1 down\n");
 90             static int flag=1;
 91             if(flag)
 92             {
 93                 printf("wtc_on\n");
  94                 led_on();
 95                 pwm_on();
 96                 flag=0;
 97             }
 98             else if(flag == 0)
 99             {
100                 printf("wtc_off\n");
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此时将是小页模式4K
211     }
212 
213     //00-10   ====  6070
214     for(va=0x00; va<=0x10; va+=0x100){
215         pa = va+0x60;
216         addr[va >> 20] = pa  2;
217     }
218 
219     //10-14   ====  1014
220     for(va=0x10; va<=0x14; va+=0x100){
221         pa = va;
         addr[va >> 20] = pa  2;
223     }
224 
225     //30-40   ====  5060
226     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位置1
241     __asm__ __volatile__(
242         "mov r0, #3\n"
243         "MCR p15, 0, r0, c3, c0, 0\n"//manager
244         "MCR p15, 0, %0, c2, c0, 0\n"//addr  
245         "MCR p15, 0, %1, c1, c0, 0\n"// enable mmu
246         :
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 down\n");
 90             static int flag=1;
 91             if(flag)
 92             {
 93                 printf("wtc_on\n");
 94                 led_on();
 95                 pwm_on();
 96                 flag=0;
 97             }
 98             else if(flag == 0)
 99             {
100                 printf("wtc_off\n");
101                 led_off();
102                 pwm_off();
103                 flag=1;
104             }
105           

  EXT_INT43PEND = (1 << 2);//清中断
106     }

当程序运行成功了之后,按下按键,LED和蜂鸣器就会工作,再按下按键,LED和蜂鸣器就会停止!

 

 

 

接下来,将以前的中断问题综合起来:写了一个用外部中断来控制LED灯闪烁的例子

流程图是:

ARM中外部中断

 

 

主要是do_rirq()函数:代码如下:

87 void do_irq()
 88     {
 89             printf("key 1 down\n");
 90             static int flag=1;
 91             if(flag)
 92             {
 93                 printf("wtc_on\n");
 94                 led_on();
 95                 pwm_on();
 96                 flag=0;
 97             }
 98             else if(flag == 0)
 99             {
100                 printf("wtc_off\n");
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 %x\n",source_addr);
 28     //将异常处理地址的值放到0x64
 29     memcopy(0x60,source_addr,0x1);
 30 
 31     enable_mmu();
 32     //内存映射将0x04映射到0x6004    
 33 
 34      //step 1: cpu cpsr
 35       __asm__ __volatile__(
 36           "mrs r0, cpsr\n"
 37           "bic r0, r0, #0x80\n"//设置CPSR的I位,将IRQ位打开
 38           "msr cpsr, r0\n"
 39           ::: "r0"
 40       );
 41 
 42     //setp1:GIC
 43     ICCICR_CPU0 = 1;
 44     ICCPMR_CPU0 = 0xff;
 45 
 46     //64
 47     ICDDCR = 1;
 48     ICDIPR16_CPU0 = (0x0 << 0);//ICD第16个寄存器,第0位
 49     ICDIPTR16_CPU0 = (0x1 << 0);//优先级,最高
 50     ICDISER2_CPU0 = (1 << 0);//一共五个,第2个使能中断
 51 
 52     //75
 53      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 gpio
 60     GPX3CON = (0xf << 8);//是GPXCON为外部中断功能
 61 
 62     //step 4: extern
 63     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;//配置寄存器为2
 79         GPD0DAT = 0x1;//date=0xf
 80     }
 81 
 82 void pwm_off(void)
 83     {
 84         GPD0CON &= ~0xffff;
 85         GPD0CON = 0x0;
 86     //  GPD0DAT &=0x0 ;//date=0xf
 87 
 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位为0
100     }
101 
102 void wtc_on()
103     {
104             //step 3: interrupt source watchdog
105         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 %d\n", 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 down\n");
134             static int flag=1;
135             if(flag)
136             {
137                 printf("wtc_on\n");
138                 wtc_on();
139                 flag=0;
140             }
141             else if(flag == 0)
142             {
143                 printf("wtc_off\n");
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         else
162         {
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此时将是小页模式4K
281     }
282 
283     //00-10   ====  6070
284     for(va=0x00; va<=0x10; va+=0x100){
285         pa = va+0x60;
286         addr[va >> 20] = pa  2;
287     }
288 
289     //10-14   ====  1014
290     for(va=0x10; va<=0x14; va+=0x100){
291         pa = va;
292         addr[va >> 20] = pa  2;
293     }
294 
295     //30-40   ====  5060
296     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位置1
311     __asm__ __volatile__(
312         "mov r0, #3\n"
313         "MCR p15, 0, r0, c3, c0, 0\n"//manager
314         "MCR p15, 0, %0, c2, c0, 0\n"//addr  
315         "MCR p15, 0, %1, c1, c0, 0\n"// enable mmu
316         :
317         : "r" (addr), "r" (mmu)
318         : "r0"
319     );
320     printf("MMU is enable!\n");
321 }
322 
                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                

运行成功:

ARM中外部中断

 

发现当按下按键是触发外部中断,LED和蜂鸣器工作,当再次按下按键的时候,停止工作!看门狗在这里的作用就是

不断的使LED和蜂鸣器闪烁和鸣叫。

到这里,ARM体系结构到一段落

关键字:ARM  外部中断 引用地址: ARM中外部中断

上一篇:单片机脚本语言移植lua到stm32MDK
下一篇:裸奔程序之外部中断检测按键

推荐阅读最新更新时间:2024-03-16 14:53

ARM linux上使用usb接口的触屏
应公司需要,在现有设备上面要使用触摸屏,显示器的尺寸是15寸,于是自己从淘宝上面买了个15寸4线电阻屏回来,带Windows下的驱动,售后告诉我不支持Linux。在pc上面使用很不错。接下来的任务是用到ARM开发板上面。 当把4根线,直接连接到开发板上面,为电阻屏预留的4个AD上面后,确实能够使用,不过鼠标并不能实时跟随触屏,会有跳动,而且在左侧区域按下后,鼠标跟随过来,当松开触摸屏后,鼠标并没有固定在按下的区域,而是回到右侧区域,类似于回到原点一样。触摸屏的最还没有反映,但是在Windows下触屏是没有问题的。查看了内核的AD输出结果,看不出来什么原因,不得已只好放弃。 在Windows下的驱动文件中找到了一份使用手册,里面介绍
[单片机]
在<font color='red'>ARM</font> linux上使用usb接口的触屏
Mouser备货Freescale® Kinetis® L系列32位MCU 基于ARM Cortex-M0+处理器构建
2012年10月8日 – Mouser Electronics宣布备货业界能效最高的处理器,该处理器来自Freescale Semiconductor.®。 Freescale公司的Kinetis® L系列32位微控制器(MCU)基于ARM® Cortex™-M0+核心构建,不仅能效出众、易于使用而且兼具了Kinetis 32位MCU产品组合的性能、外设、支持与可扩展性,同时还利用了ARM Cortex架构固有的低功耗和高性能特性。L系列产品采用Freescale的低泄露、90 nm薄膜存储(TFS)工艺技术制造,通过将出色的动态和截止电流与卓越的处理性能相结合,让功率关键型设计摆脱8位和16位MCU的限制。片内闪存记
[单片机]
Mouser备货Freescale® Kinetis® L系列32位MCU 基于<font color='red'>ARM</font> Cortex-M0+处理器构建
STM8S_009_ EXTI外部中断
有人问 我使用EXIT唤醒芯片,没什么没有触发中断,芯片却唤醒了? Ⅰ写在前面 使用STM8S开发过上面类似功能的朋友应该会知道,STM8S的稳定性不如STM32,特别是在低功耗时,使用EXTI外部中断唤醒,很容易受到干扰信号而唤醒。因此,这种情况需在硬件电路上多加考虑抗干扰的电路。 其次,就是注意软件的上下拉配置,如果外部加了上拉或下拉电阻,不建议再配置成上拉或下拉;如果没有,建议加上。要使其软件稳定,还得深入EXTI的功能。 ⅡEXTI基础知识 STM8S的EXTI外部中断归属于GPIO一类,只需要将其IO配置成外部中断、使能全局中断、在中断入口函数添加相关的代码即可。 开启中断功能 在EXTI_CR 寄存
[单片机]
ARM JTAG仿真器调试方法之SDRAM篇
之前介绍了使用ARM JTAG仿真器将映像文件加载到ARM处理器内部SRAM中进行程序调试的方法,而在实际操作中,将映像文件加载到外部SDRAM中进行调试的方式更为常见。 要把映像文件加载到SDRAM中,除了要正确设置好映像文件的RO段基地址外(对于一个加载时域和运行时域相同的映像文件来说,RO段基地址实际上就是该映像文件在存储空间的起始地址),更关键的是要对SDRAM进行初始化。因为在上电时,SDRAM是没有被初始化的,所谓初始化SDRAM,就是要设置处理器的SDRAM空间以及读写SDRAM的时序参数,因而SDRAM在初始化之前是不能进行读写操作的。 对于PXA270处理器,初始化SDRAM的工作
[单片机]
NXP宣布推出基于ARM968核的微控制器系列
恩智浦半导体(NXP Semiconductors,由飞利浦创建的独立半导体公司),近日推出了全新的LPC292x系列微控制器。在工业网络、报警系统和电机控制应用方面,125MHz的LPC292x系列是目前市场上最快的ARM968微控制器。在已有的LPC291x系列基础上,恩智浦现提供LPC292x微控制器系列的7个新产品,为市场上这个ARM微控制器的最大系列增添新成员。   在给客户们提供无以伦比的操作速度之余,LPC292x系列也包括几个以前在ARM968 MCU中未有过的特性,例如USB Host/On-The-Go/Device、16KB EEPROM、5V ADC、带RS485和LIN支持的UART、正交编码器接口和电
[单片机]
成功移植NET-SNMP到ARM平台
经过一个月的不懈努力终于将NET-SNMP成功移植到了ARM平台,网上关于NET-SNMP的资料很少,仅有的一些文章也都是轻描淡写,很容易被误导,我就是其中的受害者之一,交叉编译过程很复杂,要配置参数,路径,还有库。所以稍有插翅就会前功尽弃。而且每编译一次NET-SNMP都会耗费很多的时间。很容易挫败人的自信心。我整整啃了一个月的英文文档,边看边试。下面把详细过程贴出来,跟大家共享,希望那些也想移植NET-SNMP能够少走弯路。 主机环境 Windows + vmware(redhat9.0) IP分配如下: ARM开发板:192.168.4.151 Windows: 192.168.4.44 R
[单片机]
单片机的外部中断(二)
前言:单片机的中断系统(一) 80C51单片机提供两个外部中断口: INT0(P3.2)和INT1(P3.3)引脚输入。这两个引脚是功能复用引脚,既可以作为普通V0口,也可作为外部中断输入引脚。下面以部中断0来讲述。80C51单片机在每个机器周期的S5P2期间扫描外部中断输入引脚的电平状态。当外部中断设置为下降沿触发时,若处理器在连续两个机器周期扫描到INT0引脚的电平先后为高电平和低电平时,就会设置中断标志位IE0为1,表示外部有中断申请,该中断申请信号会一直保持,直到该中断被响应,该标志由内部硬件自动清除。当外部中断设置为电平触发方式时,在外部中断引脚INTo变为低电平时,IE0变为1,并一直保持为1,直到引脚INTo的输
[单片机]
单片机的<font color='red'>外部中断</font>(二)
嵌入式Linux下ARM处理器与DSP的数据通信
摘要:本文通过一个开发实例详细说明如何通过DSP的HPI接口与运行Linux操作系统的ARM架构处理器进行数据通信。给出接口部分的实际电路和ARM-Linux下驱动程序的开发过程。 关键词:设备驱动程序 嵌入式Linux HPI ARM DSP 1 引言 基于ARM核心处理器的嵌入式系统以其自身资源丰富、功耗低、价格低廉、支持厂商众多的缘故,越来越多地应用在各种需要复杂控制和通信功能的嵌入式系统中。 内核源码开放的Linux与ARM体系处理器相结合,可以发挥Linux系统支持各种协议及存在多进程调度机制的优点,从而使开发周期缩短,扩展性增强。作为数字处理专用电路,DSP的数字信号处理能力十分强大,但对诸如任务管理、通信、
[工业控制]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved