1.先查看《Tiny6410SDK-1103底板原理图》,找到按键部分:
从上图可知,当按键按下时,相当于接地,即低电平,从而产生一个由高电平到低电平的跳变。
Tiny6410的底板有8个按键:
2.查看《Tiny6410-1170CPU核心板原理图》,找到EINT0的连接图:
从上图可知:
EINT0接GPN0
EINT1接GPN1
EINT2接GPN2
ENIT3接GPN3
EINT4接GPN4
EINT5接GPN5
EINT19接GPL11
EINT20接GPL12
知识点:
由s3c6410外部触发的中断就是外部中断,由s3c6410内部触发的是内部中断,像watchdog就是内部中断,像key,wm9717触发的就是外部中断。
外部中断从外设到cpu的具体流程:
外设------>GPIO------>VIC------>ARM1176
我们编写关于中断的程序也是这个过程:
配置外设------>配置GPIO------>配置VIC------>配置ARM协处理器等
其实就是要打造一个通路能够让中断的电平变化能顺顺利利的传送到ARM里!
3.中断设置流程
外设都是连到GPIO上的。s3c6410具有187个多功能I/O端口,其实有127个用于外部中断。这127个引脚可以分为10个分组:
EINT0GPN0--->GPN15GPL8--->GPL14GPM0--->GPM4
EINT1GPA0--->GPA7GPB0--->GPB6
EINT2GPC0--->GPC7
EINT3GPD0--->GPD5
EINT4GPF0--->GPF14
EINT5GPG0--->GPG7
EINT6GPH0--->GPH9
EINT7GPO0--->GPO15
EINT8GPP0--->GPP14
EINT9GPQ0--->GPQ9
每个引脚可以对应一个外部中断。那么当外部中断电平变化传GPIO里,除了对应端口的哪几个寄存器(CON,PUD,etc)GPIO里又有哪些寄存器会
对这个中断信号造成影响呢?看下面:
EINTXCON:配置触发方式,低电平,高电平,上升沿,下降沿。
EINTXPEND:这个现在用不到,一会儿中断处理程序会用到,这个是pendingregister.
EINTXMASK:这里可以屏蔽某个外部中断,要通过需要clear一下对应的中断位。默认是全屏蔽的。
EINTXFLTCON:这里设置滤波方式,可以去毛刺。
我们这里要设置的是EINTXCON,EINTXMASK,EINTXFLTCON。这样我们的中断信号就可以顺利通过GPIO了,然后就是VIC向量中断控制器了。
上面说的这些外部中断在GPIO里分成了九组,具体反应到VIC里他们占用中断号如下:
No
|
Sources
|
Description
|
Group
|
0
|
INT_EINT0
|
Externalinterrupt0~3
|
VIC0
|
1
|
INT_EINT1
|
Externalinterrupt4~11
|
VIC0
|
32
|
INT_EINT2
|
Externalinterrupt12~19
|
VIC1
|
33
|
INT_EINT3
|
Externalinterrupt20~27
|
VIC1
|
53
|
INT_EINT4
|
ExternalinterruptGroup1~Group9
|
VIC1
|
这里我们使用VIC,当然要先开启VIC,这个是在协处理器里设置的VE位
mrcp15,0,r0,c1,c0,0
orrr0,r0,#(1<<24)"
mcrp15,0,r0,c1,c0,0
主要是通过CP15协处理器特定的寄存器来控制VIC的使能:查看arm6410手册,arm1176JZF-S.pdf第3-14页如下图所示,
因为op1=0,CRn=c1,CRm=c0,op2=0,跳转到3-44页图所示,查看对应寄存器。
首先,mrcp15,0,r0,c1,c0,0将协处理器cp15中op1=0,CRn=c1,CRm=c0,
op2=0所对应的寄存器的值传给r0寄存器。
其次,orrr0,r0,#(1<<24)将上面得到的r0寄存器的值与1左移24位得到的值进行按位或运算,将得到的结果放入r0中。
最后,mcrp15,0,r0,c1,c0,0将运算后的r0的值重新放回cp15协处理器对应的寄存器当中。
这样我们的VIC就能用了。
然后就是开启总中断:
mrsr0,cpsr
bicr0,r0,#0x80
msrcpsr_c,r0
然后是VIC的设置,几个重要的寄存器:
VICXINTSELECT:选择中断方式FIQorIRQ。
VICXVECTADDR:设置中断处理程序的地址。
VICXINTENABLE:使能GPIO传过来的中断信号。
其实设置到这里外部中断就能正确运行了,但是还有许多别的寄存器,比如设置什么优先级的。
ARM得知来了个中断,就和VIC进行一系列的握手,得到VICADDRESS,就开始执行我们的中断处理程序了。最后要清除一下EINTXPEND和VICXADDRESS。
4.程序实现:
inter.s:
.text
.code 32
.global _start
.global asm_handle_k1_irq
.extern interrupt_test
.extern handle_k1_irq
_start:
@disable watch dog
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
@enable vic
mrc p15,0,r0,c1,c0,0
orr r0,r0,#(1<<24)
mcr p15,0,r0,c1,c0,0
@enable interrupt
mrs r0,cpsr
bic r0,r0,#0x80
msr cpsr_c,r0
ldr sp, = 0x0C001000
@sp_irq mode
msr cpsr_cxsf,#0xd2
ldr sp, = 0x0C001000
@return back to svc mode
msr cpsr_cxsf, #0x13
bl interrupt_test
loop:
b loop
asm_handle_k1_irq:
stmfd sp!, {r0-r3,r12,lr}
ldr lr,=int_return
bl handle_k1_irq
int_return:
ldmfd sp!, {r0-r3,r12,lr}
subs pc,lr,#4
inter_func.c:
#define GPKCON0 *((volatile unsigned int*)0x7F008800)
#define GPKDAT *((volatile unsigned int*)0x7F008808)
#define GPKPUD *((volatile unsigned int*)0x7F00880C)
#define GPNCON *((volatile unsigned int*)0x7F008830)
#define GPNPUD *((volatile unsigned int*)0x7F008838)
#define EINT0CON0 *((volatile unsigned int*)0x7F008900)
#define EINT0MASK *((volatile unsigned int*)0x7F008920)
#define EINT0PEND *((volatile unsigned int*)0x7F008924)
#define EINT0FLTCON0 *((volatile unsigned int*)0x7F00891C)
#define VIC0INTSELECT *((volatile unsigned int*)0x7120000C)
#define VIC0VECTADDR *((volatile unsigned int*)0x71200100)
#define VIC0INTENABLE *((volatile unsigned int*)0x71200010)
#define VIC0INTENCLEAR *((volatile unsigned int*)0x71200014)
#define VIC0ADDRESS *((volatile unsigned int*)0x71200F00)
#define VIC1ADDRESS *((volatile unsigned int*)0x71300F00)
typedef void (isr) (void);
extern void asm_handle_k1_irq();
void led_init()
{
//init gpkcon
GPKCON0 &= 0x0000ffff;
GPKCON0 |= 0x11110000;
//set output
//light led1
GPKDAT = 0xffef;
//set pull-up register
//GPKPUD = 0x000aa00;
}
void handle_k1_irq()
{
//reverse led1
GPKDAT ^= 0x0010;
// clear K1 irq
EINT0PEND = 1;
//clear irq
VIC0ADDRESS = 0;
VIC1ADDRESS = 0;
}
void key_io_init()
{
//configure k1 as Ext.Interrupt
GPNCON &= (~0x03);
GPNCON |= 0x02;
GPNPUD &= ~(0x3);
//configure k1 as falling edge trigged
EINT0CON0 &= (~0x03);
EINT0CON0 |= 0x3;
//EINT0FLTCON0 |= 0x40;
//Enable EINT0 irq
EINT0MASK &= (~0x1);
// Select INT_EINT0 mode as irq
VIC0INTSELECT = 0;
// init the isr addr
isr** isr_array = (isr**)(0x71200100);
isr_array[0] = (isr*)asm_handle_k1_irq;
//EINT0PEND = 0xffffffff;
//VIC0INTENCLEAR = 0xffffffff;
//enable
VIC0INTENABLE |= 0x01;
}
void interrupt_test()
{
led_init();
key_io_init();
}
makefile:
CC=arm-linux-gcc
LD=arm-linux-ld
OBJCOPY=arm-linux-objcopy
CFLAG=-c
LDFLAG=-e _start -Ttext 0x0c000000
inter.bin: inter
$(OBJCOPY) -O binary $< $@
inter: inter.o inter_func.o
$(LD) $(LDFLAG) $? -o $@
inter.o:inter.s
$(CC) $(CFLAG) $< -o $@
inter_func.o:inter_func.c
$(CC) $(CFLAG) $< -o $@
clean:
rm *.o
rm inter
rm inter.bin
长按二维码向我转账
受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。
阅读
好看
已推荐到看一看
你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
取消
分享想法到看一看
确定
最多200字,当前共字
微信扫一扫
关注该公众号