按键中断---那些年我们一起玩mini2440(arm9)裸机

ARM中断控制系统

按键驱动程序设计

一.Arm中断控制系统

1.查询方式

程序不断地查询设备的状态,并做出相应的反应。该方式实现比较简单,常用在比较单一的系统中,比如:一个温控系统中可以实用查询的方式不断检测温度变化。

特点:实现简单;但CPU利用率很低,不适合多任务的系统。

2.中断方式

当事件发生时,硬件会设置某个寄存器;CPU在每执行完一个指令时,查看这个寄存器,如果所关注的事件发生了,则中断当前程序,跳转到一个固定的地址处理这个事件,处理完后返回到被中断的程序中继续运行。

特点:实现相对复杂,但效率较高,是常用的方法。

中断处理流程:

(1)中断控制器汇集各类外设发出的中断信号然后通知CPU;

(2)CPU保存当前程序的运行环境然后调用中断服务程序ISR来处理中断

(3)ISR中通过读取外设的相关寄存器来识别中断的类型,并进行相应的处理

(4)清除中断:通过读写在相关中断控制寄存器和外设相关寄存器来实现;

(5)恢复被中断程序的执行环境继续执行被中断的程序。

简化版:

1.汇集中断信号,通知CPU;

2.CPU保存当前运行环境,调用中断服务程序ISR

3.ISR读取寄存器识别中断类型

4.清中断

5.恢复中断程序的执行环境;

速记版:会(汇集)CCPUI(IRS)(清中断)回复(恢复);

S3c2440支持60个中断源,含子中断源

SUBSRCPND(用于标明子中断源有没有发生中断)【发生中断被置1清除子中断写入1

SUBSRCPND寄存器用来表明子中断(如:INT_RXD0是否发生。S3C244015个子中断,SUBSRCPND中每一位对应一个子中断,当这些子中断发生时,相应的位置被置1.清除子中断只需向SUBSRCPND寄存器中相应位写入1.

INTSUBMSK屏蔽SUBSRCPND的中断,1时屏蔽子中断

INTSUBMSK寄存器用来屏蔽SUBSRCPND寄存器所标的中断。INTSUBMSK

寄存器中某位被设为1时,相应的子中断被屏蔽。设为0时,表示子中断被允许。

SRCPND(用于标明中断源有没有发生中断)【发生中断被置1清除(子)中断写入1

SRCPND某一位用来标明一个(或一类)中断是否已经发生。例如:SRCPND

寄存器中的子中断INT_RXD0发生了,且没有被INTSUBMSK屏蔽,则SRCPNDINT_UART0位被置1. SRCPND寄存器的清除与SUBSRCPND寄存器相似,若想清除某一位,往此位写入1.

INTMSK(被置1时,中断屏蔽;0时,中断允许)

INTMSK寄存器用来屏蔽SRCPND所表示的中断。INTMSK某位被置为1时,对应的中断被屏蔽;设置为0时,相应中断被允许。

INTMSK只能屏蔽设为IRQ的中断,不能屏蔽设为FIQ的中断。

INTMODE1时,FIQ模式;0时,IRQ模式

INTMODE寄存器中某位被设置为1时,它所对应的中断源会被设置为FIQ模式,即此时中断发生时,CPU将进入快速中断模式,这通常用来处理特别紧急的中断。当该位被置为0时,表示为IRQ模式。

FIQ & IRQ

(1) IRQ模式下,中断处理程序需要自己保存R8R12这几个寄存器,退出中断处理时需要自己恢复这几个寄存器,而FIQ模式由于这几个寄存器都有back寄存器(fiq_r8….,模式切换时CPU自动保存这些值到back寄存器,退出FIQ模式时自动恢复,所以这个过程FIQIRQ快。

(2) FIQIRQ有高的优先级,优先处理FIQ

#define    GLOBAL_CLK             1

#include 

#include 

#include "def.h"

#include "option.h"

#include "2440addr.h"

#include "2440lib.h"

#include "2440slib.h"

#include "mmu.h"

#include "profile.h"

#include "memtest.h"

void key_init(void);

static void __irq key_handler(void);

void beep_init(void);

void beep_run(void);

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

Function name: delay

Parameter    : times

Description     : 延时函数

Return            : void

Argument     : void

Autor & date : Daniel

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

void delay(int times)

{

    int i,j;

    for(i=0;i

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

重点分析:

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

中断控制程序分析:

按键作为中断源

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

Function name: key_init()

Parameter: void

Description:按键K1的初始化函数

Return: void

Argument: void

Autor & date : Daniel

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

void key_init(void)

{

rGPGCON &= ~(0x3<<0); /*set eint8 as interrupt*/

rGPGCON |= (0x2<<0);

rEXTINT1 &= ~(0xf<<0); /*外部中断控制寄存器set eint8 with low level*/

rEINTPEND |= (1<<8); /*外部中断待定寄存器*/

rEINTMASK &= ~(1<<8); /*外部中断屏蔽寄存器*/

/*设置ISR*/

pISR_EINT8_23=(U32)key_handler;//按键按下就会执行相应的中断函数

EnableIrq(BIT_EINT8_23); //使能相应中断

}

<>.GPGCON0作为中断引脚

<>.EXTINT1外部中断寄存器1低四位设置全为0;低电平触发中断;

<>.EINTPEND8位清中断;判断中断源是否发生;

<>EINTMASK8位设为0,不屏蔽中断

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

Function name: key_handler()

Parameter: void

Description:按键K1的中断服务子程序

Return: void

Argument: void

Autor & date : Daniel

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

static void __irq key_handler(void)

{

/*判断是否是按键K1产生的中断*/

if(rINTPND==BIT_EINT8_23)

{

ClearPending(BIT_EINT8_23); //进入中断处理函数第一件事就是清中断,如果不清中断无法产生下次中断

if(rEINTPEND&(1<<8))

{

rEINTPEND |= 1<< 8;

beep_run();

}

}

}

原文链接:加载失败,请重新获取