S3C2440——键盘中断服务程序

S3C2440键盘模块电路

在这里插入图片描述

一共有S1、S2、S3、S4个按键,分别对应EINT19、EINT2、EINT0、EINT11这四个中断源。中断框架及服务程序如下:

中断响应,取出触发中断的键盘编号(1-4)放到R5中

;文件ASM_Interrupt.s
;(1)设置中断向量表
Mode_USR	EQU     0x50	;IRQ中断开放,FIQ中断关闭
Mode_FIQ 	EQU     0xD1	;关闭IRQ、FIQ中断
Mode_IRQ	EQU     0xD2	;关闭IRQ、FIQ中断
Mode_SVC 	EQU     0xD3	;关闭IRQ、FIQ中断

		GET	2440Reg_addr.inc
    	AREA    MyCode, CODE,READONLY
		IMPORT initial_keyboard_INT
    	ENTRY				;设置中断向量表
		B	ResetHandler		;Reset中断服务程序
		B	.			;handlerUndef
		B	.			;SWI interrupt handler
		B	.			;handlerPAbort
		B	.			;handlerDAbort
		B	.			;handlerReserved
		B	HandlerIRQ		;HandlerIRQ
		B	.			;HandlerFIQ

;(2)复位的中断处理程序
ResetHandler
		BL	Clock_Init		;初始化看门狗、时钟
		;BL	MemSetup		;初始化SDRAM
 		LDR     	SP, =SvcStackSpace	;设置管理模式堆栈
        MSR	CPSR_c, #Mode_IRQ
        LDR	SP, =IrqStackSpace	;设置IRQ中断模式堆栈
        MSR	CPSR_c, #Mode_FIQ
        LDR	SP, =FiqStackSpace	;设置FIQ中断模式堆栈
        MSR	CPSR_c, #Mode_USR	;进入用户模式
		LDR	SP, =UsrStackSpace	;设置用户与系统模式堆栈
 		;BL	Init_DATA		;初始化可读写数据
		BL initial_keyboard_INT
		LDR	R0,=pEINT0;EINT0 在中断入口散转表中的地址
		LDR	R1,=EINT0	;R1中断服务程序入口地址
		STR	R1,[R0]		;EINT0中断程序入口地址写入中断散转表
		LDR	R0,=pEINT2;EINT2 在中断入口散转表中的地址
		LDR	R1,=EINT2	;R1中断服务程序入口地址
		STR	R1,[R0]		;EINT2中断程序入口地址写入中断散转表
		LDR	R0,=pEINT8_23;EINT8_23 在中断入口散转表中的地址
		LDR	R1,=EINT8_23	;R1中断服务程序入口地址
		STR	R1,[R0]		;EINT8_23中断程序入口地址写入中断散转表
MAIN_LOOP
 		NOP
		B      	MAIN_LOOP	;死循环,被IRQ中断;初始化可读写数据区
Clock_Init
		GET	Clock_Init.s		;初始化看门狗、时钟
MemSetup
		GET	MemSetup.s		;初始化SDRAM
Init_DATA
		GET	Init_DATA.s		;初始化可读写数据区

;(3)IRQ中断处理程序
HandlerIRQ
		SUB	LR,LR, #4		;计算返回地址
    	STMFD	SP!, {LR}		;保存断点到IRQ模式的堆栈
		LDR	LR,= Int_Return 	;修改LR,执行完EINT8_23的处理程序后返回到Int_Return处
		LDR	R0,=INTOFFSET		;取得中断源的编号
		LDR	R1,[R0]
		LDR	R2,=Int_EntryTable	;中断散转表起始地址
		LDR	PC,[R2,R1,LSL#2]	;查中断散转表,取得EINT8_23的处理程序入口地址,相当于无参的子程序调用,但没保存断点
	Int_Return			;执行完EINT8_23的处理程序后须返回此处
		LDMFD  	SP!, {PC }^	;IRQ中断服务程序返回, ^表示将SPSR的值复制到CPSR
;EINT0的处理程序
EINT0
		MOV R5,#3
		LDR	R0,=SRCPND		;清除几个挂起寄存器
    	LDR	R1,[R0]
    	STR	R1,[R0]
		LDR	R0,=INTPND
    	LDR R1,[R0]
    	STR	R1,[R0]
    	MOV	PC,LR	;由EINT0处理程序返回到IRQ中断服务程序
;EINT2的处理程序
EINT2
		MOV R5,#2
		LDR	R0,=SRCPND		;清除几个挂起寄存器
    	LDR	R1,[R0]
    	STR	R1,[R0]
		LDR	R0,=INTPND
    	LDR R1,[R0]
    	STR	R1,[R0]
    	MOV	PC,LR	;由EINT2处理程序返回到IRQ中断服务程序
; (4)EINT8_23的处理程序
EINT8_23
		LDR	R0,=EINTPEND	;R0设为EINTPEND寄存器地址
		LDR 	R1,[R0]		;读取EINTPEND,共24位,最低4位保留
		CMP      	R1,#0x080000	;判断是否EINT19中断
		LDREQ  	R5,=0x1		;R5为键号
		CMP      	R1,#0x000800	;判断是否EINT11中断
		LDREQ  	R5,=0x4
		LDR	R0,=SRCPND		;清除几个挂起寄存器
    	LDR	R1,[R0]
    	STR	R1,[R0]
		LDR	R0,=INTPND
    	LDR 	R1,[R0]
    	STR	R1,[R0]
		LDR	R0,=EINTPEND
    	LDR	R1,[R0]
    	STR	R1,[R0]
    	MOV	PC,LR	;由EINT8_23处理程序返回到IRQ中断服务程序
		 AREA    MyRWData, DATA, READWRITE	;设置RW Base=0x33ffe700
Int_EntryTable
		GET	Int_EntryTable.s		;中断散转表,共32个入口
        	AREA    MyZIData, DATA, READWRITE, NOINIT,ALIGN=8
;下推式堆栈,根据对齐方式,段起始地址为0x33ffe800,各栈区空间均为1k
			SPACE	0x100 * 4	;管理模式堆栈空
SvcStackSpace	SPACE	0x100 * 4	;中断模式堆栈空间
IrqStackSpace	SPACE	0x100 * 4	;快速中断模式堆栈空间
FiqStackSpace	SPACE	0x100 *
UsrStackSpace
		END

;文件Int_EntryTable.s,定义中断散转表
;共32路,对应仲裁器32路输入
pEINT0		DCD  0		;存放EINT0-3中断服务程序入口地址
pEINT1		DCD  0
pEINT2		DCD  0
pEINT3		DCD  0

pEINT4_7	DCD  0 		;存放EINT4_7中断服务程序入口地址
pEINT8_23	DCD  0	;存放EINT8_23中断服务程序入口地址——EINT8_23

pINT_CAM	DCD  0		;存放26个内部中断服务程序入口地址
pnBATT_FLT	DCD  0
pINT_TICK 	DCD  0
pINT_WDT_AC97	DCD  0
……
pINT_UART0  DCD  0
pINT_SPI1   DCD  0
pINT_RTC 	DCD  0
pINT_ADC	DCD  0
			END
#include	"2440Reg_addr.h”	//特殊寄存器地址定义

void initial_keyboard_INT(void){
    rGPGCON=((0x10<<22)|(0x10<<6));  //设置GPIO为外部中断引脚
    rGPFCON=((0x10|(0x10<<4));// 设置GPF为中断引脚
    rGPGUP=0xffff;   //  不上拉
    rGPFUP  = 0xff;  //     不上拉
    rEINTMASK&=((0x1<<11)|(0x1<<19));//开放EINT11、19中断
    rEXTINT0=0x0;//均为低电平中断,不使用滤波
    rEXTINT1=0x0;
    rEXTINT2=0x0;
    rINTMSK=0xFFFFFFD5;//开放中断
}

猜你喜欢

转载自blog.csdn.net/qq_49588762/article/details/118674161