目 录
这是interrupt结构框架图。为了介绍该结构框架图,本文从CPU控制流程的角度,解释该结构框架图。
首先,中断的有两个来源,内部设备(如IIC、UART等)和外部管脚。当中断源由内部设备产生时,
①. SUBSRCPND被置位(寄存器的具体操作,见后文“2.寄存器操作” ) ,
②. 如果SUBMSK未被置位的话,则SRCPND被置位,
③. 然后判断MODE的模式如果是IRQ,并且此时MASK未被置位的话(MODE和MASK的工作时序,我还不明确,datasheet中没有提及)。
④. 再进行Priority判断。
⑤. 然后,置位相应的INTPND位,CPU收到命令后,执行相应的中断服务函数。
在第③步,当MODE为FIQ时,直接产生中断,但该模式只可用于紧急情况。
当中断源由外部引脚产生时,直接置位SRCPND,然后执行②~⑤。
当有内部中断产生时,SUBSRCPND相应的位将会被置位为1,即中断源已经产生了中断请求。
比如当WDT产生中断时,SUBSRCPND的第13位(即INT_WDT位)会被置1。可以通过写1清零相应的位(这个清零是必须在中断服务函数里面写的)。
初始化状态:0x00000000。
当其相应的位被置1时,中断被屏蔽。
初始化状态:0xFFFF。(使用时,需要将相应位置0)
该寄存器的功能和SUBSRCPND唯一的不同是他可以接收外部的中断请求。
结合下面的这章图,我们可以很清楚的知道,当中断发生时,其相应的为被置位为1。可以通过写1清零相应的位(这个清零是必须在中断服务函数里面写的)。
初始化状态:0x00000000。
有两种工作模式:IRQ(0)和FIQ(1)。
初始化状态:0x00000000。(默认)
当其相应的位被置1时,中断被屏蔽。
初始化状态:0xFFFFFFFF。(使用时,需要将相应位置0)
优先级设置,本处设置成可循化的方式,即当某循环被执行时,其优先级最低(LOWEST)。
初始化状态:0x7F。(默认)
当某中断有最高的优先级时,该寄存器上相应的位置1(有且只有一个被置位,这是我们判断哪一个中断的到响应唯一的依据),然后CPU相应相应的中断请求。我们可以通过READ该寄存器,知道哪一个中断服务函数被执行。
在中断服务函数中,我们必须先将SRCPNT清零,然后将INTPND清零。不然,CPU会继续产生中断。
初始化状态:0x00000000。(注意清零)
当INTPND上的某一位被置1时,INTOFFSET会具有相应的value。当我们清零SRCPNT和INTPND时,该寄存器将被自动清零。(不必对其进行任何操作)。
2.9.1 EXTINT(0-2) 用于设置中断类型(Low_level, High_level,…)。
2.9.2 EINTMASK 用于设置4-23的屏蔽与否,因为之间的INTMSK只能集中设置EINT4-7或EINT8-23.
当需要设置EINT4-23时,设置方法:先打开INTMSK,然后再在EINTMSK进行详细的设定。比如我们需要去掉EINT4的屏蔽,先设定INTMSK= ~(0x1<<4),然后EINTMSK= ~(0x1<<4)。
2.9.3 EINTPEND 表明是否occur interrupt,如果是则1,不是这置0。当然和INTPND一样,我们需要在中断函数中将其(写1)清零,不然CPU会持续产生中断。
【题外话:关于INTPEND和EINTPEND的清零顺序,我做了一个实验。
实验原理:在利用EINT4(即KEY2)产生正常产生中断的前提下,写该了一下清零INTPEND和EINTPEND的顺序。同时在中断服务函数中加了蜂鸣器语句:Beep(4000,100);这样每进一次中断,蜂鸣器就会响一次,如果多次进入就会响多次。
具体如下:
清零 |
仅INTPEND |
仅EINTPEND |
先I,后EI |
先EI,后I |
现象 |
间断而持续响 |
响2次或3次 |
1次 |
这个实验结果,让我有些迷惑,我一直在想S3C2440的内部中断系统是一个什么样的结构,为何会产生这样的结果。网上有人这样写到“在中断触发跳入中断处理函数后,首先要清除SRCPND和INTPND相应的位,如果用到次级中断源,如这里用到了EINT4_7中的EINT4,就要清除EINTPEND相应的位。一般来说,应该先清除次级中断源相应的位,再清除中断源,否则中断源会发生多次中断。在完成清除后再进行具体的处理。” 但我依然不知道为什么。如果各位有知道的话,请告诉我,我会很感激不尽的。】
寄存器:INTMSK
寄存器:EINTMASK
【现在前面的话】:
在S3C的技术手册中,并没有提到如何具体的编写相关的中断函数,而对于具体的ARM是如何是实现中断的,我还没有深入的研究,现在只是知道如何用C编写相关的函数。本来想好好的研究一番,但不符合学习计划主路线的要求,只能先放一放。
以下代码的硬件平台为TQ2440,只写了两个较重要的函数,我相信只要你能充分理解S3C2440的datasheet就可以写出完整的中断程序,我在写程序时也之参考了S3C2440的datasheet和TQ的电路原理图,虽然工作量比较大,但也收获很多,有知识上的,也有思想上的。
该函数包括两个部分:
a) 设置相应的管脚为中断管脚
b) 中断向量声明
c) 初始化寄存器
//*****************************************************************************
//
//! \Function:
//! Init interrupt: All in IRQ mode, all interrupt service is available, and Priority rotate.
//!
//! \You can choose IRQ or FIQ by set the corresponding bit to be 0 or 1 in the "rINTMOD".
//!
//! \You can mask the interrupt source by set the corresponding bit to be 1 in the "rINTMSK".
//!
//! \Priority rotate means the lasted required interrupt has the lowest priority.
//
//*****************************************************************************
void EINT_INIT(U8 nEINT, U8 Int_type)
{
EINTPin_Init(nEINT);//set pin
//set register
pISR_EINT4_7=(unsigned)EINT_ISR;
rINTMOD = 0x00000000; //all in IRQ mode
//MASK(1)
if(nEINT < 4)
rINTMSK = ~(0x1<< nEINT); //only EINT1 service is available
else if (nEINT < 8)
{
rINTMSK = ~(0x1<< 4);
rEINTMASK = ~(0x1<<nEINT);//only open EINT4
}
else
{
rINTMSK = ~(0x1<< 5);
rEINTMASK = ~(0x1<<nEINT);
}
rPRIORITY = 0x7f; //Priority rotate
//Int type
if(nEINT < 8)
rEXTINT0 =(~( 0x7<< (nEINT*4)) & rEXTINT0)| (Int_type<<(nEINT*4)); //set Int type
else if(nEINT <16)
;//we use them so little time.??2011.5.29??
else
;
}
该函数包括三个部分:
//*****************************************************************************
//
//! \Function:
//! Interrupt service of EINT.
//!
//! \Operation flow:
//! 0.ClearEINTPEND only for EINT4-EINT23
//! 1.Get the INT_SRC
//! 2.Clear the source
//! 3.service()
//!
//
//*****************************************************************************
void __irq EINT_ISR(void)
{
U32 Source;
ClearEINTPEND(); //for EINT 4-23
Source = GPIOPinIntSRC(); //get the INT_SRC.
GPIOPinIntClear(Source); //clear the source.
//////service()
LED_OFF(LED1);
Beep(4000,100);
}
》》》咱们综合分析一下上面的两个函数:
首先,中断服务函数名Key_ISR 需要在初始化中用向量指定pISR_EINT1=(unsigned)Key_ISR;,这样EINT1发出中断请求时,CPU才能进入该服务函数。
其次,要在中断函数名前加__irq.
本文及其他我写的文章,皆是鄙人学习总结笔记。文中内容我会尽最大的努力保证正确,如你发现bug,请一定要通知我,我会按您的指导进行Debug。
我相信交流是提高技术最好的方法。
文章评论(0条评论)
登录后参与讨论