当前位置:文档之家› ARM中断基础知识

ARM中断基础知识

ARM中断基础知识
ARM中断基础知识

I=0时是允许IRQ,I=1是禁止IRQ

初始化,sdram初始化,nandflash初始化(从nandflash启动)等等,然后把程序从nandflash 中拷贝到sdram中运行,在这段启动代码中我们免不了要初始化各种堆栈,而且是各个模式下的堆栈最好都提前设置好,这里就要考虑各种因素了。

比如我们是在OK6410平台上面测试,当复位或者开机后处于8K 大小的stepping stone中,此时我们设置堆栈是SVC下的堆栈,如果我们要设置其他模式下的堆栈的话我们就必须手动的设置CPSR下的模式位,来跳转到各个模式下设定好对应的堆栈。因为以后是要在sdram中运行了,所以这些堆栈应当设定为sdram中的地址。OK6410中的sdram是256M的,所以我们可以从顶部开始设置,比如说切换到irq模式,把堆栈设置为SP = 0x60000000 (因为

S3C6410中内存起始地址是从0x50000000开始的,加上256M,即0x10000000,得到栈顶为0x60000000),然后切换到fiq模式下,把堆栈设置为SP = 0x5f000000,一次类推。但是要注意的是,我们还在stepping stone中运行的时候SVC的堆栈还是得保持在片内内存的顶部即SP = 8*1024,直到要跳转到sdram中运行的时候了才把SVC的堆栈设置到sdram 中去。

有些人喜欢刚开始只设置SVC的堆栈(因为刚开启的时候就是这个模式,所以必须设置一下),而不设置别的模式的堆栈,等到中断发生了之后,在中断函数中设置堆栈的地址。我觉得这样有些不妥,提前都设置好,以后中断进来后就省去了每次设置堆栈的步骤,提高了效率。

中断向量表:

以下代码就是切换CPU工作模式的示例

;********** Begin init stact ***********/

;在6种模式下切换并设置堆栈指针

MRS R0,CPSR ;把CPSR读取到R0

BIC R0,#0x1f ;低5位清零

LDR R1,=MODE_Fiq ;设置R1 为0b10001,跳转到fiq模式

ORR R0,R0,R1 ;R0和R1相或,设置低5位

MSR CPSR_c,R0 ;把R0的值重新赋值到CPSR

LDR SP,=Stact_Fiq ;设置fiq的栈指针

BIC R0,#0x1f ;低5位清零

LDR R1,=MODE_Irq ;跳转Irq模式

ORR R0,R0,R1

MSR CPSR_c,R0

LDR SP,=Stact_Irq ;设置irq的栈指针

BIC R0,#0x1f

LDR R1,=MODE_Svc ;跳转到svc模式

ORR R0,R0,R1

MSR CPSR_c,R0

LDR SP,=Stact_Svc ;设置svc的栈指针

BIC R0,#0x1f

LDR R1,=MODE_Abort ;跳转到abort模式

ORR R0,R0,R1

MSR CPSR_c,R0

LDR SP,=Stact_Abort ;设置abort的栈指针

而可以全部由S3C6410的VIC硬件来自动处理。这样就大大简化了中断处理编程。

另外一变化是S3C6410外部中断加入了滤波电路,这样原来需要软件去毛刺的地方均可以采用硬件来进行滤波了,这样大大简化了外部中断处理。

先看下面的关系图(从下到上越来越接近cpu内核):

首先我们不采用中断方式来看各个寄存器的变化,我们用查询的方式查看,以按键中断为例,当有按键按下的时候,各个寄存器怎么变化,相互之间的关系如何:

准备一个能够在串口输出字符的程序。

OK6410的KEY1是接在 GPN0上面的,通过GPNCON把它设置成中断方式,且通过EINT0CON0设置成下降沿触发方式,代码如下:

01 /* set GPNIO to EINT mode , 10 --> Eint */

02 temp = GPNCON ;

03 temp &= ~(0x3<<0);

04 temp |= (0x2<<0);

05 GPNCON = temp;

06

07 /* set EINT triger mode to falling eage ,01x = Falling edge */

08 temp = EINT0CON0 ;

09 temp &= ~(0x7<<0);

10 temp |= (0x3<<0);

11 EINT0CON0 = temp;

当按下KEY的时候,会触发中断,并且把这个信号传送到最下层的中断悬起位寄存器

EINT0PEND,这个寄存器不同的bit对应不同的中断。EINT0PEND的上层是中断屏蔽寄存器INTMASK,当这个寄存器设置为屏蔽的时候中断触发信号是无法通过它传送到上层去的。我们先来看看当中断发生的时候EINT0PEND是如何变化的,他的变化会带来怎么样的结果。

01 while (1)

02 {

03 for(ch='a';ch<='z';ch++){

04 if( (EINT0PEND & 0x1)==0x1){ //轮询EINT0PEND有没有被置位

05 uart_putchar('+');

06 }

07 uart_putchar(ch);

08 delay();

09 }

10 }

上面的程序是在不停的查询EINT0PEND[0],该bit对应的是外部中断0,如果按下KEY产生一个下降沿,对应位会置位,if语句满足,会打印出一个“+”,然后出来打印字母,按键松开后是否还会满足if呢?看现象:

发现按下一次之后“+”会不停的打印出来,也就是说if语句都是满足的,这就意味着

EINT0PEND置位之后没有被清除,每次查询都还有,所以会不停的打印加号,所以这个寄存器我们必须手动清除,否则触发一次中断后就会不停的响应该中断。

清除的方式就是向对应位写1,我们这里是:

至于清除中断悬起位的方式:

3种清0的写法,只有最后一种是正确的清除。

1 PEND |= 1<<0; (not good)

2 PEND = 0xFFFFFFFF; (not good)

3 PEND = 1<<0; (Good!)

如果PEND寄存器某个bit是0,你写一个1进去,那么会变成1。只有当这位是1的时候写个1进去才会变成0.

第一种:用或的方式,若PEND = 00011111(二进制),PEND | (1<<0) = 00011111,也就是将00011111写入到值为00011111的PEND中,那么PEND的值变成00000000,所有的位都被清0了,而不是我们原本的意思要清除第一位。

第二种:直接赋值,其实和第一种方式是一样的,只不过第一种是先求出或的值然后写进寄存器,如果原本是00011111的PEND,写进0xFFFFFFFF那么PEND中原本是0的位还是0,是1的位全部都清为0 ,还是不是我们想要的结果。

第三种:PEND = 1<< 0 ,加入PEND是00011111,把00000001赋值进来,那么得到PEND的值为00011110,刚好是我们想要的,清除我们想要清除的位。

下面我们看看EINT0MASK的屏蔽作用是怎样的效果:

首先看看EINT0MASK的描述信息:

可以看出哪位置1就是屏蔽对应的中断信号

1 /* EINT0MASK[0] = 1 : Mask EINT0 */

2 temp = EINT0MASK ;

3 temp &= ~(0x1<<0);

4 temp |= (0x1<<0);

5 EINT0MASK = temp;

屏蔽外部中断0,看中断触发信号能不能通过它传达到上面的寄存器VIC0RAWINTR。看看VIC0RAWINTR的描述:

先不屏蔽中断,看看能否在VIC0RAWINTR看到中断信号:

01 /* EINT0MASK[0] = 0 : disMask EINT0 */

02 temp = EINT0MASK ;

03 temp &= ~(0x1<<0);

04 EINT0MASK = temp;

05

06 uart_init();

07 while (1)

08 {

09 for(ch='a';ch<='z';ch++){

10 if( (VIC0RAWINTR & 0x1)==0x1){

11 uart_putchar('+');

12 }

13 uart_putchar(ch);

14 delay();

15 }

16 }

按下KEY,触发中断,发现现象如下(没有清理EINT0PEND):

说明在VIC0RAWINTR 检测到中断触发信号了。

如果把EINT0MASK[0]设置为1,即屏蔽信号,看看结果:

怎么按KEY也检测不到中断触发信号,说明EINT0MASK是这里的一道关卡,中断触发信号能否传到上级要看这里有没有屏蔽掉,它相当于一个开关作用。

继续dismask中断触发信号,让它传递到VIC0RAWINTR ,然后清除中断悬起位,看现象是怎样的:

01 /* EINT0MASK[0] = 0 : disMask EINT0 */

02 temp = EINT0MASK ;

03 temp &= ~(0x1<<0);

04 EINT0MASK = temp;

05

06 uart_init();

07 while (1)

08 {

09 for(ch='a';ch<='z';ch++){

10 if( (VIC0RAWINTR & 0x1)==0x1){

11 uart_putchar('+');

12 EINT0PEND = 0x1;

13 }

14 uart_putchar(ch);

15 delay();

16 }

17 }

按一下KEY打印出一个“+”,然后查询VIC0RAWINTR 寄存器,发现中断触发信号没有了,说明EINT0PEND的值直接影响到VIC0RAWINTR 的值,VIC0RAWINTR 跟随EINT0PEND变化,EINT0PEND的变化实时反映到VIC0RAWINTR上来,当然得看MASK有没有屏蔽掉中断触发信号啦。

信号接着往上面传送,直到cpu内核检测到中断触发信号并产生对应的操作为止:

使用VIC(中断向量控制器)

VIC0INTENABLE的描述:

对应的清除寄存器VIC0INTENCLEAR的描述:

VIC0SELECT的描述:

我们这里选择IRQ方式,也可以是FIQ方式。

VIC0IRQSTATUS的描述:

VIC0FIQSTATUS描述:

我们选择IRQ方式,并且使能中断功能,看能不能到VIC0IRQSTATUS中查询到中断触发信号:

01 void mymain(void){

02 unsigned char ch;

03 unsigned int temp=0;

04

05 /* set GPNIO to EINT mode , 10 --> Eint */

06 temp = GPNCON ;

07 temp &= ~(0x3<<0);

08 temp |= (0x2<<0);

09 GPNCON = temp;

10

11 /* set EINT triger mode to falling eage ,01x = Falling edge */

12 temp = EINT0CON0 ;

13 temp &= ~(0x7<<0);

14 temp |= (0x3<<0);

15 EINT0CON0 = temp;

16

17 /* EINT0MASK[0] = 0 : disMask EINT0 */

18 temp = EINT0MASK ;

19 temp &= ~(0x1<<0);

20 //temp |= (0x1<<0);

21 EINT0MASK = temp;

22

23 /* VIC0INTENABLE[0]=1 : enable interrupt */

24 /* clear bit by VIC0INTENCLEAR */

25 temp = VIC0INTENABLE ;

26 temp &= ~(0x1<<0);

27 temp |= (0x1<<0);

28 VIC0INTENABLE = temp;

29

30 /* VIC0INTSELECT[0] = 0 : set to IRQ */

31 temp = VIC0INTSELECT ;

32 temp &= ~(0x1<<0);

33 VIC0INTSELECT = temp;

34

35 uart_init();

36 while (1)

37 {

38 for(ch='a';ch<='z';ch++){

39 if( (VIC0IRQSTATUS & 0x1)==0x1){

40 uart_putchar('+');

41 EINT0PEND = 0x1;

42 }

43 uart_putchar(ch);

44 delay();

45 }

46 }

按下KEY出现下面的现象:

按一次打印一个“+”,说明

如果是把VIC0INTENABLE对应位设置成disable,那么就会屏蔽掉中断信号,这里相当于又建立了一道关卡,它没同意就不能把信号传达到上一层。

1 /* VIC0INTENABLE[0]=0 : disable interrupt */

2 /* clear bit by VIC0INTENCLEAR */

3 temp = VIC0INTENABLE ;

4 temp &= ~(0x1<<0);

5 VIC0INTENABLE = temp;

现象:

怎么按KEY也不会打印出“+”,说明中断信号被屏蔽了。

当信号传达到这里的时候还得继续往上,还需要经过中断优先级的寄存器,判别那个中断优先级最高,这个只影响到中断的顺序,不影响中断信号的有无。但是在cpu内核的最近的地方还有个中断的开关,是个总开关——CPSR的I/F-bit,默认是关闭的。这个一打开了就会把中断信号送给cpu内核了。

打开最后这个总开关有两个写法,一个是在汇编里面写,一个是在c语言里面的嵌入汇编里面写,我们这里在c语言潜入汇编来写:

1 /* init CPSR I-bit */

2 //0101,0011

3 __asm{

4 mov r0,#0x53

5 msr cpsr,r0

6 }

但是编译的时候有警告,说应该吧这个r0定义成一个变量:

解决方法:

声明一个变量来代替寄存器

1 int val;

2 /* init CPSR I-bit */

3 //0101,0011

4 __asm

5 {

6 mov val,#0x53

7 msr cpsr,val

8 }

编译警告就没有了,这里出现警告是因为R0可能被别的使用的,这里使用会冲突,我们定义一个变量来代替R0就行了。

但是编译运行后发现还是按下就有“+”打印出来,没有什么跳转现象啊!

cpsr修改成为cpsr_cxsf或者CPSR_cxsf,再次编译运行后,按下按键会发现,不打印了,停下来了:

说明cpu检测到了中断信号,跳出了原来运行的主函数,但是按理来说是要重启的,这里可能是VIC没有打开。下面介绍怎么打开VIC

打开VIC:

1 int val2;

2 /* VIC Enable (cp15) */

3 __asm

4 {

5 mrc p15,0,val2,c1,c0,0

6 orr val2,val2,#(1<<24)

7 mcr p15,0,val2,c1,c0,0

8 }

这样cpu内核就能捕捉到中断了。编译运行,果然重启了。

但是怎么跳转的,跳转到哪里去呢??

中断发生了之后怎么办?

接下来有2种处理方法:

A) 简单的办法就是使用VIC 向量中断控制器的功能

1、跳转的地址向量要提前设置好

2、通知ARM11内核,启动VIC Port 功能

紧接着的问题是,如何在执行完beep之后返回主程序?(假设我们的目的是蜂鸣beep)原因:beep程序不能作为IRQ_handler

1)保存cpu现场STMFD

2)清除掉Pending bit,调用beep

3)恢复cpu现场LDMFD (LR-4)->PC ,SPSR -> CPSR

修改start.s,实现IRQ_handler

1)IRQ模式下的sp指针需要初始化

2)除了清除pending bit之外,还需要清除VIC0ADDRESS =0 ;

B)复杂的办法就是不用VIC,自己实现全过程

1、当IRQ 异常发生的时候,cpu 跳转到0x18

2、背景知识:reset 0 地址被映射map 到iROM (内容不可修改)

0 地址在iROM 中(0xD0000000)

iRAM (0xD0020000) -> 0x20000 (iROM 被映射到了0x20000)

通过md 命令,查看相关内存单元值,发现0x18: 0xEA000018

经过一系列分析,最终在iROM 中的跳转指令会加载从0xD0037400 地址开始的值,作为异常发生后要跳转的地址+offset ,因此只需要修改0xD0037418 的向量即可。3、(int)IRQ_handler -> 0xD0037400 + 0x18

如果是SWI 软件中断,则在0xD0037408 处填写swi_handler的地址

第一种方法

当程序有中断且cpu检测到中断的时候轮询就没有意义了,所以去掉轮训。在主函数外面声明一个handler函数:

1 void C_IRQ_handler(void)

2 {

3 EINT0PEND = 0x1;

4 uart_putchar(' ');

5 uart_putchar('+');

6 uart_putchar(' ');

7 }

那要怎么样才能调用到这个handler呢?

这就要注册这个函数地址到向量地址里面去了

1 /* VIC0VECTADDR[31:0] --> 0x71200100 : 0x7120017C */

2 /* Contains ISR vector addresses */

3 #define VIC0VECTADDR0 (*((volatile unsigned int *)0x71200100 ))

4 #define VIC1VECTADDR0 (*((volatile unsigned int *)0x71300100 ))

5 /* install IRQ handler to Vectors */

6 /* EINT0 --> VIC0VECTADDR[0] */

7 VIC0VECTADDR0 = (int)C_IRQ_handler;

这样注册后是不是就能跳转到这个函数去了呢?当然不是!VIC默认是关闭的(uboot里面可能打开VIC了,但是完全裸机的话,VIC默认是关闭的,要自己手动打开)。上面手动打开了VIC了,这里注册好函数之后编译运行,发现开发板还是重启,没有进入到handler里面来,什么原因呢??

********************************************************** **************************************************

下面是在汇编里面写的handler,要做中断sp的设置,返回地址lr的计算,现场保存,然后调用c语言里面的handler,返回后要恢复现场:

01 import C_IRQ_handler

02 export asm_IRQ_handler

03 asm_IRQ_handler

04 ldr sp,=0x58000000

05 ;lr=lr-4

06 sub r14,r14,#4

07

08 stmfd r13!,{r1-r12,r14}

09 bl C_IRQ_handler

10 ldmfd r13!,{r1-r12,pc}^

下面是c语言的handler,它要完成中断悬起位的清除,中断处理函数地址寄存器的清除,然后做别的事情:

1 void C_IRQ_handler(void)

2 {

3 EINT0PEND = 0x1;//clear pending bit

4 VIC0ADDRESS = 0;//clear address

5 uart_putchar(' ');

6 uart_putchar('+');

7 uart_putchar(' ');

8 }

这个程序直接下载到ram中运行,按下按键,中断触发就直接重启开发板了,但是放在ads上去调试却没有什么毛病能够进入中断正常运行(代码参考OK6410裸机调试笔记--> 6),不知道什么原因。

ARM体系结构详解之ARM异常处理

ARM处理器异常处理 所谓异常就是正常的用户程序被暂时中止,处理器就进入异常模式,例如响应一个来自外设的中断,或者当前程序非法访问内存地址都会进入相应异常模式。 1.1异常分类 (1)复位异常 当CPU刚上电时或按下reset重启键之后进入该异常,该异常在管理模式下处理。 (2)一般/快速中断请求 CPU和外部设备是分别独立的硬件执行单元,CPU对全部设备进行管理和资源调度处理,CPU要想知道外部设备的运行状态,要么CPU定时的去查看外部设备特定寄存器,要么让外部设备在出现需要CPU干涉处理时“打断”CPU,让它来处理外部设备的请求,毫无疑问第二种方式更合理,可以让CPU“专心”去工作,这里的“打断”操作就叫做中断请求,根据请求的紧急情况,中断请求分一般中断和快速中断,快速中断具有最高中断优先级和最小的中断延迟,通常用于处理高速数据传输及通道的中数据恢复处理,如DMA等,绝大部分外设使用一般中断请求。 (3)预取指令中止异常 该异常发生在CPU流水线取指阶段,如果目标指令地址是非法地址进入该异常,该异常在中止异常模式下处理。 (4)未定义指令异常 该异常发生在流水线技术里的译码阶段,如果当前指令不能被识别为有效指令,产生未定义指令异常,该异常在未定义异常模式下处理。 (5)软件中断指令(swi)异常 该异常是应用程序自己调用时产生的,用于用户程序申请访问硬件资源时,例如:printf()打印函数,要将用户数据打印到显示器上,用户程序要想实现打印必须申请使用显示器,而用户程序又没有外设硬件的使用权,只能通过使用软件中断指令切换到内核态,通过操作系统内核代码来访问外设硬件,内核态是工作在特权模式下,操作系统在特权模式下完成将用户数据打印到显示器上。这样做的目的无非是为了保护操作系统的安全和硬件资源的合理使用,该异常在管理模式下处理。 (6)数据中止访问异常 该异常发生在要访问数据地址不存在或者为非法地址时,该异常在中止异常模式下处理。 1.1.22异常发生的硬件操作 在异常发生后,ARM内核会自动做以下工作: l保存执行状态:将CPSR复制到发生的异常模式下SPSR中; l模式切换:将CPSR模式位强制设置为与异常类型相对应的值,同时处理器进入到

ARM中的中断要点

一、S5PV210中中断的特点 1、特点 ? Supports 93 vectored IRQ interrupts ? Fixed hardware interrupts priority levels ? Programmable interrupt priority levels ? Supports Hardware interrupt priority level masking ? Programmable interrupt priority level masking ? Generates IRQ and FIQ ? Generates Software interrupt 2、FIQ与IRQ的区别 1)FIQ和IRQ并不是中断源,而是中断的类型,我们可以将一个中断源设置成FIQ也可以设置成IRQ。2)FIQ是快速中断,IRQ是一般中断,FIQ的响应时间比IRQ短。 3)FIQ的优先级高于IRQ。 4)FIQ的分组寄存器(R8~R14)比IRQ(R13~R14)多。当在FIQ产生的时候,R8~R14不需要保存,响应的速度会快。 3、S5PV210的中断源

二、原理图分析

三、如何以中断的方式来检测按键:GPH2_2(EINT18) 、GPH2_3(EINT19) 按键的检测:轮询:将GPIO配置成输入……. 中断:将GPIO配置成外部中断……. 1、GPIO的配置,将一个GPIO配置成外部中断 2、外部中断的触发方式 (高电平、低电平、上升沿、下降沿)

3、外部中断的开关寄存器 0 = Enables Interrupt 打开中断 1 = Masked 关闭中断 4、外部中断判断寄存器 0 = Not occur 外部中断没有发生 1 = Occur interrupt 触发了中断

实验5 ARM中断编程

实验五 ARM中断编程 一、实验目的 1.学习键盘驱动原理。 2.掌握中断的使用方法。 二、实验内容 通过ARM的外部中断进行键盘的扫描,利用中断服务程序编写键盘的驱动,在超级终端上显示相应的键值。UART接收中断,以中断方式(而不是查询方式)实现串口数据的接收 三、预备知识 1.掌握在ADS1.2集成开发环境中编写和调试程序的基本过程。 2.会使用UltraEdit编辑C语言源程序。 3.了解ARM中断服务程序的框架结构。 4.了解编译后的映象文件的下载方法。 四、键盘驱动程序的原理 1.简单键盘扫描 通常在一个键盘中使用了一个瞬时接触开关,并且用如图1所示的简单电路,微处理器可以容易地检测到闭合。当开关打开时,通过处理器的I/O口的一个上拉电阻提供逻辑1;当开关闭合时,处理器的I/O口的输入将被拉低得到逻辑0。可遗憾的是,开关并不完善,因为当它们被按下或者被释放时,并不能够产生一个明确的1或者0。尽管触点可能看起来稳定而且很快地闭合,但与微处理器快速的运行速度相比,这种动作是比较慢的。当触点闭合时,其弹起就像一个球。弹起效果将产生如图2所示的好几个脉冲。弹起的持续时间通常将维持在5ms~30ms之间。如果需要多个键,则可以将每个开关连接到微处理器上它自己的输入端口。然而,当开关的数目增加时,这种方法将很快使用完所有的输入端口。为此我将用到矩阵键盘。 图1 简单键盘电路

图2 键盘抖动 2. 复杂矩阵键盘扫描 键盘上陈列这些开关最有效的方法(当需要5个以上的键时)就形成了一个如图3所示的二维矩阵。当行和列的数目一样多时,也就是方型的矩阵,将产生一个最优化的布列方式(I/O 端被连接的时候)。一个瞬时接触开关(按钮)放置在每一行与线一列的交叉点。矩阵所需的键的数目显然根据应用程序而不同。每一行由一个输出端口的一位驱动,而每一列由一个电阻器上拉且供给输入端口一位。 图3 矩阵键盘 键盘扫描过程就是让微处理器按有规律的时间间隔查看键盘矩阵,以确定是否有键被按下。一旦处理器判定有一个键按下,键盘扫描软件将过滤掉抖动并且判定哪个键被按下。每个键被分配一个称为扫描码的唯一标识符。应用程序利用该扫描码,根据按下的键来判定应该采取什么行动。换句话说,扫描码将告诉应用程序按下哪个键。

ARM异常中断机制.

ARM9(以S3C2410为例)中断机制 一、ARM异常机制介绍 ARM9处理器有7种工作模式。分别是(除了用户模式其他都是异常模式 用户模式(usr:ARM处理器正常的程序执行状态。 快速中断模式(fiq:用于高速数据传输或通道处理。 外部中断模式(irq:用于通用的中断处理。 管理模式(svc:操作系统使用的保护模式。 数据访问终止模式(abt:当数据或指令预取终止时进入该模式。 系统模式(sys:运行具有特权的操作系统任务。 未定义指令中止模式(und:当未定义的指令执行时进入该模式。 每种模式通过5位二进制编码进行标示: 用户模式10000 快速中断模式10001 外部中断模式10010 管理模式10011 数据访问终止模式10111 未定义指令中止模式11011 系统模式11111 模式编码存放在CPSR(程序当前状态寄存器,记录当前工作模式的编码的值)中的[4:0]。

快速中断模式、外部中断模式、数据访问终止模式、未定义指令中止模式、管理模式称为异常模式。 异常类型具体含义 复位当处理器的复位电平有效时,产生复位异常,程序跳转到复位异常处理程序处执行。 未定义指令遇到不能处理的指令时,产生未定义指令异常。 软件中断该异常由执行SWI指令产生,可用于用户模式下的程序调用特权操作指令。可使用该异常机制实现系统功能调用。 指令预取中止若处理器预取指令的地址不存在,或该地址不允许当前指令访问,存储器会向处理器发出中止信号,但当预取的指令被执行时,才会产生指令预取中止异常。 数据中止若处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时,产生数据中止异常。 IRQ(外部中断请求)当处理器的外部中断请求引脚有效,且CPSR中的I 位为0时,产生IRQ异常。系统的外设可通过该异常请求中断服务。 FIQ(快速中断请求)当处理器的快速中断请求引脚有效,且CPSR中的F 位为0时,产生FIQ异常。 当多个异常发生时,处理器根据优先级进行处理。优先级

ARM的中断原理

ARM的中断原理(转) 1.中断概述 CPU与外设的数据传输方式通常有以下3种方式:查询方式、中断方式、DMA方式。 所谓查询方式是指,CPU不到查询外设的状态,如果外设准备就绪则开始进行数据传输;如果外设还没有准备好,CPU将进入循环等待状态。很显然这样浪费了大量的CPU时间,降低了CPU的利用率。 所谓中断方式是指,当外设准备好与CPU进行数据传输时,外设首先向CPU发出中断请求,CPU 接收到中断请求并在一定条件下,暂时停止原来的程序并执行中断服务处理程序,执行完毕以后再返回原来的程序继续执行。由此可见,采用中断方式避免了CPU把大量的时间花费在查询外设状态的操作上,从而大大提高了CPU的执行效率。 1.中断概述 CPU与外设的数据传输方式通常有以下3种方式:查询方式、中断方式、DMA方式。 所谓查询方式是指,CPU不到查询外设的状态,如果外设准备就绪则开始进行数据传输;如果外设还没有准备好,CPU将进入循环等待状态。很显然这样浪费了大量的CPU时间,降低了CPU的利用率。 所谓中断方式是指,当外设准备好与CPU进行数据传输时,外设首先向CPU发出中断请求,CPU 接收到中断请求并在一定条件下,暂时停止原来的程序并执行中断服务处理程序,执行完毕以后再返回原来的程序继续执行。由此可见,采用中断方式避免了CPU把大量的时间花费在查询外设状态的操作上,从而大大提高了CPU的执行效率。 ARM系统包括两类中断:一类是IRQ中断,另一类是FIQ中断。IRQ是普通中断,FIQ是快速中断,在进行大批量的复制、数据传输等工作时,常使用FIQ中断。FIQ的优先级高于IRQ。 在ARM系统中,支持7类异常,包括:复位、未定义指令、软中断、预取中止、数据中止、IRQ和FIQ,每种异常对应于不同的处理器模式。一旦发生异常,首先要进行模式切换,然后程序将转到该异常对应的固定存储地址执行。这个固定的地址称为异常向量。异常向量中保存的通常为异常处理程序的地址。ARM的异常向量如下: 异常模式正常地址高向量地址 复位管理 0x00000000 0xFFFF0000 未定义指令未定义 0x00000004 0xFFFF 0004 软中断管理 0x00000008 0xFFFF 0008 预取指中止中止0x0000000C 0xFFFF 000C 数据中止中止0x00000010 0xFFFF0010 IRQ IRQ 0x00000018 0xFFFF0018

ARM-Linux下的GPIO中断程序.

ARM-Linux下的GPIO中断程序 [日期:2011-03-22] 来源:Linux社区作者:cskywit 今日为了调试ARM板上的GPIO引脚中断效果,以便在后续项目使用ARM与ZLG7290按键LED中断芯片连接中随意选择空闲的GPIO引脚来作为ZLG7290的中断信号线,特意编写了一个小的Linux GPIO中断驱动程序下载到开发板上做实验。经验证,这种软件中断方式也还差强人意。下面贴出自己编写的不成熟的代码,见笑(<-_->)。 实验的硬件电路为ARM GPIO的PB17连接一个共阴LED,PB18与PB19连接,PB18由中断驱动设置为低电平触发,PB19由GPIO驱动程序控制,上层应用程序通过驱动控制PB19高低电平变化,从而引发PB18发生中断,中断程序中控制PB17的LED亮和灭。 Linux中断驱动部分: /* * PB18_IRQTest.c * This is a test program for sam9260, using PB19(J5_18 pin) input a signal to PB18(J5_16 pin), * PB18 receive this signal as IRQ and make the LED linking on PB17((J5_14 pin)) turn on or turn off * * @Author: Cun Tian Rui * @Date :March.18.2011 */ #include #include #include #include #include #include #include #include #include #include #include #include #include

arm中断返回地址详细分析.

在ARM体系中,通常有以下3种方式控制程序的执行流程: 1、在正常执行过程中,每执行一条ARM指令,程序计数器PC的值加4个字节;每执行一条Thumb 指令,程序计数器PC加2个字节。整个过程是顺序执行的; 2、跳转B指令执行跳转操作;BL指令在执行跳转的同时,保存子程序返回地址;BX指令,执行跳转的同时,根据目标地址的最低位,可以将程序状态切换到Thumb状态;BLX指令执行上述3个操作; 3、当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场,在从异常中断处理程序退出时,要恢复被中断的程序的执行现场。当异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。 异常中断种类、异常中断向量地址和异常中断优先级别见下表: ARM运行的几种处理器模式如上表所示。其中,应用程序通常运行在用户模式下! 为了说明异常中断执行过程,先了解各处理器模式下的寄存器组,如下表: 重点:ARM处理器对异常中断的响应过程: ㈠、保存当前程序状态寄存器CPSR到对应异常中断的处理器模式下的SPSR中; ㈡、设置当前程序状态寄存器CPSR的处理器模式位M(4:0)为对应的处理器模式,并禁止IRQ 中断(设置I位=1);当进入的是FIQ模式时,禁止FIQ中断(设置F位=1); ㈢、将对应异常中断的处理器模式下的LR设置成返回地址; ㈣、将程序计数器PC值,设置成该异常中断向量地址,从而跳转到相应的异常中断处理程序处执行。 上述处理器对异常中断的响应过程可以用伪代码描述如下: R14=return Link SPSR=CPSR CPSR[4:0]=exception mde number CPSR[5] = 0 //所有异常均在ARM状态下处理(本句出自《基于ARM的嵌入式系统开发与实例》P32) if(==Reset or FIQ )then CPSR[6]=1 //禁止FIQ中断 CPSR[7] =1 //禁止IRQ中断 PC = exception vetor address 程序将自动跳转到对应异常中断的处理程序中。 上述过程,完全由处理器自动完成,所以,当发生一种异常中断时,寄存器R14 、CPSR、SPSR 和PC的值将是上述的结果!结果如下图所示: 下面是引用别人的文章: ARM处理器中主要有7个异常(2个中断异常): 1、复位异常;在以ARM为核的单片机中,常把下列事件作为引起复位的原因。 ? 上电复位:在上电后,复位使内部达到预定的状态,特别是程序跳到初始入口; ? 复位引脚上的复位脉冲:这是由外部其他控制信号引起的; ? 对系统电源检测发现过压或欠压; ? 时钟异常复位。 ARM处理器复位后,处理器硬件将进行以下操作: ? 强制进入管理模式;0b10011 ? 强制进入ARM状态;T=0 ? 跳转到绝对地址PC=0x00000000处执行;

ARM技术中英文缩写解说

ARM技术中英文缩写解说 中一些常见英文缩写解释 MSB:最高有效位; LSB:最低有效位; AHB:先进的高性能总线; VPB:连接片内外设功能的VLSI外设总线; EMC:外部存储器控制器; MAM:存储器加速模块; VIC:向量中断控制器; SPI:全双工串行接口; CAN:控制器局域网,一种串行通讯协议; PWM:脉宽调制器; ETM:嵌入式跟踪宏; CPSR:当前程序状态寄存器; SPSR:程序保护状态寄存器; 使用注意事项: 答:当改变 MAM 定时值时,必须先通过向 MAMCR 写入 0 来关闭 MAM,然后将新值写入 MAMTIM。最后,将需要的操作模式的对应值写入MAMCR,再次打开MAM。 对于低于 20MHz 的系统时钟,MAMTIM 设定为 001。对于 20MHz 到 40MHz 之间的系统时钟,建议将Flash 访问时间设定为2cclk,而在高于40MHz的系统时钟下,建议使用3cclk。 使用注意事项 答:如果在片内RAM当中运行代码并且应用程序需要调用中断,那么必须将中断向量重新映射到Flash地址0x0。这样做是因为所有的异常向量都位于地址0x0及以上。通过将寄存器MEMMAP(位于系统控制模块当中)配置为用户RAM模式来实现这一点。用户代码被连接以便使中断向量表装载到0x4000 0000。 4. ARM启动代码设计 答:ARM启动代码直接面对处理器内核和硬件控制器进行编程,一般使用汇编语言。启动代码一般包括:中断向量表 初始化存储器系统 初始化堆栈初始化有特殊要求的端口、设备 初始化用户程序执行环境 改变处理器模式 呼叫主应用程序 和 FIQ 之间的区别 答:IRQ和FIQ是ARM处理器的两种编程模式。IRQ是指中断模式,FIR是指快速中断模式。对于 FIQ 你必须尽快处理你的事情并离开这个模式。IRQ 可以被 FIQ 所中断,但 IRQ 不能中断 FIQ。为了使 FIQ 更快,所以这种模式有更多的影子寄存器。FIQ 不能调用 SWI(软件中断)。FIQ 还必须禁用中断。如果一个 FIQ 例程必须重新启用中断,则它太慢了,并应该是 IRQ 而不是 FIQ。

ARM处理器中断处理的理解

ARM处理器中断处理的理解 在发生外部中断时的处理过程如下图所示: 在发生外部中断时ARM程序跳转到 b HandlerIRQ;handler for IRQ interrupt 根据如下语句 LTORG HandlerFIQ HANDLER HandleFIQ HandlerIRQ HANDLER HandleIRQ HandlerUndef HANDLER HandleUndef 就会调用如下HANDLER宏: HandlerIRQ HANDLER HandleIRQ ;发生外部中断时调用这个宏,跳转到IsrIRQ HANDLER宏如下: MACRO $HandlerLabel HANDLER $HandleLabel ;在一个标号前使用$表示程序被汇编时将使用相应的值来代替$后的标号 $HandlerLabel ;可以将其想像成函数名,但这个函数名可以被不同名称(HandlerIRQ,HandlerFIQ)替代sub sp,sp,#4 ;decrement sp(to store jump address) stmfd sp!,{r0} ;PUSH the work register to stack(lr does't push because it return to original address) ldr r0,=$HandleLabel ;可以当成函数参数, HandleIRQ所指向的地址內裝的是IsrIRQ的入口地址 ;所以下面的語句实际上是load IsrIRQ的入口地址到r0 ldr r0,[r0] ;load the contents(service routine start address IsrIRQ的入口地址) of HandleXXX to r0 str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack, r0也就是IsrIRQ的入口地址to SP

armlinux内核中ARM中断实现详解.

linux-2.6.26内核中ARM中断实现详解(1) 作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM ATC授权培训讲师。 看了一些网络上关于linux中断实现的文章,感觉有一些写的非常好,在这里首先感谢他们的无私付出,然后也想再补充自己对一些问题的理解。先从函数注册引出问题吧。 一、中断注册方法 在linux内核中用于申请中断的函数是request_irq(),函数原型在 Kernel/irq/manage.c中定义: int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) irq是要申请的硬件中断号。 handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。 irqflags是中断处理的属性,若设置了IRQF_DISABLED (老版本中的 SA_INTERRUPT,本版zhon已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARED (老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的 SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag是可以通过或的方式同时使用的) dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。 devname设置中断名称,在cat /proc/interrupts中可以看到此名称。 request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。 关于中断注册的例子,大家可在内核中搜索下request_irq。 在编写驱动的过程中,比较容易产生疑惑的地方是: 1、中断向量表在什么位置?是如何建立的? 2、从中断开始,系统是怎样执行到我自己注册的函数的? 3、中断号是如何确定的?对于硬件上有子中断的中断号如何确定? 4、中断共享是怎么回事,dev_id的作用是? 本文以2.6.26内核和S3C2410处理器为例,为大家讲解这几个问题。

ARM中异常中断处理概述

异常中断处理概述 1.ARM中异常中断处理概述 1)在正常程序执行过程中,每执行一条ARM指令,程序计数器寄存器PC的值加4个字 节;每执行一条Thumb指令,程序计数器寄存器PC的值加两个字节.整个过程是顺序执行. 2)通过跳转指令,程序可以跳转到特定的地址标号处执行,或者跳转到特定的子程序处 执行; B指令用于执行跳转操作; BL指令在执行跳转操作的同时,保存子程序的返回地址; BX指令在执行跳转操作的同时,根据目标地址的最低位可以将程序状态切换到Thumb状态; BLX指令执行3个操作:跳转到目标地址处执行,保存子程序的返回地址(R15保存在R14中),根据目标地址的最低位可以将程序状态切换到Thumb状态. 3)当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执 行.在当异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行. 4)在进入异常中断处理程序时,要保存被中断的程序的执行现场,在从异常中断处理程 序退出时,要恢复被中断的程序的执行现场.本章讨论ARM体系中的异常中断机制. 2.ARM体系中异常中断种类. ARM体系中的异常中断如下表所示:

3. 中断向量表中指定了各异常中断及其处理程序的对应关系.它通常存放在存储地址的低端.在ARM体系中,异常中断向量表的大小为32字节.其中,每个异常中断占据4个字节大小,保留了4个字节空间. 每个异常中断对应的中断向量表的4 .通过这两种指令,程序将跳转到相应的异常中断处理程序处执行. 当几个异常中断同时发生时,就必须按照一定的次序来处理这些异常中断.在ARM 中通过给各异常中断富裕一定的优先级来实现这种处理次序.当然有些异常中断是不坑能同时发生的,如指令预取中止异常中断和软件中断(SWI)异常中断是有同一条指令的执行触发的,他们是不可能同时发生的.处理器执行某个特定的异常中断的过程中,称为处理器处于特定的中断模式.各异常中断的中断向量地址以及中断的处理优先级如表2所示. 4.异常中断使用的寄存器 各异常中断对应着一定的处理器模式.应用程序通常运行在用户模式下.ARM中的处理器模式如表3所示. 各种不同的处理器模式可能有对应于该处理器模式的物理寄存器组,如表4所示,其中,R13_svc表示特权模式下的R13寄存器,R13_abt表示中止模式下的R13寄存器,其余的各寄存器名称含义类推. 表4 各处理器模式的物理寄存器组

ARM的三种中断调试方法简介.

ARM的三种中断调试方法简介 1嵌入式软件开发流程参照嵌入式软件的开发流程。第一步:工程建立和配置。第二步:编辑源文件。第三步:工程编译和链接。第四步:软件的调试。第五步:执行文件的固化。在整个流程中,用户首先需要建立工程并对工程做初步的配置,包括配置处理器和配置调试设备。编辑工程文件,包括自己编写的汇编和C语言源程序,还有工程编译时需要编写的链接脚本文件,调试过程中需要编写存储区映像文件和命令脚本文件,以及上电复位时的程序运行 1 嵌入式软件开发流程 参照嵌入式软件的开发流程。第一步:工程建立和配置。第二步:编辑源文件。第三步:工程编译和链接。第四步:软件的调试。第五步:执行文件的固化。 在整个流程中,用户首先需要建立工程并对工程做初步的配置,包括配置处理器和配置调试设备。编辑工程文件,包括自己编写的汇编和C语言源程序,还有工程编译时需要编写的链接脚本文件,调试过程中需要编写存储区映像文件和命令脚本文件,以及上电复位时的程序运行入口的启动程序文件。 对后四种文件的理解很重要,其作用解释如下。 (1) 链接脚本文件:在程序编译时起作用。该文件描述代码链接定位的有关信息,包括代码段,数据段,地址段等,链接器必须使用该文件对整个系统的代码做正确的定位。在SDRAM中调试程序、在FLASH中调试或固化后运行的链接脚本文件应加以区分。(在IDE开发环境中使用扩展名*.ld) (2)命令脚本文件:在SDRAM中调试程序时起作用。在集成环境与目标连接时、软件调试过程中以及目标板复位后,有时需要集成环境自动完成一些特定的操作,比如复位目标板、清除看门狗、屏蔽中断寄存器、存储区映射等。这些操作可以通过执行一组命令序列来完成,保存一组命令序列的文本文件称为命令脚本文件(在 IDE开发环境中使用扩展名*.cs)。 (3)存储区映像文件:在SDRAM中调试程序时起作用。在软件调试过程中访问非法存储区在部分处理器和目标板上会产生异常,如果异常没有处理,则会导致软件调试过程无法继续,为了防止以上问题并调整仿真器访问速度以达到最合适的水平,提供这样一种用于描述各个存储区性质的文件叫存储区映像文件(在IDE开发环境中使用扩展名*.map)。 在程序的调试过程中可以选择使用存储区映像文件*.map和命令脚本文件*. cs 配合程序的调试。

ARM中断系统.

该文章介绍了ARM处理器的中断系统,以周立功公司的LPC2000为例。希望对大家有用! 1.1 中断源 LPC2000系列的向量中断控制器(VIC)支持32个中断请求输入,也即是支持32个中断源,见表5.1。这32个中断按顺序称为VIC通道0,VIC通道1,…,VIC通道31。 每一个VIC通道都支持软件中断与硬件中断,即每个中断均可由软件或硬件中断产生,软件中断与对应通道上的硬件中断是逻辑“或”的关系。软件中断可通过置位VICSoftInt寄存器相应位来产生,也可通过置位VICSoftIntClear 寄存器相应位来清除。 表5.1 外设功能的中断源 1.2 三种中断类型 LPC2000具有3类中断:FIQ、向量IRQ和非向量IRQ。LPC2000系列可通过对VICIntSelect和VICVectCntlx(x=0,1,…,15)这两类寄存器的设置,将以上的32个中断源设置为这三类中断的任何一种。其中,快速中断请求FIQ具有最高优先级。建议只分配一个中断请求给FIQ以减少中塅处理程序的延迟。当然,VIC支持多个FIQ中断。向量IRQ具有中等优先级。该级别最多可分配32个请求中的16个。32个请求中的任何一个都可以分配到16个向量IRQslot中的任意一个。其中,slot0具有最高优先级,而slot15则为最低优先级。非向量IRQ 具有最低优先级。 1.3 如何初始化某个中断源为三类中断中的一类 通过VICIntSelect中断选择寄存器将32个中断请求分配为FIQ或IRQ (包括向量IRQ与非向量IRQ);通过VICVectCntlx(x=0,1,…,15)来选择32个中断请求中的某个为向量IRQ并设定此中断请求为IRQ slotx(x对应于VICVectCntlx中的x)。若某个中断源被设定为IRQ,但却未通过VICVectCntlx 使能,则该中断源将被默认为非向量IRQ。 1.4 中断处理过程中断处理过程如下所示: 初始化:设置中断源为3种中断源之一,设置中断地址,使能中断,然后正常运行用户程序;当有IRQ中断产生时,VIC将会根据中断源设置VICVectAddr

arm中断处理流程

ARM编程特别是系统初始化代码的编写中通常需要实现中断的响应、解析跳转和返回等操作,以便支持上层应用程序的开发,而这往往是困扰初学者的一个难题。中断处理的编程实现需要深入了解ARM内核和处理器本身的中断特征,从而设计一种快速简便的中断处理机制。需要说明的是,具体的上层高级语言编写的中断服务函数不在本文的讨论范围之内。 ARM处理器异常中断处理概述 当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。当异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场。从异常中断处理程序退出时,要恢复被中断的程序的执行现场。ARM体系中通常在存储地址的低端固化了一个32字节的硬件中断向量表,用来指定各异常中断及其处理程序的对应关系。当一个异常出现以后,ARM微处理器会执行以下几步操作: 1)保存处理器当前状态、中断屏蔽位以及各条件标志位; 2)设置当前程序状态寄存器CPSR中相应的位; 3)将寄存器lr_mode设置成返回地址; 4)将程序计数器(PC)值设置成该异常中断的中断向量地址,从而跳转到相应的异常中断处理程序处执行。 在接收到中断请求以后, ARM处理器内核会自动执行以上四步,程序计数器PC总是跳转到相应的固定地址。从异常中断处理程序中返回包括下面两个基本操作: 1)恢复被屏蔽的程序的处理器状态; 2)返回到发生异常中断的指令的下一条指令处继续执行。 当异常中断发生时,程序计数器PC所指的位置对于各种不同的异常中断是不同的,同样,返回地址对于各种不同的异常中断也是不同的。例外的是,复位异常中断处理程序不需要返回,因为整个应用系统是从复位异常中断处理程序开始执行的。 支持中断跳转的解析程序 解析程序的概念和作用 如前所述,ARM处理器响应中断的时候,总是从固定的地址开始的,而在高级语言环境下开发中断服务程序时,无法控制固定地址开始的跳转流程。为了使得上层应用程序与硬件中断跳转联系起来,需要编写一段中间的服务程序来进行连接。这样的服务程序常被称作中断解析程序。 每个异常中断对应一个4字节的空间,正好放置一条跳转指令或者向PC寄存器赋值的数据访问指令。理论上可以通过这两种指令直接使得程序跳转到对应的中断处理程序中去。但实际上由于函数地址值为未知和其它一些问题,并不这么做。这里给出一种常用的中断跳转流程:

ARM处理器中断处理的编程实现.

ARM处理器中断处理的编程实现 ARM处理器中断处理的编程实现 类别:嵌入式系统 arm编程特别是系统初始化代码的编写中通常需要实现中断的响应、解析跳转和返回等操作,以便支持上层应用程序的开发,而这往往是困扰初学者的一个难题。中断处理的编程实现需要深入了解arm内核和处理器本身的中断特征,从而设计一种快速简便的中断处理机制。需要说明的是,具体的上层高级语言编写的中断服务函数不在本文的讨论范围之内。 arm处理器异常中断处理概述当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。当异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场。从异常中断处理程序退出时,要恢复被中断的程序的执行现场。arm体系中通常在存储地址的低端固化了一个32字节的硬件中断向量表,用来指定各异常中断及其处理程序的对应关系。当一个异常出现以后,arm 微处理器会执行以下几步操作:保存处理器当前状态、中断屏蔽位以及各条件标志位;设置当前程序状态寄存器cpsr中相应的位;将寄存器lr_mode设置成返回地址;将程序计数器(pc)值设置成该异常中断的中断向量地址,从而跳转到相应的异常中断处理程序处执行。在接收到中断请求以后, arm处理器内核会自动执行以上四步,程序计数器pc总是跳转到相应的固定地址。从异常中断处理程序中返回包括下面两个基本操作: 恢复被屏蔽的程序的处理器状态;返回到发生异常中断的指令的下一条指令处继续执行。当异常中断发生时,程序计数器pc所指的位置对于各种不同的异常中断是不同的,同样,返回地址对于各种不同的异常中断也是不同的。例外的是,复位异常中断处理程序不需要返回,因为整个应用系统是从复位异常中断处理程序开始执行的。支持中断跳转的解析程序解析程序的概念和作用如前所述,arm处理器响应中断的时候,总是从固定的地址开始的,而在高级语言环境下开发中断服务程序时,无法控制固定地址开始的跳转流程。为了使得上层应用程序与硬件中断跳转联系起来,需要编写一段中间的服务程序来进行连接。这样的服务程序常被称作中断解析程序。 每个异常中断对应一个4字节的空间,正好放置一条跳转指令或者向pc寄存器赋值的数据访问指令。理论上可以通过这两种指令直接使得程序跳转到对应的中断处理程序中去。但实际上由于函数地址值为未知和其它一些问题,并不这么做。这里给出一种常用的中断跳转流程: 图1中断跳转流程图这个流程中的关键部分是中断向量表,为了让解析程序能找到向量表,应该将向量表的地址固定化(编程者自定义)。这样,整个跳转流程的所有程序地址都是固定的,当中断触发后,就可以自动运行。其中,只有向量表的内容是可变的,编程者只要在向量表中填入正确的目标地址值就可以了。这使得上层中断处理程序和底层硬件跳转有机地联系起来。解析过程示例以一次irq跳转为例,假定中断向量表定义在

ARM之定时器0(中断)

ARM之定时器0(中断) 这也是一个很简单的程序,主要是应用ARM 实现定时1 秒中断的小程序, 主要说明ARM7 中中断的用法。程序如下: #include #define L5_Communicatin_Flag (1/****************************************************************** *********** 名称:IRQ_Time0()* 功能:定时器0 中断服务程序,取反BEEPCON 控制口。* 入口参数:无* 出口参数:无 ******************************************************************** ********/void __irq IRQ_Time0(void){if( (IO0SET&L5_Communicatin_Flag) == 0 ) //使I/O 口P1.17,p0.28 每隔1 秒翻转一次{IO0SET |= L5_Communicatin_Flag;} else{IO0CLR |= L5_Communicatin_Flag; } T0IR = 0x01; // 清除中断标志VICVectAddr = 0x00; // 通知VIC 中断处理结束} /******************************************************************** ********* 名称:Time0_Init()* 功能:定时器0 初始化函数。* 入口参数:无 * 出口参数:无 ******************************************************************** ********/void Time0_Init(void){/* Fcclk = Fosc*4 = 11.0592MHz*4 = 44.2368MHz Fpclk = Fcclk/4 = 44.2368MHz/4 = 11.0592MHz*/T0PR = 99; // 设置定时器0 分频为100 分频,得110592HzT0MCR = 0x03; // 匹配通道0 匹配中断并复位T0TCT0MR0 = 110592; // 比较值(1S 定时值)T0TCR = 0x03; // 启动并

ARM中断处理及状态机嵌套实现

ARM中断处理及状态机嵌套实现 1.ARM7 提供两种级别的中断, FIQ(Fast Interrupt Request 快中断) 一般中断低速反应中断IRQ。所有的中断请求一旦产生则中断反应会经过三个步骤 a. 输入阶段这个逻辑可以根据中断源被实现,需要0-2 个时钟周期 b.EIC 自身处理 2 个时钟周期 c.ARM7 的逻辑处理2.EIC Enhanced Interrupt Controller 增强型中断控制器EIC 硬件处理多路中断,中断优先运算和矢能。 a.32 路可屏蔽的中断, 映射到ARM 的CPU 中断请求总线 b.每路16 级可编程优先级映射IRQ c.硬件支持最大16 个中断嵌套 d.2 路可屏蔽的中断通过FIQ 中断请求总线 e.在0x18 处的寄存器装载的是最高优先及中断用户自定义的中断处理地址 f.16 个XTI 块外部中断3.中断处理过程 1.检查相关中断的请求屏蔽位 2.比较所有中断请 求的优先级,IRQ 当前中断是否优先级高于当前存储的中断。 3.自动装载EIC_SIRn[31:16]位用户自定义地址进入EIC_IVR[15:0]中 4.手动装载用户中断处理高16 位地址进入EIC_IVR[31:16] 5.当新产生一个中断则保存先前的中断优先级进入优先栈中。 6.当新的中断被接受则用新的优先级更新当前中断优先 级寄存器EIC_ICR 中断控制寄存器31-2 保留1. FIQ_EN:RW 是FIQ 允许的标志位置1 开启置0 关闭0.IRQ_EN:RW 是IRQ 允许的标志位置1 开启置0 关闭EIC_CICR 中断频道控制寄存器31-5 保留4-0.CIC[4:0]:R 是当前中断的序号, 是第几号中断由中断请求发生时硬件写入 EIC_CIPR 当前中断优先级寄存器31-4 保留3-0 CIP[3:0]:rw 是当前中断的优先级,在IRQ 总线上会自动探测进入的中断请求优先级和当前的优先级的高低。EIC_IVR 中断矢量寄存器IVR[31-16]:IRQ 用户写入的在程序初始化时,是中断 服务的高16 位地址IVR[15-0]:I 在中断请求接受后,从EIC_SIRn[31-16]的自定 义服务程序地址拷贝过来

ARM中断系统_百度文库.

该文章介绍了 ARM 处理器的中断系统,以周立功公司的 LPC2000为例。希望对大家有用! 1.1中断源 LPC2000系列的向量中断控制器(VIC支持32个中断请求输入,也即是支持32个中断源,见表5.1。这32个中断按顺序称为 VIC 通道0,VIC 通道1, …, VIC 通道31。 每一个 VIC 通道都支持软件中断与硬件中断,即每个中断均可由软件或硬件中断产生, 软件中断与对应通道上的硬件中断是逻辑“或” 的关系。软件中断可通过置位 VICSoftInt 寄存器相应位来产生, 也可通过置位 VICSoftIntClear 寄存器相应位来清除。 表5.1外设功能的中断源 1.2三种中断类型 LPC2000具有3类中断:FIQ、向量 IRQ 和非向量 IRQ。LPC2000系列可通过对 VICIntSelect 和VICVectCntlx(x=0,1,…,15这两类寄存器的设置,将以上的32个中断源设置为这三类中断的任何一种。其中, 快速中断请求 FIQ 具有最高优先级。建议只分配一个中断请求给 FIQ 以减少中塅处理程序的延迟。当然,VIC 支持多个FIQ 中断。向量 IRQ 具有中等优先级。该级别最多可分配32个请求中的16个。32个请求中的任何一个都可以分配到16个向量 IRQslot 中的任意一个。其 中,slot0具有最高优先级, 而 slot15则为最低优先级。非向量 IRQ 具有最低优先级。 1.3如何初始化某个中断源为三类中断中的一类 通过 VICIntSelect 中断选择寄存器将32个中断请求分配为 FIQ 或 IRQ (包括向量 IRQ 与非向量 IRQ ;通过VICVectCntlx(x=0,1,…,15来选择32个中断请求中的某个为向量 IRQ 并设定此中断请求为 IRQ slotx(x对应于 VICVectCntlx 中的 x 。若

ARM中断学习,讲的十分到位值得一看.

ARM 中断学习,讲的十分到位。。值得一看。 中断向量 b HandlerIRQ ;handler for IRQ interrupt 很自然,因为所有的单片机都是那样,中断向量一般放在开头,用过单片机的人都会很熟悉,那就不多说了。 异常服务程序 这里不用中断(interrupt)而用异常(exception),毕竟中断只是异常的一种情况, 下面主要分析的是“中断异常”说白了,就是我们平时单片机里面用的中断!!!所有由器件引起的中断,例如TIMER中断,UART 中断,外部中断等等,都有一个统一的入口,那就是中断异常IRQ ! 然后从IRQ的服务函数里面分辨出,当前究竟是什么中断,再跳转到相应的中断服务程序。这样看来,ARM比单片机要复杂一些了,不过原理是不变的。 上面说的就是思路,跟着这个思路来接着分析。 HandlerIRQ 很明显是一个标号,我们找到了 HandlerIRQ HANDLER HandleIRQ 这里是一个宏定义,我们再找到这个宏,看他是怎么定义的: MACRO $HandlerLabel HANDLER $HandleLabel $HandlerLabel sub sp,sp,#4 ;decrement sp(to store jump address) stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address) ldr r0,=$HandleLabel ;load the address of HandleXXX to r0 ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR) MEND 用HandlerIRQ 将这个宏展开之后得到的结果实际是这样的 HandlerIRQ sub sp,sp,#4 ;decrement sp(to store jump address) stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address) ldr r0,=HandleIRQ ;load the address of HandleXXX to r0 ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)

相关主题
文本预览
相关文档 最新文档