论坛» 嵌入式开发» MCU

请问IRQ中断

菜鸟
2005-08-15 22:58 1楼

IRQ中断的问题:

在S3C44B0X的开发板中,要使用定时器0的中断,应该怎么设置ARM的寄存器呢?

菜鸟
2005-08-16 00:44 2楼

从第二章的中断部分我们得到中断服务程序的首地址为:
_ISR_STARTADDRESS

所以我们在h头文件44b.h来用这个首地址加每个中断的
偏移量来定义中断服务程序的地址.我们配置Port G为8个外
部中断源输入,所以对Port G的控制寄存器也要定义.中断控
制寄存器为必需品,当然不能少.
所以为了完成中断服务程序,我们必须在头文件里定义下
面几部分内容
服务程序地址
#define pISR_EINT4567 (*(unsigned *)(_ISR_STARTADDRESS+0x74))
I/O 端口
#define rPCONG (*(volatile unsigned *)0x1d20040)
#define rPDATG (*(volatile unsigned *)0x1d20044)
#define rPUPG (*(volatile unsigned *)0x1d20048)
#define rSPUCR (*(volatile unsigned *)0x1d2004c)
#define rEXTINT (*(volatile unsigned *)0x1d20050)
#define rEXTINTPND (*(volatile unsigned *)0x1d20054)
INTERRUPT 控制寄存器
#define rINTCON (*(volatile unsigned *)0x1e00000)
#define rINTPND (*(volatile unsigned *)0x1e00004)
#define rINTMOD (*(volatile unsigned *)0x1e00008)
#define rINTMSK (*(volatile unsigned *)0x1e0000c)
#define rI_ISPR (*(volatile unsigned *)0x1e00020)
#define rI_ISPC (*(volatile unsigned *)0x1e00024)
EINT4567 的Pending 位
#define BIT_EINT4567 (0x1<<21)
#define BIT_GLOBAL (0x1<<26)
变量解释
为了能够更好的理解下面的内容,我们必须要对上面的定
义做一下解释.
对于中断服务程序的地址,不用多讲废话.对I/O 端口
INTERRUPT 控制寄存器有必要解释一下.
#define rPCONG (*(volatile unsigned *)0x1d20040)
阅读S3C44B0X的硬件说明文档我们发现,她有两组8位的
输入/输出端口: Port D 和 PortG ,她还吹牛,这些I/O口可以
很容易地通过软件来配置,从而满足各种设计需求.
上面这个define就定义了PortG端口,我们打算配置她作为
外部中断输入.
#define rPDATG (*(volatile unsigned *)0x1d20044)
如果PortG 被配置成输出口(output ports) 数据写入这
个寄存器;如果PortG 被配置成输入口(input ports) 从这个
寄存器读数据
#define rPUPG (*(volatile unsigned *)0x1d20048)
控制PortG 口的上拉电阻是接通还是断开
#define rSPUCR (*(volatile unsigned *)0x1d2004c)
控制数据总线的上拉电阻是接通还是断开
#define rEXTINT (*(volatile unsigned *)0x1d20050)
这个用来配置中断是通过信号的上升沿触发,还是下降沿
触发,是高电平触发, 还是底电平触发.
#define rEXTINTPND (*(volatile unsigned *)0x1d20054)
EINT4, EINT5, EINT6, 和 EINT7这四个中断输入共享同
一条中断请求线和中断控制器相连,那如何区分他们啊?
不急,EXTINTPND寄存器就可以解决这个问题.
If EINT4 产生时, EXTINTPND[0] =1 (0001)
If EINT5 产生时, EXTINTPND[1] =1 (0010)
If EINT6 产生时, EXTINTPND[2] =1 (0100)
If EINT7 产生时, EXTINTPND[3] =1 (1000)
#define rINTCON (*(volatile unsigned *)0x1e00000)
中断控制寄存器,用来配置下面两个重要属性:
使用向量还是非向量中断模式,
使用普通中断(IRQ)还是快速中断(FRQ)
#define rINTPND (*(volatile unsigned
*)0x1e00004)
这个寄存器的每一位对应一个中断源.例如当一个中断
请求产生时,相应的位会置为1. 比如,当EINT4 产生时,
INTPND[21]的值变为1
Interrupt Pending Register is a read-only
register, so the service routine must clear the pending

condition by writing a 1 to I_ISPC or F_ISPC
#define rINTMOD (*(volatile unsigned *)0x1e00008)
为每个中断源设置中断模式,比如
IF INTMOD[21]=1 EINT4 为 FIQ mode
IF INTMOD[21]=0 EINT4 为 IRQ mode
#define rINTMSK (*(volatile unsigned *)0x1e0000c)
中断屏蔽寄存器,比他屏蔽后,中断就不能触发了.比如:
If INTMSK[21]=1, EINT4被屏蔽
#define rI_PSLV (*(volatile unsigned *)0x1e00010)
#define rI_PMST (*(volatile unsigned *)0x1e00014)
#define rI_CSLV (*(volatile unsigned *)0x1e00018)
#define rI_CMST (*(volatile unsigned *)0x1e0001c)
上面四个为优先级配置寄存器
#define rI_ISPR (*(volatile unsigned *)0x1e00020)
#define rI_ISPC (*(volatile unsigned *)0x1e00024)
I_ISPR 确定当前正在服务的中断
I_ISPC/F_ISPC 用来对INTPND/I_ISPR中的pending位清
零,
I_ISPC/F_ISPC 也通知中断控制器一个中断服务程序运行
完成.在中断服务程序的最后必须把pending位清零.
手册上的英语描述的更清晰:
I_ISPR indicates the interrupt being currently serviced.

Although the several interrupt pending bits are all turned
on,only one bit will be turned on.
I_ISPC/F_ISPC clears the interrupt pending bit (INTPND).
I_ISPC/F_ISPC also informs the interrupt controller of the end
of corresponding ISR (interrupt service routine). At the end of
ISR(interrupt service routine), the corresponding pending bit
must be cleared.
Interrupt Pending Register is a read-only register, so the
service routine must clear the pending condition by writing
a 1 to I_ISPC or F_ISPC
上面的解释说明是针对S3C44B0X的寄存器,对于其他的芯
片一定会有区别,但他们都有共同的,相似的地方.
中断服务程序的实现
为了简单期间我们把中断服务程序放在在main.c 文件
里实现.
定义中断服务程序
void __irq Eint4567Isr(void);
volatile char which_int=0;//标识发生了那个中断,4,5,6 or 7?
void __irq Eint4567Isr(void)
{
which_int=rEXTINTPND;
/*
If EINT4 产生时, EXTINTPND[0] =1 (0001)1
If EINT5 产生时, EXTINTPND[1] =1 (0010)2
If EINT6 产生时, EXTINTPND[2] =1 (0100)4
If EINT7 产生时, EXTINTPND[3] =1 (1000)8
所以上面语句执行的结果是:
If EINT4 产生时 which_int=1
If EINT4 产生时 which_int=2
If EINT4 产生时 which_int=4
If EINT4 产生时 which_int=8
*/
rEXTINTPND=0xf;
/* clear EXTINTPND reg
The interrupt service routine must clear the interrupt
pending condition(INTPND) after clearing the
external pending condition(EXTINTPND).
*/
rI_ISPC=BIT_EINT4567;
/* clear pending_bit */
}
主程序
int Main()
{
unsigned int save_G,save_PG;
rINTMOD=0x0;
rINTCON=0x1;
/*中断初始化
rINTMOD=0x0 设置为 IRQ mode
rINTCON=0x1 设置为向量中断模式
*/
pISR_EINT4567=(int)Eint4567Isr;
/*
中断服务程序入口地址定位
;pISR_EINT4567
;0xc7fff74: Eint4567Isr


把Eint4567Isr 代码存放在地址为0xc7fff74 开始的内存空间里
*/
save_G=rPCONG;
save_PG=rPUPG;
/*保存原来I/O 端口的配置 */
rPCONG=0xffff; //EINT7~0
rPUPG=0x0; //pull up enable
/*
rPCONG=0xffff 把PortG 配置为8 个中断输入
rPUPG=0x0 中断为上升沿触发
*/
rINTMSK=~(BIT_GLOBAL|BIT_EINT4567); ;
/*开放屏蔽位*/
while(!which_int);
switch(which_int)
{
case 1:
Uart_Printf("EINT4 had been occured...\n");
break;
case 2:
Uart_Printf("EINT5 had been occured...\n");
break;
case 4:
Uart_Printf("EINT6 had been occured...\n");
break;
case 8:
Uart_Printf("EINT7 had been occured...\n");
break;
default :
break;
}
rINTMSK=BIT_GLOBAL;
/* 屏蔽所有中断*/
rPCONG=save_G;
rPUPG=save_PG;
which_int=0;
Uart_Printf("\nrINTCON=0x%x\n",rINTCON);
}

更多的解释请参看:

http://micro9229.blogchina.com/2599285.html

共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]