第9章 中断
来源:互联网 发布:长三角师资招聘会 网络 编辑:程序博客网 时间:2024/05/01 09:25
第9章中断
cpsr
(2)对于irq,可能同时有几个中断被触发。 未被INTMSK寄存器屏蔽的中断经过比较后选出优先级最高的中 断(通过仲裁器和priority), 此中断在INTPND寄存器中的相应位被置1, 然后cpu进入中断模式处理。 中断服务程序可以通过读取INTPND寄存器或者intoffs et寄存器来确定中断源 (3)清除中断:如果不清除中断, 则cpu会误以为这个中断又发生一次。 若ISR执行过程中,这个中断可能发生并不能丢弃、 则在调用isr之前清除中断、 这样在ISR执行过程中发生的中断能够被个寄存器再次记录并终止 cpu;如果在ISR执行过程中, 这个中断不会发生或者丢弃则在调用ISR之后清除中断。 清除中断过程:首先,操作具体外设中断信号:其次, 清除SUBSRPND,srcpnd寄存器中的相应位(写1); 最后,清除INTPND寄存器相应位(写1),
#include "s3c24xx.h"
#defineGPF_EINT1 (0x2<<(2*1)) //K1 10=EINT1
#defineGPF_EINT2 (0x2<<(2*4)) //K2 10=EINT4
#defineGPF_EINT3 (0x2<<(2*2)) //K3 10=EINT2
#defineGPF_EINT4 (0x2<<(2*0)) //K4 10=EINT0
#define GPB_OUT5 (1<<(2*5)) //led1
#defineGPB_OUT6 (1<<(2*6)) //led2 01=out
#defineGPB_OUT7 (1<<(2*7))
#defineGPB_OUT8 (1<<(2*8)) //led4 01=out
void disable_watchdog(void)
{
WTCON=0;
}
void init_led(void)
{
GPBCON|=GPB_OUT5|GPB_OUT6|GPB_ OUT7|GPB_OUT8; //5,6,7,8SET ASOUT
}
void init_irq()
{
GPFCON|=GPF_EINT1|GPF_EINT2| GPF_EINT3|GPF_EINT4 ;//SET ASEINT
EINTMASK =0x000ffffd;//EINT4 MUST ==0 TO ENABLE
PRIORITY =0x07f83c;
INTMSK&=(~(1<<0))&(~(1<<1))&(~ (1<<2))&(~(1<<4));
}
#include "s3c24xx.h"
void EINT_Handle()
{
unsigned long ofset=INTOFFSET ;
switch(ofset)
{
case 0 :
{
GPBDAT|=(0xf<<5);//led OFF
GPBDAT&=(~(1<<5));//ONLY GPBdat5=0;LED1 0N
break;
}
case 1:
{
GPBDAT|=(0xf<<5);
GPBDAT&=(~(1<<6)); //write gpbdat6=0.
break;
}
case 2:{
GPBDAT|=(0xf<<5);
GPBDAT&=(~(1<<7));
break;
}
9.1.1 s3c2440中断控制器
中断方式:当某件事情发生时,硬件会设置某个寄存器; cpu在每执行完一个指令时,通过硬件查看这个寄存器, 如果发生所关注的事件发生了,则中断当前程序流程, 跳转到一个固定的地址处理这件事情。
ISR中断服务程序
Request sources(withsub-register)表示INT_RXD0/INT_ TXD0等中断源(s3c2440共15个), 他们不同于requestsources(with-out sub-register)
中断控制器的寄存器
SUBSRCPND和SRCPND寄存器表明有哪些中断被触发, 正在等待处理;SUBMASK(intsubmsk) 和mask(intmsk)用于屏蔽某些中断
中断示意图
1.request sources(withoutsub-registered)中的中断源被触发之后, srcpnd寄存器相应位置1,if INTMSK==0(没有屏蔽)and FIQ(1),将进一步处理
2.request source(with sub-register)中的中断源被触发后, SUBSRCPND寄存器相应位被置1,if INTSUBMSK ==0没有屏蔽,then srcpnd相应位也被置1,接着同上(1)处处理.
(1)如果是,;FIQ——mode(intmod寄存器)中为1的为对应中断是FIQ, 则cpu进入快速中断模式。
上图中priority表示中断的优先级判断, 通过ptiotity寄存器进行设置
由此可知中断流程如下:
1.设置好中断模式和快速中断模式下的栈,when FIQ,cpu进入中断模式,使用快速中断模式下的栈。
2.准备好中断处理函数
(1.) 在异常中断向量表中设置好当进入中断模式或快速中断模式时的跳转 函数,异常向量分别为0x00000018( 中断模式的中断向量)、0x0000001c( FIQ的中断向量)。
(2)终端服务程序ISR
IRQ/FIQ的跳转函数,最终将调用具体中断的服务函数
对于IRQ, 读取INTPND寄存器或INTOFFSET寄存器的值来确定中 断源,然后分别处理
对于FIQ,因为只有一个中断可以设为FIQ,无须判断中断源
3.进入、退出中断模式或快速中断模式时,需要保存、 恢复被中断程序的运行环境。
对于IRQ,进入退出的代码如下:
sub lr,lr,#4 @计算返回地址
stmdb sp!,{r0-r12,lr} @保存使用到的寄存器
.....
ldmia sp!,{r0-r12,pc}^ @中断返回 ;^表示将spsr的值赋给cpsr
对于FIQ,进入退出的代码如下:
sub lr,lr,#4 @计算返回地址
stmdb sp!,{r0-r7,lr} @保存使用到的寄存器
......
ldmia sp!,{r0-r7,pc}^ @快速中断返回^表示将spsr的值赋给cpsr
4.根据具体中断,设置相关外设,如gpio中断, 需要将相应引脚的功能设为“外部中断”设置中断触发条件(高、 低电平触发,上、下降沿触发)
5.对于request sources(withoutsub-registered)的中断, 将INTSUBMSK寄存器设为0.
6.确定此中断的方式:IF FIQ THEN INTMOD=1;IF IRQ THEN RIORITY中设置优先级
7.if IRQ THEN INTMSK=0(FIQ 不受intmsk寄存器影响)
8.设置cpsr寄存器中的i-bit位(irq)或f- bit(fiq)使能irq或fiq
9.1.3 中断寄存器
1.SUBSRCPND寄存器
SUBSRCPND寄存器用来标识INT_RXD0、INT_ TXD0等中断(共15个每bit对应一个),
while(int) if INTSUBMSK没有被屏蔽 srcpnd对应位=1(subsrcpnd若干位汇集 )
if SUBSRCPND对应位==1,clear int;
2.INTSUBMSK
IF INTSUBMSK对应位==1 屏蔽对应中断;
3.SRCPND
SRCPND 中每一位被用来表示一个或一类中断是否发生 IF SRCPND相应位==1 clear 中断;
4.INTMSK
INTMSK 被用来屏蔽SRCPND寄存器所表示的中断,if intmsk相应位==1 对应屏蔽被中断(仅能屏蔽irq 不能屏蔽fiq)
5.INTMOD
if intmod相应位==1 对应的中断设为FIQ
6.PRIORITY寄存器
用于选出最优先级中断,中断优先级的判选通过7个仲裁器来完成: 6个一个仲裁器,1个二级仲裁器,结构如下图
即PRIORITY每3位控制一个仲裁器。 00xxxxxxxx00000000000
7.INTPND
经过中断优先级仲裁器选出有限级最高的中断后, 这个中断在INTPND寄存器的相应位被置1随后cpu将进入中 断模式处理它,同一时间只有一个bit被置1: 在ISR中根据这个位确定哪个是中断,往该位写1清除中断。
8.INTOFFSET寄存器
用来确定INTPND中哪一位被置1, 即INTPND寄存器中位【x】为1时, intoffset寄存器的值为x,在清除SRCPND、 INTPND寄存器时,INTOFFSET寄存器被自动清除。
EINTPND、SUBSRCPND、SRCPND、 INTPND需要写1清除!!!
head.S
@**************
@head.s
@set inital interrupt
@***************
.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:
ldrsp,=4096 @when reset ,the cpu is on cpu mode
bl disable_watchdog @close watchdog
msrcpsr_c,#0xd2 @11010010 irq mode
ldrsp,=3072 @set stack point sp_und
msrcpsr_c,#0xd3 @11010011 superivor mode
ldrsp,=4096 @set stack point sp_svc
blinit_led @init led gpio
blinit_irq @init intterupt in the init.c
msrcpsr_c,#0x53 @open irq
ldrlr,=halt_loop @set return addr
ldrpc,=main @go to main
halt_loop:
b halt_loop
HandleIRQ:
sublr,lr,#4 @return addr
stmdbsp!,{r0-r12,lr} @save reg
ldrlr,=int_return @set return addr after isr
ldrpc,=EINT_Handle @go to isr in the initerrupt.c
int_return:
ldmiasp!,{r0-r12,pc}^ @now pc=lr that means ,return to main means cpsr=spsr;return
@head.s
@set inital interrupt
@***************
.extern main
.text
.global _start
_start:
@*****************************
@ 异常向量,本程序中,除Reset和HandleIRQ外,
@*****************************
@ 0x04: 未定义指令中止模式的向量地址
HandleUndef:
@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
@ 0x14: 保留
HandleNotUsed:
@ 0x18: 中断模式的向量地址
@ 0x1c: 快中断模式的向量地址
HandleFIQ:
reset:
halt_loop:
HandleIRQ:
int_return:
init.c:
#include "s3c24xx.h"
#defineGPF_EINT1
#defineGPF_EINT2
#defineGPF_EINT3
#defineGPF_EINT4
#define GPB_OUT5
#defineGPB_OUT6
#defineGPB_OUT7
#defineGPB_OUT8
void disable_watchdog(void)
{
}
void init_led(void)
{
}
void init_irq()
{
}
interrupt.c
#include "s3c24xx.h"
void EINT_Handle()
{