TQ2440裸机中断(外部中断)

1. 关于中断

1.所谓中断,是指CPU在正常运行程序时,由于内部/外部事件或由程序预先安排的事件,引起CPU中断正在运行的程序,而转到为内部/外部事件或为预先安排的事件服务的中断程序中去,服务完毕,再返回去执行刚才被中断的程序。

2.什么是中断优先级

中断优先级是指,中断源被响应和处理的优先等级。设置优先级的目的是为了在有多个中断源同时发出中断请求时,CPU能够按照预定的顺序(如:按事件的轻重缓急处理)进行响应并处理。

3.什么是中断嵌套

中断嵌套是指当CPU正在处理某个中断源即正在执行中断服务程序时,会出现优先级更高的中断源申请中断,为了使更急的中断源及时得到服务,需要暂时中断(挂起)当前正在执行的级别较低的中断服务程序,去处理更高级别的中断源,待执行完毕后再返回来执行低优先级的中断服务程序。但中断级别低的中断源不能中断级别高的中断服务,这就是中断嵌套,并且称这种中断嵌套方式为完全嵌套方式。

4.什么是中断向量

中断向量是中断服务程序的入口地址,中断向量一般是固定的,我们需要把我们写好的中断服务程序(ISR)的入口地址写道中断向量表中,这样在发生中断时,CPU就会自动跳转到中断向量表中找到它要执行的中断服务程序了。

5.什么是硬中断,什么是软中断

硬中断是由外部事件引起的因此具有随机性和突发性;软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的。

 

2. S3C2440/S3C2410中断体系结构

6.ARM体系 CPU的7种工作模式:

· 用户模式(usr): ARM处理器正常的程序执行状态(对应于LINUX的用户态)
· 快速中断模式(fiq): 用于高速数据传输或通道处理
· 中断模式(irq):用于通用的中断处理
· 管理模式(svc):操作系统使用的保护模式(对应于内核态)
· 数据访问终止模式(abt): 当数据或指令预取时进入该模式,可用于虚拟存储及存储保护
· 系统模式(sys) :运行具有特权操作系统任务
· 未定义指令中止模式(und): 当为定义的指令执行时进入该模式,可用于支持硬件协处理的软件仿真

可以通过软件来进行模式切换,或者发生各类中断,异常时CPU自动进入相应的模式。除用户模式外,其余的6中工作模式都属于特权模式。大多数程序运行于用户模式,进入特权模式是为了处理中断,异常,或者访问被保护的系统资源。

ARM920T的寄存器分为7组,其每个工作模式都拥有对应的寄存器组。其中有些寄存器是共用的,有些寄存器在不同模式下有自己的副本。当切换到另一个 工作模式时,那个工作模式的寄存器副本将被使用;这些寄存器成为备份寄存器(下图中使用灰色三角形标记的寄存器)


R0-R15可以直接访问,R13-R15稍有特殊,R13又称为 栈指针寄存器,通常用于保存栈指针。R14又称为程序连接寄存器或连接寄存器,比如当执行BL子程序调用指令时,R14得到调用前的程序计数器 PC(R15)的备份,以供子程序返回之用。当发生中断和异常时,对应的R14_svc、R14_irq、R14_fiq、R14_abt和 R14_und保存R15返回值,R15是程序计数器PC。
PC(程序计数器),CPSR(当前程序状态寄存器)寄存器是程序执行时必不可少的寄存器。每组寄存器都有自己独立的SPSR,R14是为了保存CPSR和PC进入异常前的值。

7.ARM920T异常处理的过程——从寄存器值的变化和地址跳转两个角度

7.1 ·ARM920T异常处理的过程——寄存器值变化角度

ARM920T CPU 将在异常(包括中断)的进入和退出时自动完成的工作:
在处理异常前,必须保存当前处理器的状态(PC和CPSR值),当中断程序处理程序完成后,原来的程序能够继续执行。
处理一个异常: 
· 将下一条指令的地址(PC)保存在相应的LR(R14)寄存器中。如果异常是从ARM状态进入,则保存在LR(R14)寄存器中的下一条指令的地址。如果是从Thumb状态进入,则保存在LR寄存器中的是当前PC的偏移值。它能使程序异常返回后从正确的位置重新开始。这就意味着异常处理不需要确定异常是从何种状态进入的。
· 将CPSR复制到相应的SPSR中
· 将CPSR的工作模式位设置为这个异常对应的工作模式
· 令PC值等于这个异常模式在异常向量表中的地址,即跳转去执行异常的向量表中的相应指令
退出一个异常:
· 前面进入异常工作模式时,连接寄存器中保存了前一个工作模式的下一个指令的地址,将它减去一个适当的值(图二)后赋给PC寄存器。
· 将SPCR值复制回CPSR
                           进入/退出异常模式PC地址

 

CPSR各位意义:
· T位:置位时,CPU处于Thumb状态,否则处于ARM状态
· 中断禁止位: I位和F位属于中断禁止位,他们被置位时,IRQ中断,FIQ中断分别被禁止。
· 工作模式: 表明CPU当前处于什么工作模式,可以编写这些位,使CPU进入指定的工作模式。


中断处理过程:
· 中断控制器汇集各类外设发出的中断信号,然后通知CPU
· CPU保存程序的运行环境(保存相应寄存器的值),调用中断服务程序(ISR)来处理这些中断。
· 在ISR中通过读取中断控制器,外设的相关寄存器来识别这个是那个中断,并进行相应的处理
· 清除中断: 通过读写中断控制器和外设的相关寄存器来实现(要记得清除中断,记得当时面试过一个题目,面试官说中断处理最重要的就是要清除中断)
· 最后恢复被中断程序的运行环境(即上面保存的各个寄存器等),继续执行

(FIQ私有R8-R14,IRQ私有R13-R14这几个寄存器,所以,FIQ比IRQ中断速度要快,因为省去了保存及恢复R8-R12这几个寄存器的过程)

7.2 ARM920T异常处理的过程——地址跳转变化角度

通常嵌入式处理器都有一张中断向量表,当中断出现时,必须调用向量表,向量表一般为与0 地址处,只要在对应的地址上写上跳转指令就实现了中断向量表。
 ARM9的中断向量表
 地址  异常
0x0000 0000  复位
0x0000 0004  未定义指令
0x0000 0008  软件中断
0x0000 000c  中止(预取指令)
0x0000 0010  中止(数据)
0x0000 0014  保留
0x0000 0018  IRQ(外部中断请求)
0x0000 001c  IQ(快速中断请求)

中断处理的过程如下图:

8.S3C2440S3C2410中断相关寄存器寄存器设置

中断相关寄存器的设置包括中断控制寄存器设置和引脚(IO)模式的设置,在这里我只介绍各个环节设计到的寄存器及其功能,而对于具体的设置我不做详细介绍,请参考芯片手册(interruptController And IO Ports)

 
S3C2440S3C2410中断控制寄存器
S3C2440S3C2410中断控制寄存器有5大类:
·  源待决寄存器(SRCPND)
当中断源产生中断信号时,在SRCPND相应位置位,至于CPU相应哪个中断不是SRCPND的工作。
· 中断模式寄存器(INTMOD)
该寄存器是设置中断模式是FIQ还是IRQ
(默认情况是IRQ,触发中断进入IRQ模式)
·  中断掩码寄存器(INTMSK)
该寄存器是中断使能,当置位时,屏蔽该中断信号。
·  优先级寄存器(PRIORITY)
该寄存器是设置IRQ模式下中断的优先级
·  中断源待决寄存器(INTPND)
该寄存器的值决定CPU响应哪个中断,即只有一位被置位,但是该寄存器值一般是不用设置的(清楚中断的需要设置),该寄存器的值是系统自动计算得出来的值
这五类寄存器值的设置里,中断掩码寄存器和优先级寄存器设置是比较复杂的。中断模式寄存器、中断掩码寄存器、中断源待决寄存器涉及到子寄存器(子寄存器说法不很准确)的设置,就是关于EINT8_EINT23中断掩码寄存器的设置和中断源待决寄存器的设置

注:INTOFFSET寄存器用来表示INTPND寄存器中 那个被置位了,即INTPND寄存器中位[X]为1时INTOFFSET寄存器的值为X(X为0~31)上图展示了中断处理框图(硬件实现角 度)Request source(with sub -register)表示INT_RXD0,INT_TXD0等中断源(S3C2440中有15个),他们不同于Request source(without sub-regiser).假如Request source(with sub -register)中的中断源被触发后,SUBSRCPND寄存器的相应位置1,如果此中断没有被INTSUBMSK寄存器屏蔽,它在SRCPND寄存 器中的相应位置1,之后的过程和Request source(without sub-regiser)一样了。(SUBSCRCPND,带子中断,如UART中断,又可以分为TX RX中断)

3. 代码分析

代码地址:http://download.csdn.net/detail/forsakening/5489403

/* 外部中断:按键中断,控制LED灯的亮灭 */
/*
 * 1.设置IO口为外中断模式
 */
#define KEY1 (2 << 2) 
#define KEY2 (2 << 8)
#define KEY3 (2 << 4)
#define KEY4 (2 << 0)

void Key_Init(void)
{
	rGPFCON &= ~((3 << 0) | (3 << 2) | (3 << 4) | (3 << 8)) ;
	/* GPFCON: 00:input 01:output 10:EINT */
	rGPFCON |= KEY1 | KEY2 | KEY3 | KEY4 ;
	rGPFDAT |= (1 << 0) | (1 << 1) | (1 << 2 ) | (1 << 4) ;//将键盘对应的四个引脚置为高电平,完成初始化工作	
}

void Delay1s(void)
{
	int i=0;
	for (;i<1000000;i++);		
}

/*
 * 2.使能中断:打开INTMSK中断屏蔽
 *   INTMSK有单独位来屏蔽外部中断0-3。对于4-7用EINTMASK来区分
 */
void Irq_Init(void)
{
	rINTMSK   &= ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4)) ;//使能外部中断0,1 ,2 ,4
	rEINTMASK &= (~(1 << 4)) ;//使能外部中断4	
}

/*
 * 3.中断服务程序:a)中断向量表的安装
 *               b)中断处理,记得清除中断
 */
/*
 * #define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))
 * _ISR_STARTADDRESS是中断的入口地址
 * 在启动代码中提到,若发生中断,(以IRQ为例)动作是
 * 1)b HandlerIRQ, 一级查找
 * 2)HandlerIRQ HANDLER HandleIRQ,执行HandleIRQ对应的程序
 * 3)根据INTOFFSET确定是哪个中断源,计算出偏移量,
 *   在HandleEINT0的基础上偏移,执行中断程序,二级查找
 * 4)HandleEINT0的地址和pISR_EINT0所在的地址实际上是一样的,代表的就是中断服务程序
 *   不过HandleEINT0是一个地址,pISR_EINT0代表地址里存放的数值(实际上是真正服务程序的地址Eint0_Isr)
 */
void Isr_Init(void)
{
	pISR_EINT0 = (unsigned int)Eint0_Isr ;
	pISR_EINT1 = (unsigned int)Eint1_Isr ;
	pISR_EINT2 = (unsigned int)Eint2_Isr ;
	pISR_EINT4_7 = (unsigned int)Eint4_7_Isr ;/**/
}

/*
 * SRCPND和INTPND的每一个位代表一个中断源,当有中断产生时,对应的位置会自动置1
 * 清除此中断需要往对应位置写1
 * 对于外部中断4-7,由于是由子中断控制,还需要向EINTPEND中对应位置写1
 * 对于启动代码中所说的INTOFFSET寄存器,其用来标识INTPND的哪种类型中断发生了,
 * 当SRCPND和INTPND对应的中断标志位清除后,INTOFFSET对应位会被自动清零
 */
void __irq Eint0_Isr(void)
{
	Led1_On();Delay1s() ;Led1_Off() ;
	
	rSRCPND |= 1 << 0 ;//清除这一位的话,会自动清除INTOFFSET这一位的;
	rINTPND |= 1 << 0 ;	
}

void __irq Eint1_Isr(void)
{
	Led2_On();Delay1s() ;Led2_Off() ;
	
	rSRCPND |= 1 << 1 ;//清除这一位的话,会自动清除INTOFFSET这一位的;
	rINTPND |= 1 << 1 ;
}

void __irq Eint2_Isr(void)
{
	Led3_On();Delay1s() ;Led3_Off() ;
	
	rSRCPND |= 1 << 2 ;//清除这一位的话,会自动清除INTOFFSET这一位的;
	rINTPND |= 1 << 2 ;
}

void __irq Eint4_7_Isr(void)
{
	
	if(rEINTPEND & (1 << 4) ) //EINTPEND记载着具体是哪个外部中断发生了
	{
		Led4_On();Delay1s() ;Led4_Off() ;
	
		rEINTPEND |= 1 << 4 ;
	}
	rSRCPND   |= 1 << 4 ;
	rINTPND   |= 1 << 4 ;
}

void IO_Init()
{
	Led_Init() ;
	Key_Init() ;
	Isr_Init() ;
	Irq_Init() ;
}

int Main()
{
	IO_Init() ;
	
	while(1);

	return 0;	
}

四. C语言处理中断__irq关键字

前述,中断处理结束后,需要进行模式的恢复以及保存寄存器的恢复,这在上述代码是如何体现的呢?ADS编译器提供__irq的关键字为我们C语言开发中断程序提供了方便,其实__irq关键字的工作有2个:

1)中断发生后,将需要保存的寄存器压栈;

2)中断结束后,恢复之前保存的寄存器,及工作模式的恢复.

如:

void __irq Eint0_Isr(void)
{
	Led1_On();Delay1s() ;Led1_Off() ;
	
	rSRCPND |= 1 << 0 ;//清除这一位的话,会自动清除INTOFFSET这一位的;
	rINTPND |= 1 << 0 ;	
}

利用ADS反汇编查看后得到:

    Eint0_Isr
        0x00000108:    e92d501f    .P-.    STMFD    r13!,{r0-r4,r12,r14}
        0x0000010c:    e24dd004    ..M.    SUB      r13,r13,#4
        0x00000110:    e3a04456    VD..    MOV      r4,#0x56000000
        0x00000114:    e5940014    ....    LDR      r0,[r4,#0x14]
        0x00000118:    e3c00020     ...    BIC      r0,r0,#0x20
        0x0000011c:    e5840014    ....    STR      r0,[r4,#0x14]
        0x00000120:    ebfffffe    ....    BL       Delay1s
        0x00000124:    e5940014    ....    LDR      r0,[r4,#0x14]
        0x00000128:    e3800020     ...    ORR      r0,r0,#0x20
        0x0000012c:    e5840014    ....    STR      r0,[r4,#0x14]
        0x00000130:    e3a0044a    J...    MOV      r0,#0x4a000000
        0x00000134:    e5901000    ....    LDR      r1,[r0,#0]
        0x00000138:    e3811001    ....    ORR      r1,r1,#1
        0x0000013c:    e5801000    ....    STR      r1,[r0,#0]
        0x00000140:    e5901010    ....    LDR      r1,[r0,#0x10]
        0x00000144:    e3811001    ....    ORR      r1,r1,#1
        0x00000148:    e5801010    ....    STR      r1,[r0,#0x10]
        0x0000014c:    e28dd004    ....    ADD      r13,r13,#4
        0x00000150:    e8bd501f    .P..    LDMFD    r13!,{r0-r4,r12,r14}
        0x00000154:    e25ef004    ..^.    SUBS     pc,r14,#4

前两句和后两句就分别是保存和恢复的动作。

后记:

1)S3C2440中断结构部分参考:http://blog.sina.com.cn/s/blog_73a6f76301014c7x.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值