原创 S3C2440-INTERRUPT

2011-6-4 00:50 3350 6 6 分类: MCU/ 嵌入式


1         总体框架

20110604004436001.jpg

      

   这是interrupt结构框架图。为了介绍该结构框架图,本文从CPU控制流程的角度,解释该结构框架图。

首先,中断的有两个来源,内部设备(如IICUART等)和外部管脚。当中断源由内部设备产生时,

①.  SUBSRCPND被置位(寄存器的具体操作,见后文“2.寄存器操作”

②.  如果SUBMSK未被置位的话,则SRCPND被置位,

③.  然后判断MODE的模式如果是IRQ,并且此时MASK未被置位的话(MODEMASK的工作时序,我还不明确,datasheet中没有提及)。

④.  再进行Priority判断。

⑤.  然后,置位相应的INTPND位,CPU收到命令后,执行相应的中断服务函数。

在第③步,当MODEFIQ时,直接产生中断,但该模式只可用于紧急情况。

当中断源由外部引脚产生时,直接置位SRCPND,然后执行②~⑤。

2         寄存器介绍

2.1       SUBSRCPND

当有内部中断产生时,SUBSRCPND相应的位将会被置位为1,即中断源已经产生了中断请求。

比如当WDT产生中断时,SUBSRCPND的第13位(即INT_WDT位)会被置1。可以通过写1清零相应的位(这个清零是必须在中断服务函数里面写的)。

初始化状态:0x00000000

2.2       INTSUBMSK

当其相应的位被置1时,中断被屏蔽。

初始化状态:0xFFFF。(使用时,需要将相应位置0

2.3       SRCPND

该寄存器的功能和SUBSRCPND唯一的不同是他可以接收外部的中断请求。

结合下面的这章图,我们可以很清楚的知道,当中断发生时,其相应的为被置位为1。可以通过写1清零相应的位(这个清零是必须在中断服务函数里面写的)。

初始化状态:0x00000000

20110604004437002.jpg

2.4       INTMOD

有两种工作模式:IRQ0)和FIQ1)。

初始化状态:0x00000000。(默认)

2.5       INTMSK

当其相应的位被置1时,中断被屏蔽。

初始化状态:0xFFFFFFFF。(使用时,需要将相应位置0

2.6       PRIORITY

优先级设置,本处设置成可循化的方式,即当某循环被执行时,其优先级最低(LOWEST)。

初始化状态:0x7F。(默认)

2.7       INTPND

当某中断有最高的优先级时,该寄存器上相应的位置1(有且只有一个被置位,这是我们判断哪一个中断的到响应唯一的依据),然后CPU相应相应的中断请求。我们可以通过READ该寄存器,知道哪一个中断服务函数被执行。

在中断服务函数中,我们必须先将SRCPNT清零,然后将INTPND清零。不然,CPU会继续产生中断。

初始化状态:0x00000000。(注意清零)

2.8       INTOFFSET

INTPND上的某一位被置1时,INTOFFSET会具有相应的value。当我们清零SRCPNTINTPND时,该寄存器将被自动清零。(不必对其进行任何操作)。

2.9       关于IO口中几个寄存器

2.9.1    EXTINT0-2 用于设置中断类型(Low_level, High_level,…)。

2.9.2    EINTMASK 用于设置4-23的屏蔽与否,因为之间的INTMSK只能集中设置EINT4-7EINT8-23.

当需要设置EINT4-23时,设置方法:先打开INTMSK,然后再在EINTMSK进行详细的设定。比如我们需要去掉EINT4的屏蔽,先设定INTMSK= ~(0x1<<4),然后EINTMSK= ~(0x1<<4)

2.9.3    EINTPEND 表明是否occur interrupt,如果是则1,不是这置0。当然和INTPND一样,我们需要在中断函数中将其(写1)清零,不然CPU会持续产生中断。

【题外话:关于INTPENDEINTPEND的清零顺序,我做了一个实验。

实验原理:在利用EINT4(即KEY2)产生正常产生中断的前提下,写该了一下清零INTPENDEINTPEND的顺序。同时在中断服务函数中加了蜂鸣器语句:Beep(4000,100);这样每进一次中断,蜂鸣器就会响一次,如果多次进入就会响多次。

具体如下:

清零

INTPEND

EINTPEND

I,后EI

EI,后I

现象

间断而持续

间断而持续响

2次或3

1

这个实验结果,让我有些迷惑,我一直在想S3C2440的内部中断系统是一个什么样的结构,为何会产生这样的结果。网上有人这样写到“在中断触发跳入中断处理函数后,首先要清除SRCPNDINTPND相应的位,如果用到次级中断源,如这里用到了EINT4_7中的EINT4,就要清除EINTPEND相应的位。一般来说,应该先清除次级中断源相应的位,再清除中断源,否则中断源会发生多次中断。在完成清除后再进行具体的处理。 但我依然不知道为什么。如果各位有知道的话,请告诉我,我会很感激不尽的。】

寄存器:INTMSK

20110604004437003.jpg

   寄存器:EINTMASK

20110604004438004.jpg

3         常用的函数

【现在前面的话】:

S3C的技术手册中,并没有提到如何具体的编写相关的中断函数,而对于具体的ARM是如何是实现中断的,我还没有深入的研究,现在只是知道如何用C编写相关的函数。本来想好好的研究一番,但不符合学习计划主路线的要求,只能先放一放。

以下代码的硬件平台为TQ2440,只写了两个较重要的函数,我相信只要你能充分理解S3C2440datasheet就可以写出完整的中断程序,我在写程序时也之参考了S3C2440datasheetTQ的电路原理图,虽然工作量比较大,但也收获很多,有知识上的,也有思想上的。

3.1       初始化函数

该函数包括两个部分:

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

          ;

}

3.2       中断服务函数

该函数包括三个部分:

//*****************************************************************************

//

//! \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条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条