一、S3C2440间断体系结构
1)ARM体系CPU的7种作业形式
用户形式(usr):ARM处理器正常的程序履行状况
快速间断形式(fiq):用于高速数据传输或通道处理
间断形式(irq):用于通用的间断处理
管理形式(svc):操作体系运用的维护形式
数据拜访停止形式(abt):当数据或指令预取停止时进入该形式,可用于虚拟存储及存储维护
体系形式(sys):运转具有特权的操作体系使命
未定义指令间断形式(und):当未定义的指令履行时进入该形式,可用于支撑硬件协处理器的软件仿真
除用户形式外,其他6种作业形式都归于特权形式,大多数程序运转于用户形式,进入特权形式是为了处理间断、反常,或许拜访被维护的体系资源。
ARM体系的CPU有以下两个作业状况
ARM状况:此刻处理器履行32位的字对齐的ARM指令
Thumb状况:此刻处理器履行16位的、半字对齐的Thumb指令
ARM920T有31个通用的32位寄存器和6个程序状况寄存器。这37个寄存器分为7组,如下图所示:
图中R0-R15能够直接拜访,这些寄存器除了R15外都是通用寄存器,既能够保存地址也能够保存数据。
R13称为栈指针寄存器,一般用于保存栈指针
R14称为程序衔接寄存器(LR),当履行BL子程序调用指令时,R14得到R15(程序计数器PC)的备份。
而当产生间断或反常时,对应的R14_svc,R14_irq,R14_abt或R14_und中保存R15的回来值
R15是程序计数器
快 速间断形式有7个备份寄存器R8_fiq-R14_fiq,这使得进入快速间断形式履行很大部分程序时(不改动R0-R7),不需求保存任何寄存器。用户 形式、管理形式、数据拜访停止形式和未定义指令间断形式都含有两个独占的寄存器副本R13、R14,这样令每个形式具有自己的栈指针寄存器和衔接寄存器。
每种作业形式还有寄存器CPSR(当时程序状况寄存器),它被用于标识各种状况和当时处于哪种作业形式,如下图所示:
当一个反常产生时,将切换进入相应的作业形式,这是ARM920T CPU将主动完结如下作业:
①在反常作业形式的衔接寄存器R14中保存前一个作业形式的下一条行将履行的指令地址。关于ARM状况,这个值是当时PC值加4或加8
②将CPSR的值仿制到反常形式的SPSR
③将CPSR的作业形式位设为这个反常对应的作业形式
④令PC值等于这个反常形式在反常向量表中的地址,即跳转去履行反常向量表中的相应指令
从反常作业形式回到之前的作业形式时,需求经过软件完结如下作业:
①前面进入反常作业形式时,衔接寄存器中保存了前一作业形式的一个指令地址,将它减去恰当的值后赋值给PC寄存器
②将SPSR的仿制回CPSR
反常形式 | 退出反常形式时PC的核算方法 | 进入反常形式时R14中保存的值 |
管理形式(SWI指令进入) | MOVS PC, R14 | PC+4(1) |
未定义指令停止形式 | MOVS PC, R14 | PC+4(1) |
快速间断形式 | SUBS PC, R14, #4 | PC+4(2) |
间断形式 | SUBS PC, R14, #4 | PC+4(2) |
数据拜访停止形式 |
反常原因:指令预取停止 SUBS PC, R14, #4 |
PC+4(1) |
反常原因:数据拜访停止 SUBS PC, R14, #8 |
PC+8(3) |
注:
(1)PC为这些指令的地址:SWI、未定义的指令、在预取指时就失利的指令
(2)PC为这些指令的地址:进入快速间断形式、间断形式前,被打断而未履行的指令
(3)PC为这些指令的地址:导致数据拜访停止的加载/存储指令(LDR、STR、LDM和STM)
二、S3C2440间断操控器
当某事情产生时,硬件会设置某个寄存器,CPU在履行完一个指令时,经过硬件检查这个寄存器,假如发现所重视的事情产生了,则间断当时程序流程,跳转到一个固定的地址处理这个事情,终究回来持续履行被间断的程序。
间断处理的进程:
①间断操控器聚集各类外设宣布的间断信号,告知CPU
②CPU保存当时程序的运转环境,调用间断服务程序(ISR)来处理这些间断
③在ISR中经过读取间断操控器、外设的相关寄存器来辨认时哪个间断,并进行相应处理
④铲除间断:经过读写间断操控器和外设的相关寄存器来完结
⑤终究康复被间断程序的运转环境(康复寄存器),持续履行
s3c2440的间断操控器结构如上图所示:
①request sources(without sub-register)中的间断源被触发后,SRCPND寄存器中相应位被置1,假如此间断没有被INTMSK寄存器屏蔽或许快速间断的话,它将被进一步处理。
② 关于request sources(with sub-register)中的间断源被触发后,SUBSRCPEND寄存器中的相应位被置1,假如此间断没有被INTSUBMSK寄存器屏蔽的话,它在 SRCPND寄存器中的相应位也被置1,今后的处理进程就和①过程相似。
③假如被触发的间断中有快速间断,INTMOD寄存器中为1的位对应的间断是FIQ,则CPU进入快速间断形式进行处理
④ 关于一般的间断IRQ,或许一起有几个间断被触发,未被INTMSK寄存器屏蔽的间断经过比较后,选出优先级最高的间断,此间断在INTPND寄存器中的 相应位被置1,然后CPU进入间断形式进行处理。间断服务程序经过读取INTPND或许INTOFFSET来确认间断源
三、间断操控寄存器
1)SUBSRCPND寄存器
它用来表明INT_RXD0、INT_TXD0等间断是否产生,每位对应一个间断,当这些间断产生而且没有被INTSUBMSK寄存器屏蔽,则它们中的若干位将聚集出现在SRCPND寄存器的某一位上。要铲除间断,往此寄存器中某位写1
2)INTSUBMSK寄存器
它用来屏蔽SUBSRCPND寄存器所标识的间断,INTSUBMSK寄存器中某位设置1时,对应的间断被屏蔽
3)SRCPND寄存器
它每一位被用来表明一个或一类间断是否产生,要铲除某一位,往此位写1,具体参阅数据手册
4)INTMSK寄存器
用来屏蔽SRCPND寄存器所标识的间断。INTMSK寄存器中某位被设为1时,对应的间断被屏蔽,它只能屏蔽IRQ间断,不能屏蔽FIQ
5)INTMOD寄存器
它某位被设为1时,对应的间断被设为FIQ,同一时间,INTMOD只能有一位被设为1
6)PRIORITY寄存器
当有多个IRQ一起产生时,间断操控器选出最高优先级的间断,首要处理它。间断优先级经过7个裁定器来完结,结构图如下所示:
每个裁定器依据一个位裁定器形式操控(ARB_MODE)和挑选操控信号(ARB_SEL)的两位来处理 6个间断请求。
假如ARB_SEL位是 00b,优先级是REQ0,REQ1,REQ2,REQ3,REQ4,和REQ5.
假如ARB_SEL位是 01b,优先级是REQ0,REQ2,REQ3,REQ4,REQ1,和REQ5.
假如ARB_SEL位是 10b,优先级是REQ0,REQ3,REQ4,REQ1,REQ2,和REQ5.
假如ARB_SEL位是 11b,优先级是REQ0,REQ4,REQ1,REQ2,REQ3,和REQ5.
注 意裁定器的 REQ0 总是有最高优先级,REQ5 总是有最低优先级。此外经过改动ARB_SEL 位,咱们能够翻转 REQ1 到 REQ4 的优先级。假如ARB_MODE方位0,ARB_SEL位不会主动改动,使得裁定器在一个固定优先级的形式下操作(留意在此形式下,咱们经过手艺改动 ARB_SEL 位来装备优先级)。别的,假如 ARB_MODE 位是 1,ARB_SEL 位以翻转的方法改动。例如假如 REQ1 被服务,则ARB_SEL位主动的变为01b,把REQ1放到最低的优先级。ARB_SEL改变的具体规矩如下:
假如REQ0 或REQ5 被服务,ARB_SEL位彻底不会改变。
假如REQ1 被服务,ARB_SEL位变为 01b。
假如REQ2 被服务,ARB_SEL位变为 10b。
假如REQ3 被服务,ARB_SEL位变为 11b。
假如REQ4 被服务,ARB_SEL位变为 00b。
7)INTPND寄存器
经过间断优先级选出优先级最高的间断后,这个间断在INTPND寄存器中的相应位被置1,随后CPU进入间断形式处理它
同一时间,此寄存器只要一位被置1,在ISR中,能够依据这个位确认是哪个间断,铲除间断时,往此位写入1
8)INTOFFSET寄存器
用来表明INTPND寄存器中哪位被置1了,即INTPND寄存器中位[x]为1时,INTOFFSET寄存器的值为x(x为0-31)
铲除SRCPND、INTPND寄存器时,INTOFFSET寄存器被主动铲除
四、间断操控器操作实例:外部间断
开发板上,K1-K4四个按键所接的CPU引脚能够设为外部间断,本程序的功用是,当按下某个按键时,CPU调用间断服务程序点亮对应的LED
@******************************************************************************
@ File:head.S
@ 功用:初始化,设置间断形式、体系形式的栈,设置好间断处理函数
@******************************************************************************
.extern main
.text
.global _start
_start:
@******************************************************************************
@ 间断向量,本程序中,除Reset和HandleIRQ外,其它反常都没有运用
@******************************************************************************
b Reset
@ 0x04: 未定义指令间断形式的向量地址
HandleUndef:
b HandleUndef
@ 0x08: 管理形式的向量地址,经过SWI指令进入此形式
HandleSWI:
b HandleSWI
@ 0x0c: 指令预取停止导致的反常的向量地址
HandlePrefetchAbort:
b HandlePrefetchAbort
@ 0x10: 数据拜访停止导致的反常的向量地址
HandleDataAbort:
b HandleDataAbort
@ 0x14: 保存
HandleNotUsed:
b HandleNotUsed
@ 0x18: 间断形式的向量地址
b HandleIRQ
@ 0x1c: 快间断形式的向量地址
HandleFIQ:
b HandleFIQ
Reset:
ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需求设好栈
bl disable_watch_dog @ 封闭WATCHDOG,不然CPU会不断重启
msr cpsr_c, #0xd2 @ 进入间断形式,cpsr_c表明cpsr[7:0],0xd2=0b1101 0010
ldr sp, =3072 @ 设置间断形式栈指针
msr cpsr_c, #0xdf @ 进入体系形式
ldr sp, =4096 @ 设置体系形式栈指针,
@ 其实复位之后,CPU就处于体系形式,
@ 前面的“ldr sp, =4096”完结相同的功用,此句可省掉
bl init_led @ 初始化LED的GPIO管脚
bl init_irq @ 调用间断初始化函数,在init.c中
msr cpsr_c, #0x5f @ 设置I-bit=0,开IRQ间断
ldr lr, =halt_loop @ 设置回来地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4 @ 核算回来地址
stmdb sp!, { r0-r12,lr } @ 保存运用到的寄存器
@ 留意,此刻的sp是间断形式的sp
@ 初始值是上面设置的3072
ldr lr, =int_return @ 设置调用ISR即EINT_Handle函数后的回来地址
ldr pc, =EINT_Handle @ 调用间断服务函数,在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 间断回来, ^表明将spsr的值仿制到cpsr
/*
* init.c: 进行一些初始化
*/
#include “s3c24xx.h”
/*
* LED1-4对应GPB5、GPB6、GPB7、GPB8
*/
#define GPB5_out (1<<(5*2)) // LED1
#define GPB6_out (1<<(6*2)) // LED2
#define GPB7_out (1<<(7*2)) // LED3
#define GPB8_out (1<<(8*2)) // LED4
/*
* K1-K4对应GPG0,GPG3,GPG5,GPG6
*/
#define GPG0_eint (2<<(0*2)) // K1,EINT8
#define GPG3_eint (2<<(3*2)) // K2,EINT11
#define GPF5_eint (2<<(5*2)) // K3,EINT13
#define GPF6_eint (2<<(6*2)) // K4,EINT14
/*
* 封闭WATCHDOG,不然CPU会不断重启
*/
void disable_watch_dog(void)
{
WTCON = 0;// 封闭WATCHDOG很简单,往这个寄存器写0即可
}
void init_led(void)
{
GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;
}
/*
* 初始化GPIO引脚为外部间断
* GPIO引脚用作外部间断时,默以为低电平触发、IRQ方法(不必设置INTMOD)
*/
void init_irq( )
{
GPGCON = GPG0_eint | GPG3_eint |GPG5_eint |GPG6_eint;
// 关于EINT8、11、13、14,需求在EINTMASK寄存器中使能它们
EINTMASK &= (~(1<<8)) & (~(1<<11)) & (~(1<<13)) & (~(1<<14));
/*
* 设定优先级:
* ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2
* 裁定器1、6无需设置
* 终究:
* EINT0 > EINT2 > EINT11,EINT19,即K4 > K3 > K1,K2
* EINT11和EINT19的优先级相同
*/
PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;
//敞开EINT8_23
INTMSK &= ~(1<<5);
}
interrupt.c
#include “s3c24xx.h”
void EINT_Handle()
{
unsigned long oft = INTOFFSET;
switch( oft )
{
//INTOFFSET为5时,代表INTPND的位[5]为1,则EINT8-23间断产生
case 5:
{
GPBDAT |= (0x0f<<5); //LED全灭
if (EINTPEND & (1<<8)) //EINT8产生(EINT8对应K1)
GPBDAT &= ~(1<<5);
if (EINTPEND & (1<<11)) //EINT11产生(EINT8对应K2)
GPBDAT &= ~(1<<6);
if (EINTPEND & (1<<13)) //EINT13产生(EINT8对应K3)
GPBDAT &= ~(1<<7);
if (EINTPEND & (1<<14)) //EINT14产生(EINT8对应K4)
GPBDAT &= ~(1<<8);
break;
}
default:
break;
}
//铲除间断
if(oft == 5)
EINTPEND = (1<<8) | (1<<11) | (1<<13) | (1<<14);
SRCPND = 1< INTPND = 1< } main.c int main() { while(1); return 0; }