中断体系结构.docx

上传人:b****6 文档编号:7259916 上传时间:2023-01-22 格式:DOCX 页数:15 大小:383.43KB
下载 相关 举报
中断体系结构.docx_第1页
第1页 / 共15页
中断体系结构.docx_第2页
第2页 / 共15页
中断体系结构.docx_第3页
第3页 / 共15页
中断体系结构.docx_第4页
第4页 / 共15页
中断体系结构.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

中断体系结构.docx

《中断体系结构.docx》由会员分享,可在线阅读,更多相关《中断体系结构.docx(15页珍藏版)》请在冰豆网上搜索。

中断体系结构.docx

中断体系结构

中断体系结构

ARM体系CPU有以下7种工作模式。

.用户模式(usr):

ARM处理器正常的程序执行状态。

.快速中断模式(fiq):

用于高速数据传输或通道处理。

.中断模式(irq):

用于通用的中断处理。

.管理模式(svc):

操作系统使用的保护模式。

.数据访问终止模式(abt):

当数据或指令预取终止时进入该模式,可用于虚拟存储及存储保护。

.系统模式(sys):

运行具有特权的操作系统任务。

.未定义指令中止模式(und):

当未定义的指令执行时进入该模式,可用于支持硬件协处理器的软件仿真。

可以通过软件来进行模式切换,或者发生各类中断、异常时CPU自动进入相应的模式。

除用户模式外,其它6种工作模式都属于特权模式。

大多数程序运行于用户模式,进入特权模式是为了处理中断、异常,或者访问被保护的系统资源。

ARM920T有31个通用的32位寄存器和6个程序状态寄存器。

这37个寄存器分为7组,进入某个工作模式时就使用它那组的寄存器。

有些寄存器,不同的工作模式下有自己的副本,当切换到另一个工作模式时,那个工作模式的寄存器副本将被使用:

这些寄存器被称为备份寄存器。

在ARM状态下,每种工作模式都有16个通用寄存器和1个(或2个,这取决于工作模式)程序状态寄存器。

图中R0~R15可以直接访问,这些寄存器中除R15外都是通用寄存器,即它们既可以用于保存数据也可以用于保存地址。

另外,R13~R15稍有些特殊。

R13又被称为栈指针寄存器,通常被用于保存栈指针。

R14又被称为程序连接寄存器或连接寄存器,当执行BL子程序调用指令时,R14得到R15(程序计数器PC)的备份。

而当发生中断或异常时,对应的R14_svc、R14_irq、R14_fiq、R14_abt或R14_und中保存R15返回值。

快速中断模式有7个备份寄存器R8_fiq~R14_fiq,这使得进入快速中断模式执行很大部分程序时,甚至不需要保存任何寄存器(只要它们不改变R0~R7)。

每种工作模式除R0~R15共16个寄存器外,还有第17个寄存器CPSR,即“当前程序状态寄存器”。

CPSR中一些位被用于标识各种状态,一些位被用于标识当前处于什么工作模式。

除CPSR外,还有快速中断模式、中断模式、管理模式、数据访问终止模式和未定义指令中止模式等5种工作模式和一个寄存器——SPSR,即“程序状态保存寄存器”。

当切换进入这些工作模式时,在SPSR中保存前一个工作模式的CPSR值,这样,当返回前一个工作模式时,可以将SPSR的值恢复到CPSR中。

综上所述,当一个异常发生时,将切换进入相应的工作模式(为表述方便,下文中将它称为异常模式),这时ARM920TCPU核将自动完成如下事情。

a.在异常工作模式的连接寄存器R14中保存前一个工作模式的下一条,即将执行的指令的地址。

对于ARM状态,这个值是当前PC值加4或加8.

b.将CPSR的值复制到异常模式的SPSR。

c.将CPSR的工作模式位设为这个异常对应的工作模式。

d.令PC值等于这个异常模式在异常向量表中的地址,即跳转去执行异常向量表中的相应指令。

相反地,从异常工作模式退回到之前的工作模式时,需要通过软件完成如下事情。

a.前面进入异常工作模式时,连接寄存器中保存了前一个工作模式的一个指令地址,将它减去一个适当的值后赋值给PC寄存器。

b.将SPSR的值复制回CPSR。

ARM处理器对异常的响应过程可用伪代码描述如下:

R14_=returnlink

SPSR_=CPSR

CPSR[4:

0]=exceptionmodenumber

CPSR[5]=0/*当运行于ARM状态时*/

if==ResetorFIQthen

CPSR[6]=1/*禁止新的FIQ中断*/

CPSR[7]=1/*禁止新的IRQ中断*/

PC=exceptionvectoraddress

注意:

异常发生时异常模式R14的定义是PC-4。

IRQ、FIQ和ABT(指令预取)异常中断处理程序的返回:

发生IRQ或者FIQ异常中断时,指令已经执行完毕,PC指向当前指令后面的第3条指令。

因此IRQ或者FIQ的异常中断发生时,处理器将程序计数器的计算值(PC-4)保存到LR_IRQ或者LR_FIQ寄存器中。

这时LR_IRQ或者LR_FIQ寄存器的值指向当前指令后的第2条指令。

在指令预取时如果目标地址是非法的,该指令将被标记成有问题的指令,处理器产生指令预取ABT异常。

此刻PC的值还没有更新,它指向当前指令后的第2条指令。

指令预取ABT异常中断发生时,处理器将程序计数器的计算值(PC-4)保存到异常模式LR_ABT。

这时LR_ABT寄存器的值指向当前指令后的第1条指令。

当IRQ、FIQ和ABT(指令预取)异常中断处理程序退出时,前两种情况下应该执行断点的下一条指令,后一种情况下程序应该返回到有问题的指令处(即断点指令),重新读取并执行。

无论上述三种情况的那一种,返回操作都应该通过SUBSPC,LR,#4指令实现。

该指令将寄存器LR中的值复制到程序计数器PC中,实现程序返回,同时将SPSR_SVC或者SPSR_UND寄存器的内容复制到CPSR中。

不论何种CPU,中断的处理过程是相似的。

(1)中断控制器汇集各类外设发出的中断信号,然后告诉CPU。

(2)CPU保存当前程序的运行环境(各个寄存器等),调用中断服务程序(ISR)来处理这些中断。

(3)在ISR中通过读取中断控制器、外设的相关寄存器来识别这是哪个中断,并进行相应的处理。

(4)清除中断:

通过读写中断控制器和外设的相关寄存器来实现。

(5)最后恢复被中断程序的运行环境(即上面保存的各个寄存器等),继续执行。

SUBSRCPND和SRCPND寄存器表明有哪些中断被触发了,正在等待处理;SUBMASK和MASK用于屏蔽某些中断。

“Requestsource(withoutsub-register)”中的中断源被触发之后,SRCPND寄存器中相应位被置1,如果此中断没有被INTMASK寄存器屏蔽或者快速中断的话,它将被进一步处理。

“Requestsource(withsub-register)”中的中断源被触发之后,SUBSRCPND寄存器中的相应位被置1,如果此中断没有被INTSUBMASK寄存器屏蔽的话,它在SRCPND寄存器中的相应位也被置1,之后的处理过程就和“Requestsource(withoutsub-register)”一样了。

在SRCPND寄存器中,被触发的中断的相应位被置1,等待处理。

如果被触发的中断有快速中断(FIQ)——MODE(INTMODE寄存器,FIQ只能分配一个,即INTMOD中只能有一位设为1)中为1的位对应的中断是FIQ,则CPU进入快速中断模式(FIQMode)进行处理。

对于一般中断IRQ,可能同时有几个中断被触发,未被INTMASK寄存器屏蔽的中断经过比较后,选出优先级最高的中断,此中断在INTPND寄存器中的相应位被置1,然后CPU进入中断模式(IRQMode)进行处理。

中断服务程序可以通过读取INTPND寄存器或者INTOFFSET寄存器来确定中断源。

使用中断的步骤如下:

(1)设置好中断模式和快速中断模式下的栈:

当发生中断IRQ时,CPU进入中断模式,这时使用中断模式下的栈;当发生快速中断FIQ时,CPU进入快速中断模式,这时使用快速中断模式下的栈。

InitStacks:

mrsr0,cpsr

bicr0,r0,#MODEMASK

orrr1,r0,#UNDEFMODE|NOINT

msrcpsr_c,r1@UndefMode

ldrsp,=UndefStack@UndefStack=0x33FF_5C00

orrr1,r0,#ABORTMODE|NOINT

msrcpsr_c,r1@AbortMode

ldrsp,=AbortStack@AbortStack=0x33FF_6000

orrr1,r0,#IRQMODE|NOINT

msrcpsr_c,r1@IRQMode

ldrsp,=IRQStack@IRQStack=0x33FF_7000

orrr1,r0,#FIQMODE|NOINT

msrcpsr_c,r1@FIQMode

ldrsp,=FIQStack@FIQStack=0x33FF_8000

bicr0,r0,#MODEMASK|NOINT

orrr1,r0,#SVCMODE

msrcpsr_c,r1@SVCMode

ldrsp,=SVCStack@SVCStack=0x33FF_5800

(2)准备好中断处理函数。

a.异常向量表中设置好当进入中断模式或快速中断模式时的跳转函数,它们的异常向量地址分别为0x00000018、0x0000001c。

bReset

@0x04:

未定义指令中止模式的向量地址

bHandlerUndef

@0x08:

管理模式的向量地址,通过SWI指令进入此模式

bHandlerSWI

@0x0c:

指令预取终止导致的异常的向量地址

bHandlerPrefetchAbort

@0x10:

数据访问终止导致的异常的向量地址

bHandlerDataAbort

@0x14:

保留

bHandlerNotUsed

@0x18:

中断模式的向量地址

bHandlerIRQ

@0x1c:

快中断模式的向量地址

bHandlerFIQ

跳转到具体的异常处理函数:

HandlerFIQ:

HANDLERHandleFIQ

HandlerIRQ:

HANDLERHandleIRQ

HandlerUndef:

HANDLERHandleUndef

HandlerSWI:

HANDLERHandleSWI

HandlerDataAbort:

HANDLERHandleDabort

HandlerPrefetchAbort:

HANDLERHandlePabort

HandlerNotUsed:

b.

HANDLER是一个宏定义,它将跳转到具体的函数进行执行。

.macroHANDLERHandleLabel

subsp,sp,#4

stmfdsp!

{r0}

ldrr0,=\HandleLabel

ldrr0,[r0]

strr0,[sp,#4]

ldmfdsp!

{r0,pc}

.endm

b.中断服务程序(ISR)。

IRQ、FIQ的跳转函数,最终将调用具体中断的服务函数。

对于IRQ,读取INTPND寄存器或INTOFFSET寄存器的值来确定中断源,然后分别处理。

IsrIRQ:

sublr,lr,#4@计算返回地址

stmfdsp!

{r0-r12,lr}@保存使用到的寄存器

subsp,sp,#4@保留pc寄存器的值

stmfdsp!

{r8-r9}@把r8r9按入堆栈

ldrlr,=int_return@设置调用ISR即EINT_Handle函数后的返回地址

ldrr9,=INTOFFSET@把中断偏移INTOFFSET的地址装入r9里面

ldrr9,[r9]@取出INTOFFSET单元里面的值给r9

ldrr8,=HandleEINT0@向量表的入口地址赋给r8

addr8,r8,r9,lsl#2@求出具体中断向量的地址

ldrr8,[r8]@中断向量里面存储的中断服务程序的入口地址赋给r8

strr8,[sp,#8]@按入堆栈

ldmfdsp!

{r8-r9,pc}@堆栈弹出,跳转到相应的中断服务程序

int_return:

ldmfdsp!

{r0-r12,pc}^@中断返回,^表示将spsr的值复制到cpsr

对于FIQ,因为只有一个中断可以设为FIQ,无须判断中断源。

c.清除中断:

如果不清除中断,则CPU会误以为中断又一次发生了。

可以在调用ISR之前清除中断,也可以在调用ISR之后清除中断,这取决于在ISR执行过程中,这个中断是否可能继续发生、是否能够丢弃。

如果在ISR执行过程中,这个中断可能发生并不能丢弃,则在调用ISR之前清除中断,这样在ISR执行过程中发生的中断能够被各寄存器再次记录并通知CPU;如果在ISR执行过程中,这个中断不会发生或者可以丢弃,则在调用ISR之后清除中断。

清除中断时,从源头开始:

首先,需要的话,操作具体外设清除中断信号;其次,清除SUBSRCPND(用到的话),SRCPND寄存器中相应位(往相应位写1即可);最后,清除INTPND寄存器中的相应位(往相应位写1即可),最简单的方法就是“INTPND=INTPND”。

(3)进入、退出中断模式或快速中断模式时,需要保存、恢复被中断程序的运行环境。

a.对于IRQ,进入和退出的代码如下:

sublr,lr,#4//计算返回地址

stmdbsp!

{r0-r12,lr}//保存使用到的寄存器

……//中断处理

ldmiasp!

{r0-r12,pc}^//中断返回,^表示将spsr的值赋给cpsr

b.对于FIQ,进入和退出的代码如下:

sublr,lr,#4//计算返回地址

stmdbsp!

{r0-r7,lr}//保存使用到的寄存器

……//中断处理

ldmiasp!

{r0-r7,pc}^//中断返回,^表示将spsr的值赋给cpsr

(4)根据具体中断,设置相关外设。

(5)对于“Requestsources(withsub-register)”中的中断,将INTSUBMASK寄存器中相应位设为0。

(6)确定使用此中断的方式:

FIQ或IRQ。

如果是FIQ,则在INTMODE寄存器中设置相应位为1.如果是IRQ,则在PRIORITY寄存器中设置优先级。

(7)如果是IRQ,将INTMASK寄存器中相应位设为0(FIQ不受INTMASK寄存器控制)。

(8)设置CPSR寄存器中的I-bit(对于IRQ)或F-bit(对于FIQ)为0,使能IRQ或FIQ。

以下是一个按键的中断测试程序。

主要做以下几件事:

初始化中断,中断函数注册,开中断,如果中断测试完毕则关掉相应的中断。

基于bootloader的设计,在写中断的时候,只需要将中断函数的地址写到我们规定的地址即可。

关于bootloader的设计,后续再作介绍。

#defineGPB5_out(1<<(5*2))//LED1

#defineGPB6_out(1<<(6*2))//LED2

#defineGPB7_out(1<<(7*2))//LED3

#defineGPB8_out(1<<(8*2))//LED4

#defineGPF4_eint(2<<(4*2))//K2,EINT4

#defineGPF2_eint(2<<(2*2))//K3,EINT2

#defineGPF1_eint(2<<(1*2))//K1,EINT1

#defineGPF0_eint(2<<(0*2))//K4,EINT0

voidinit_led(void)

{

GPBCON=GPB5_out|GPB6_out|GPB7_out|GPB8_out;

GPBDAT=0xffff;

}

/*

*初始化GPIO引脚为外部中断

*GPIO引脚用作外部中断时,默认为低电平触发、IRQ方式(不用设置INTMOD)

*/

voidinit_irq(void)

{

GPFCON=GPF0_eint|GPF1_eint|GPF2_eint|GPF4_eint;

EINTMASK&=(~(1<<4));

PRIORITY=(PRIORITY&((~0x01)|(0x3<<7)))|(0x0<<7);

INTMSK&=(~(1<<0))&(~(1<<1))&(~(1<<2))&(~(1<<4));

}

voidEINT_Handle()

{

unsignedlongoft=INTOFFSET;

switch(oft)

{

//K4被按下

case0:

{

GPBDAT|=(0x0f<<5);//所有LED熄灭

GPBDAT&=~(1<<8);//LED4点亮

break;

}

case1:

{

GPBDAT|=(0x0f<<5);//所有LED熄灭

GPBDAT&=~(1<<5);//LED3点亮

break;

}

//K3被按下

case2:

{

GPBDAT|=(0x0f<<5);//所有LED熄灭

GPBDAT&=~(1<<7);//LED3点亮

break;

}

//K1或K2被按下

case4:

{

GPBDAT|=(0x0f<<5);//所有LED熄灭

GPBDAT&=~(1<<6);//K2被按下,LED2点亮

break;

}

default:

break;

}

//清中断

if(oft==4)

EINTPEND=(1<<4);

SRCPND=1<

INTPND=1<

}

voidKeyScan_Test(void)

{

charc;

init_led();//led初始化

init_irq();

printf("\nKeyScanTest,pressESCkeytoexit!

\n");

ClearPending(BIT_EINT0|BIT_EINT1|BIT_EINT2|BIT_EINT4_7);

pISR_EINT0=pISR_EINT1=pISR_EINT2=pISR_EINT4_7=(int)EINT_Handle;//注册中断函数

EnableIrq(BIT_EINT0|BIT_EINT1|BIT_EINT2|BIT_EINT4_7);

//while

(1);

while((c=get_c())!

=0x1b);

DisableIrq(BIT_EINT0|BIT_EINT1|BIT_EINT2|BIT_EINT4_7);

}

对于pISR_EINT0、pISR_EINT1、pISR_EINT2、pISR_EINT4_7等相关的二级中断地址我们已经有了定义。

#define_ISR_STARTADDRESS0x31ffff00

//Exceptionvector

#definepISR_RESET(*(unsigned*)(_ISR_STARTADDRESS+0x0))

#definepISR_UNDEF(*(unsigned*)(_ISR_STARTADDRESS+0x4))

#definepISR_SWI(*(unsigned*)(_ISR_STARTADDRESS+0x8))

#definepISR_PABORT(*(unsigned*)(_ISR_STARTADDRESS+0xc))

#definepISR_DABORT(*(unsigned*)(_ISR_STARTADDRESS+0x10))

#definepISR_RESERVED(*(unsigned*)(_ISR_STARTADDRESS+0x14))

#definepISR_IRQ(*(unsigned*)(_ISR_STARTADDRESS+0x18))

#definepISR_FIQ(*(unsigned*)(_ISR_STARTADDRESS+0x1c))

//Interruptvector

#definepISR_EINT0(*(unsigned*)(_ISR_STARTADDRESS+0x20))

#definepISR_EINT1(*(unsigned*)(_ISR_STARTADDRESS+0x24))

#definepISR_EINT2(*(unsigned*)(_ISR_STARTADDRESS+0x28))

#definepISR_EINT3(*(unsigned*)(_ISR_STARTADDRESS+0x2c))

#definepISR_EINT4_7(*(unsigned*)(_ISR_STARTADDRESS+0x30))

#definepISR_EINT8_23(*(unsigned*)(_ISR_STARTADDRESS+0x34))

#definepISR_CAM(*(unsigned*)(_ISR_STARTADDRESS+0x38))

#definepISR_BAT_FLT(*(unsigned*)(_ISR_STARTADDRESS+0x3c))

#definepISR_TICK(*(unsigned*)(_ISR_STARTADDRESS+0x40))

#definepISR_WDT_AC97(*(unsigned*)(_ISR_STARTADDRESS+0x44))

#definepISR_TIMER0(*(unsigned*)(_ISR_STARTADDRESS+0x48))

#definepISR_TIMER1(*(unsigned*)(_ISR_STARTADDRESS+0x4c))

#definepISR_TIMER2(*(unsigned*)(_ISR_STARTADDRESS+0x50))

#definepISR_TIMER3(*(unsigned*)(_ISR_STARTADDRESS+0x54))

#definepISR_TIMER4(*(unsigned*)(_ISR_STARTADDRESS+0x58))

#definepISR_UART2(*(unsigned*)(_ISR_STARTADDRESS+0x5c))

#definepISR_LCD(*(unsigned*)(_ISR_STARTADDRESS+0x60))

#definepISR_DMA0(*(unsigned*)(_ISR_STARTADDRESS+0x64))

#definepISR_DMA1(*(u

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 哲学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1