1. 先查看《Tiny6410SDK-1103 底板原理圖》,找到按鍵部分:
從上圖可知,當按鍵按下時,相當于接地,即低電平,從而產生一個由高電平到低電平的跳變。
Tiny6410的底板有8個按鍵:
2. 查看《Tiny6410-1170 CPU核心板原理圖》,找到EINT0的連接圖:
從上圖可知:
EINT0 接 GPN0
EINT1 接 GPN1
EINT2 接 GPN2
ENIT3 接 GPN3
EINT4 接 GPN4
EINT5 接 GPN5
EINT19 接 GPL11
EINT20 接 GPL12
知識點:
由s3c6410外部觸發的中斷就是外部中斷,由s3c6410內部觸發的是內部中斷,像watch dog就是內部中斷,像key,wm9717觸發的就是外部中斷。
外部中斷從外設到cpu的具體流程:
外設------>GPIO------>VIC------>ARM1176
我們編寫關于中斷的程序也是這個過程:
配置外設------>配置GPIO------>配置VIC------>配置ARM協處理器等
其實就是要打造一個通路能夠讓中斷的電平變化能順順利利的傳送到ARM里!
3. 中斷設置流程
外設都是連到GPIO上的。s3c6410具有187個多功能I/O端口,其實有127個用于外部中斷。這127個引腳可以分為10個分組:
EINT0 GPN0--->GPN15 GPL8--->GPL14 GPM0--->GPM4
EINT1 GPA0--->GPA7 GPB0--->GPB6
EINT2 GPC0--->GPC7
EINT3 GPD0--->GPD5
EINT4 GPF0--->GPF14
EINT5 GPG0--->GPG7
EINT6 GPH0--->GPH9
EINT7 GPO0--->GPO15
EINT8 GPP0--->GPP14
EINT9 GPQ0--->GPQ9
每個引腳可以對應一個外部中斷。那么當外部中斷電平變化傳GPIO里,除了對應端口的哪幾個寄存器(CON,PUD,etc)GPIO里又有哪些寄存器會
對這個中斷信號造成影響呢?看下面:
EINTXCON :配置觸發方式,低電平,高電平,上升沿,下降沿。
EINTXPEND :這個現在用不到,一會兒中斷處理程序會用到,這個是pending register.
EINTXMASK :這里可以屏蔽某個外部中斷,要通過需要clear一下對應的中斷位。默認是全屏蔽的。
EINTXFLTCON :這里設置濾波方式,可以去毛刺。
我們這里要設置的是EINTXCON,EINTXMASK,EINTXFLTCON。這樣我們的中斷信號就可以順利通過GPIO了,然后就是VIC 向量中斷控制器了。
上面說的這些外部中斷在GPIO里分成了九組,具體反應到VIC里他們占用中斷號如下:
No | Sources | Description | Group |
0 | INT_EINT0 | External interrupt 0 ~ 3 | VIC0 |
1 | INT_EINT1 | External interrupt 4 ~ 11 | VIC0 |
32 | INT_EINT2 | External interrupt 12 ~ 19 | VIC1 |
33 | INT_EINT3 | External interrupt 20 ~ 27 | VIC1 |
53 | INT_EINT4 | External interrupt Group 1 ~ Group 9 | VIC1 |
這里我們使用VIC,當然要先開啟VIC,這個是在協處理器里設置的 VE位
mrc p15,0,r0,c1,c0,0
orr r0,r0,#(1<<24)'
mcr p15,0,r0,c1,c0,0
主要是通過CP15協處理器特定的寄存器來控制VIC的使能:查看arm6410手冊,arm1176JZF-S.pdf 第3-14頁如下圖所示,
因為op1=0,CRn=c1,CRm=c0,op2=0,跳轉到3-44頁圖所示,查看對應寄存器。
首先,mrc p15,0,r0,c1,c0,0將協處理器cp15中op1=0,CRn=c1,CRm=c0,
op2=0所對應的寄存器的值傳給r0寄存器。
其次,orr r0,r0,#(1<<24)將上面得到的r0寄存器的值與1左移24位得到的值進行按位或運算,將得到的結果放入r0中。
最后,mcr p15,0,r0,c1,c0,0將運算后的r0的值重新放回cp15協處理器對應的寄存器當中。
這樣我們的VIC就能用了。
然后就是開啟總中斷:
mrs r0,cpsr
bic r0,r0,#0x80
msr cpsr_c,r0
然后是VIC的設置,幾個重要的寄存器:
VICXINTSELECT:選擇中斷方式FIQ or IRQ。
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
5. 問題記錄
(1) 設置GPNCON時,網上的文章寫成GPNCON &= (~0x2),實際上應該是GPNCON &= (~0x03),導致中斷無反應。
(2) 直接設置VIC向量的地址為中斷邏輯,忘記要在中斷模式下進行堆棧的保存與恢復,導致程序只能觸發一次中斷。
asm_handle_k1_irq:
stmfd sp!, {r0-r3,r12,lr}
ldr lr,=int_return
bl handle_k1_irq @一開始直接作為VIC向量的地址
int_return:
ldmfd sp!, {r0-r3,r12,lr}
subs pc,lr,#4
上一篇:Tiny6410 LED 裸機驅動筆記
下一篇:S3c6410 平臺 Android系統的Wi-Fi調試記錄
推薦閱讀最新更新時間:2025-04-17 01:41





設計資源 培訓 開發板 精華推薦
- 【CW32】無刷電機驅動
- LT1170HVCT、-10 至 -26/5A LCD 對比度電源的典型應用
- 使用 RTC2-2405SRW 隔離式 DC/DC 轉換器并根據 EN55022 A 類進行 EMC 濾波的典型應用
- STM32F411RE
- esp8266wifi攻擊器
- DER-635 - 使用 InnoSwitch3-MX 和 InnoMux 芯片組的 LED 電視 45 W 多輸出電源
- ADC多按鍵
- VNH5050A評估板
- AM30EW-2405SZ 5V 單路輸出 DC/DC 轉換器的典型應用
- LTC3672B-2 的典型應用 - 在 2mm x 2mm DFN 中具有雙路 150mA LDO 的單片式固定輸出 400mA 降壓穩壓器
- 英特爾攜海信發布端側會議領域垂域模型解決方案,讓商務會議更安全更智能
- 英特爾攜手MAXHUB聯合發布企業級AI PC, 加速AI大模型在端側落地
- 助力低碳數字未來 英飛凌攜多款創新成果亮相2025慕尼黑上海電子展
- ?日清紡微電子科技賦能產業升級,亮相慕尼黑上海電子展
- 泰克閃耀 2025 慕尼黑上海電子展,引領測試技術新變革
- 破局AI眼鏡性能、續航、成本“不可能三角”:芯原推出高集成度參考設計方案
- 人形機器人成下一風口,各大車企紛紛入局,比智能汽車潛力更大?
- 業績最高 TDK為汽車應用推出電容值達100V的MLCC
- 微型柔性機器人:開啟智能救援與精準醫療新紀元
- 人工智能加速芯片設計:動態自適應流程引領高效創新