S3C2440 keyboard module circuit
There are a total of S1, S2, S3, and S4 buttons, corresponding to the four interrupt sources of EINT19, EINT2, EINT0, and EINT11. The interrupt framework and service routine are as follows:
Interrupt response, take out the keyboard number (1-4) that triggered the interrupt and put it in 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;//开放中断
}