您的位置:首页 > 其它

中断体系结构的实验~TQ2440

2010-01-26 09:55 225 查看
当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执

行。当异常中断处理程序执行完成后,程序返回到发生中断指令的下条指令处执行。在进入异

常中断处理程序时,要保存被中断程序的执行现场,从异常中断处理程序退出时,要恢复被中

断程序的执行现场。
中断的使能在cpsr的I F位,分别允许普通中断和快速中断。
SRCPND :当一个中断发生后,那么相应的位会被置1,表示一个或一类中断发生了,可以

同时发生多个中断,就会多个位置1.
INTMSK :中断屏蔽寄存器。FIQ不受其影响
INTPND :中断发生后,SRCPND中会有位置1,可能好几个(因为同时可能发生几个中

断),这些中断会由优先级仲裁器选出一个最紧迫的,然后吧把INTPND中相应位置1,所以同一

时间只有一位是1。也就是说前面的寄存器置1是表示发生了,只有INTPND置1,CPU才会处理。
INTOFFSET :用来表示INTPND中哪一位置1了,好让你查询,普通中断跳转时查询用

。清除INTPND、SRCPND时自动清除。
中断处理之后需要我们写1清除中断,(如果你也许在处理这个中断的时候可以继续

发生此中断,也可以在处理之前清除中断),否则,会被认为没有被处理,会不停的处理这个

中断。清除中断是按照eintpnd srcpnd intpnd的顺序。
子中断掩码subintmsk
中断产生的时候:
1.中断模式下的LR寄存器保存上一个模式的的下一条指令地址(lr=pc+4),
2.将CPSR值复制到异常模式的SPSR,以保存现场
3.将CPSR设置为异常模式的数值
4.令PC的数值等于异常模式在异常向量表中的地址,即跳转执行异常向量表中的指令
中断处理完成之后:
1.将保存在异常模式中的LR的数值减去适当的数值,赋给PC寄存器
2.将SPSR复制给CPSR
pc和cpsr是通用的,关于寄存器,有一个图标明显的指出哪些寄存器通用,哪些寄存

器有副本,可惜csdn目前不支持图片,以后补上吧
开启中断之前我们要做的工作:
1,设置好各种模式下的堆栈,因为每种模式都有自己的堆栈
2,写好中断处理函数
3,设置好中断向量表,与中断函数关联起来
4,开启中断使能位cpsr的I F
5,中断产生之后会自动根据中断向量表跳转到对应的处理函数,此时srcpnd的相应位会被置1

,然后检查intmsk对应的中断是否屏蔽,然后会通过优先级仲裁器选出优先级最高的一个中断

,自动让intpnd的相应位置一,intpnd有且只有一位会被置一。我们会读取intoffset的值,判

断出中断源,开始处理中断函数,处理之后清除中断,也可以在中断处理之前清除,视情况而

定。
代码下班了补上,代码会给出更详细解释。

@led start
@2010-01-12
@jay
.text
.globl _start
_start:
b reset
//@预留着以后扩展中断向量表
int_irq0:
b intirq
int_irq1:
b intirq
int_irq2:
b intirq
int_irq3:
b intirq
int_irq4:
b intirq
int_irq5:
b intirq
int_irq6:
b intirq

reset:
@disable watchdog
ldr r0,=0x53000000
mov r1,#0
str r1,[r0]

msr cpsr_c,#0xd2       @in usr mode       分别设置好各模式的堆栈
ldr sp,=3072			   @setup stack

msr cpsr_c,#0xdf		@in sys mode
ldr sp,=4096				@setup stack
@ 其实reset就处于系统模式,
bl irq_init

msr cpsr_c,#0x5f        @enable irq

ldr lr,=ledloop
ldr pc,=irq_test
ledloop:
b .

intirq:

sub lr,lr,#4     @ 计算返回地址,因为返回时pc会加4
stmdb sp!,{r0-r12,lr}  @ 保存会使用的寄存器到spsr
@ 注意,此时的sp是中断模式的sp
ldr lr,=irq_return       @设置好返回指针

ldr pc,=eint_key         @关联中断函数

irq_return:
ldmia sp!,{r0-r12,pc}^   @ ^    恢复现场


#include"led.h"
#include"tq2440.h"

//中断体系
//初始化gpio为外部中断
void irq_init()
{
GPFCON =(2<<0)|(2<<2)|(2<<4)|(2<<6);  //gpio设为中断模式

//开启屏蔽的中断0~4 为0       eintmask是屏蔽4  23的
INTMSK &=~(0xf);
/*
设定优先级 priority
arbmod0=0;arbsel0=0;
优先级反转,使能的话就会转动的哦
*/
PRIORITY&=(~(1<<0))|(~(1<<7));
}

void eint_key()
{
GPBCON =GPB05OUT | GPB06OUT | GPB07OUT | GPB08OUT ;  //gpio 配置输出out
//0xEFF, 0xF7F, 0xFBF, 0xFDF
unsigned long key;
key=INTOFFSET;
switch(key){
case 0:
GPBDAT=~(1<<5);  //k1
break;
case 1:
GPBDAT=~(1<<6);  //k2
break;
case 2:
GPBDAT=~(1<<7);  //k3
break;
case 4:
GPBDAT=~(1<<8);  //k4
break;
default:
GPBDAT=0;
break;
}

//清除中断,相应位写1   清除中断

SRCPND |=(1<<INTOFFSET);
INTPND=INTPND;

}
/*eint8-23表示外部中断eint8---eint23
INTOFFSET判断中断源,显示哪个中断在INTPND中待决,(0-3可以直接判断出,4--23需要我们再次判断EINTPEND)  返回值为0-31
4-7合用IRQ5,8-23合用IRQ6

INTPEND 表示待决的中断 有且只有一个位置1   有待决的就是1,可以显示0-3和其他中断INT-ADC之类的 .该寄存器值一般是不用设置的.
EINTPEND只显示4-23的中断待决 表示外部待决中断

SRCPND

*/
void irq_test()
{
while(1);
}


led和makefle boot.lst 和以前一样 , 所以就不传上来了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: