嵌入式系统设计与实践:Linux篇
上QQ阅读APP看书,第一时间看更新

4.2 中断控制器

1.中断的概念

中断是指在计算机执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序。待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。在嵌入式系统中外部设备的功能实现主要是靠中断机制来实现的。

2.中断的功能

中断功能可以解决CPU内部运行速度远远快于外部总线速度而产生的等待延时问题。它是计算机可以更好更快利用有限的系统资源解决系统响应速度和运行效率的一种控制技术。

(1)并行操作;

(2)硬件故障报警与处理;

(3)支持多道程序并发运行,提高计算机系统的运行效率;

(4)支持实时处理功能。

3.中断类型与中断的优先级

ARM系统包括两类中断:一类是IRQ中断,另一类是FIQ中断。IRQ是普通中断,FIQ是快速中断,在进行大批量的复制、数据传输等工作时,常使用FIQ中断。FIQ的优先级高于IRQ。在ARM系统中,支持7类异常,包括:复位、未定义指令、软中断、预取中止、数据中止、IRQ和FIQ,每种异常对应于不同的处理器模式。一旦发生异常,首先要进行模式切换,然后程序将转到该异常对应的固定存储地址执行。这个固定的地址称为异常向量。异常向量中保存的通常为异常处理程序的地址。S3C2410中ARM中断模式及中断向量入口地址如表4.8所示。

表4.8 ARM中断模式及中断向量入口地址

4.中断响应过程

中断响应过程描述如下:

(1)当发生中断IRQ时,CPU进入“中断模式”,这时使用“中断模式”下的堆栈;当发生快中断FIQ时,CPU进入“快中断模式”,这时使用“快中断模式”下的堆栈。所以在使用中断前,应先设置好相应模式下的堆栈。

(2)对于Request sources中的中断,将INTSUBMSK寄存器中相应位设为0。

(3)将INTMSK寄存器中相应位设为0。

(4)确定中断是FIQ还是IRQ。

a.如果是FIQ,则在INTMOD寄存器设置相应位为1;

b.如果是IRQ,则在RIORITY寄存器中设置优先级。

(5)准备好中断处理函数

a.中断向量:在中断向量设置好当FIQ或IRQ被触发时的跳转函数,IRQ、FIQ的中断向量地址分别为0x00000018、0x0000001c。

b.对于IRQ,在跳转函数中读取INTPND寄存器或INTOFFSET寄存器的值来确定中断源,然后调用具体的处理函数。

c.对于FIQ,因为只有一个中断可以设为FIQ,无须判断中断源。

d.中断处理函数进入和返回。

(6)设置CPSR寄存器中的F-bit(对于FIQ)或I-bit(对于IRQ)为0,开中断。

中断返回之前需要清中断:设置次级源待决中断寄存器SUBSRCPND、源待决中断寄存器SRCPND、中断请求寄存器INTPND中相应位写1即可。

中断流程图如图4.4所示

图4.4 中断的响应过程

5.与中断相关的寄存器

常用的中断寄存器如表4.9所示。

表4.9 常用的中断寄存器

S3C2410.h中与中断相关的地址映射为:

    #define rSRCPND    (*(volatile unsigned *)0x4a000000)
    //Interrupt request status
    #define rINTMOD    (*(volatile unsigned *)0x4a000004)
    //Interrupt mode control
    #define rINTMSK    (*(volatile unsigned *)0x4a000008)
    //Interrupt mask control
    #define rPRIORITY   (*(volatile unsigned *)0x4a00000c)
    //IRQ priority control
    #define rINTPND    (*(volatile unsigned *)0x4a000010)
    //Interrupt request status
    #define rINTOFFSET  (*(volatile unsigned *)0x4a000014)
    //Interruot request source offset
    #define rSUBSRCPND  (*(volatile unsigned *)0x4a000018)
    //Sub source pending
    #define rINTSUBMSK  (*(volatile unsigned *)0x4a00001c)
    //Interrupt sub mask

6.中断寄存器的设置实例

下列函数init_irq是中断初始化函数,函数中应用GPG3、GPG6、GPG7、GPG11产生的外部中断输入功能,采用系统默认的优先级、默认的低电平触发,所有的中断都设为IRQ中断模式,通过设置中断屏蔽寄存器INTMSK的第5位,外部中断EINT8_23使能,通过设置外部中断屏蔽寄存器EINTMSK第11、14、15、19位,中断EINT11、EINT14、EINT15、EINT19使能。

分析:由于通过GPG3、GPG6、GPG7、GPG11将产生的外部中断输入,S3C2410中用控制位10控制外部中断输入。程序中首先用表达式~(3<<6)的“与运算”设置第6、7控制位为00,再与表达式(2<<6)进行或运算,用于控制GPG3引脚的控制位为10,控制GPG3达到外部中断输入的功能(在本题中第6~7、12~13、14~15、22~23控制位需设置为10),通过以下语句设置:

      rGPGCON & = (~((3<<6)| (3<<12)| (3<<14)| (3<<22)));
      rGPGCON | =(2<<6)| (2<<12)| (2<<14)| (2<<22);

保证GPGCON第6~7、12~13、14~15、22~23控制位为10。

中断优先级使用默认的固定优先级,中断模式使用IRQ中断,通过语句:

      rPRIORITY=0x00000000;
      rINTMOD=0x00000000;

设置中断优先级与中断模式。

外部中断EINT8_23使能需要将中断寄存器INTMSK第5位设置为0。

通过设置rEINTMASK的11、14、15、19位为0,使EINT11、EINT14、EINT15、EINT19中断使能,因而有语句:

        rEINTMASK & = (~((1<<11) | (1<<14) | (1<<15) | (1<<19)));

此问题完整的中断函数如下:

      void  init_irq(  )
      {
        rGPGCON & = (~((3<<6)| (3<<12)| (3<<14)| (3<<22)));
        rGPGCON | =(2<<6)| (2<<12)| (2<<14)| (2<<22);
        //设置GPG3、GPG6、GPG7、GPG11引脚的中断功能
      rPRIORITY=0x00000000;
      //使用默认的固定优先级
          rINTMOD = 0x00000000
      //所有中断均为IRQ中断
      rINTMSK & = ( ~(1<<5));
      //使能外部中断EINT8_23
          rEINTMASK & = (~((1<<11) | (1<<14) | (1<<15) | (1<<19)));
      //EINT11、EINT14、EINT15、EINT19中断使能
      }

        思考:分析下列函数,写出函数代码的含义。
        void Enable_Eint(void)
        {
        rEINTPEND = 0xffffff; //to clear the previous pending states
        rSRCPND |= BIT_EINT0|BIT_EINT2|BIT_EINT8_23;
        rINTPND |= BIT_EINT0|BIT_EINT2|BIT_EINT8_23;
        rEINTMASK=~( (1<<11)|(1<<19) );
        rINTMSK=~(BIT_EINT0|BIT_EINT2|BIT_EINT8_23);
        }

7.常用中断处理函数

在Linux操作系统中应用于S3C2410中常用的中断处理函数有: