版权声明:本文为博主原创文章,允许转载请注明。谢谢! <a class="copy-right-url" href=" https://blog.csdn.net/wangweijundeqq/article/details/78632424"> https://blog.csdn.net/wangweijundeqq/article/details/78632424</a>
</div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css">
<div class="htmledit_views" id="content_views">
上接:
http://blog.csdn.net/wangweijundeqq/article/details/78634146
ARM裸机学习之中断系统1(S5PV210的中断系统详解)
六
、
S5PV210中断处理
1.S5PV210的外部中断通过外部中断对应的GPIO产生
外部中断寄存器位于文档中GPIO部分。
外部中断的主要寄存器:
EXT_INT_N_CON:设置外部中断的触发方式
EXT_INT_N_PEND:中断挂起寄存器,32位,每位对应一个外部中断源,
EXT_INT_N_MASK:中断掩码控制寄存器,各个外部中断的使能/禁止开关。
分析X210开发板的按键对应的EINT编号:
GPIO :SW5:GPH0_2 SW6:GPH0_3 SW78910:GPH2_0123
EINT :EINT2、EINT3、EINT16、EINT17、EINT18、EINT19
2.中断方式处理按键编程
按键的初始化(包括外部中断的GPIO,触发模式等设置,分开说明)
2.1. 外部中断对应的GPIO模式设置
rGPH0CON |=
0xFF<<
8;
rGPH2CON |=
0xFFFF<<
0;
.
2.2. 中断触发模式设置
rEXT_INT_0_CON &= ~(
0xFF<<
8);
// bit8~bit15全部清零
rEXT_INT_0_CON
|= ((2<<8)|(
2<<
12));
// EXT_INT2和EXT_INT3设置为下降沿触发
rEXT_INT_2_CON &= ~(
0xFFFF<<
0);
//EINT16、
17、
18、
19,设置为下降沿触发
rEXT_INT_2_CON
|= ((2<<0)|(
2<<
4)
|(2<<8)|(
2<<
12));
按键的初始化(包括外部中断的GPIO,触发模式等设置)的整合如下:
2.3. 中断允许
rEXT_INT_0_MASK &= ~(
3<<
2);
rEXT_INT_2_MASK &= ~(
0x0f<<
0);
2.4. 清挂起,清除是写1,不是写0
rEXT_INT_0_PEND |= (3<<2);
rEXT_INT_2_PEND |=
(0x0F<<
0);
按键的初始化(包括外部中断的GPIO,触发模式等设置)的整合如下:
3.中断处理程序isr编写及其整体调用
3.1.中断ISR处理函数的编写,即(类似于STM32的中断服务函数)
3.2.绑定isr到中断控制器硬件
3.3.使能中断(不是使能外部中断(因前面的中断初始化已经使能),是使能中断控制器)
3.4.整体调用如下:
3.5
最后,上面的理解在结合下图 一起理解,就显得很简单了。
中断处理的编程模型:
(参考
http://blog.csdn.net/kiny_anderson/article/details/46884893
)
int.c:
#include "int.h"
#include "stdio.h"
void reset_exception(
void)
{
printf(
"reset_exception.\n");
}
void undef_exception(
void)
{
printf(
"undef_exception.\n");
}
void sotf_int_exception(
void)
{
printf(
"sotf_int_exception.\n");
}
void prefetch_exception(
void)
{
printf(
"prefetch_exception.\n");
}
void data_exception(
void)
{
printf(
"data_exception.\n");
}
void system_init_exception(
void)
{
r_exception_reset = (
unsigned
int)reset_exception;
r_exception_undef = (
unsigned
int)undef_exception;
r_exception_sotf_int = (
unsigned
int)sotf_int_exception;
r_exception_prefetch = (
unsigned
int)prefetch_exception;
r_exception_data = (
unsigned
int)data_exception;
r_exception_irq = (
unsigned
int)IRQ_handle;
r_exception_fiq = (
unsigned
int)IRQ_handle;
intc_init();
}
void intc_clearvectaddr(
void)
{
VIC0ADDR =
0;
VIC1ADDR =
0;
VIC2ADDR =
0;
VIC3ADDR =
0;
}
void intc_init(
void)
{
VIC0INTENCLEAR =
0xffffffff;
VIC1INTENCLEAR =
0xffffffff;
VIC2INTENCLEAR =
0xffffffff;
VIC3INTENCLEAR =
0xffffffff;
VIC0INTSELECT =
0x0;
VIC1INTSELECT =
0x0;
VIC2INTSELECT =
0x0;
VIC3INTSELECT =
0x0;
intc_clearvectaddr();
}
void intc_setvectaddr(
unsigned
long intnum,
void (*handler)(
void))
{
if(intnum<
32)
{
*( (
volatile
unsigned
long *)(VIC0VECTADDR +
4*(intnum
-0)) ) = (
unsigned)handler;
}
else
if(intnum<
64)
{
*( (
volatile
unsigned
long *)(VIC1VECTADDR +
4*(intnum
-32)) ) = (
unsigned)handler;
}
else
if(intnum<
96)
{
*( (
volatile
unsigned
long *)(VIC2VECTADDR +
4*(intnum
-64)) ) = (
unsigned)handler;
}
else
{
*( (
volatile
unsigned
long *)(VIC3VECTADDR +
4*(intnum
-96)) ) = (
unsigned)handler;
}
return;
}
void intc_enable(
unsigned
long intnum)
{
unsigned
long temp;
if(intnum<
32)
{
temp = VIC0INTENABLE;
temp |= (
1<<intnum);
VIC0INTENABLE = temp;
}
else
if(intnum<
64)
{
temp = VIC1INTENABLE;
temp |= (
1<<(intnum
-32));
VIC1INTENABLE = temp;
}
else
if(intnum<
96)
{
temp = VIC2INTENABLE;
temp |= (
1<<(intnum
-64));
VIC2INTENABLE = temp;
}
else
if(intnum<NUM_ALL)
{
temp = VIC3INTENABLE;
temp |= (
1<<(intnum
-96));
VIC3INTENABLE = temp;
}
else
{
VIC0INTENABLE =
0xFFFFFFFF;
VIC1INTENABLE =
0xFFFFFFFF;
VIC2INTENABLE =
0xFFFFFFFF;
VIC3INTENABLE =
0xFFFFFFFF;
}
}
void intc_disable(
unsigned
long intnum)
{
unsigned
long temp;
if(intnum<
32)
{
temp = VIC0INTENCLEAR;
temp |= (
1<<intnum);
VIC0INTENCLEAR = temp;
}
else
if(intnum<
64)
{
temp = VIC1INTENCLEAR;
temp |= (
1<<(intnum
-32));
VIC1INTENCLEAR = temp;
}
else
if(intnum<
96)
{
temp = VIC2INTENCLEAR;
temp |= (
1<<(intnum
-64));
VIC2INTENCLEAR = temp;
}
else
if(intnum<NUM_ALL)
{
temp = VIC3INTENCLEAR;
temp |= (
1<<(intnum
-96));
VIC3INTENCLEAR = temp;
}
else
{
VIC0INTENCLEAR =
0xFFFFFFFF;
VIC1INTENCLEAR =
0xFFFFFFFF;
VIC2INTENCLEAR =
0xFFFFFFFF;
VIC3INTENCLEAR =
0xFFFFFFFF;
}
return;
}
unsigned
long intc_getvicirqstatus(
unsigned
long ucontroller)
{
if(ucontroller ==
0)
return VIC0IRQSTATUS;
else
if(ucontroller ==
1)
return VIC1IRQSTATUS;
else
if(ucontroller ==
2)
return VIC2IRQSTATUS;
else
if(ucontroller ==
3)
return VIC3IRQSTATUS;
else
{}
return
0;
}
void irq_handler(
void)
{
unsigned
long vicaddr[
4] = {VIC0ADDR,VIC1ADDR,VIC2ADDR,VIC3ADDR};
int i=
0;
void (*isr)(
void) =
NULL;
for(i=
0; i<
4; i++)
{
if(intc_getvicirqstatus(i) !=
0)
{
isr = (
void (*)(
void)) vicaddr[i];
break;
}
}
(*isr)();
}
key.c:
#include "stdio.h"
#include "main.h"
#define GPH0CON 0xE0200C00
#define GPH0DAT 0xE0200C04
#define GPH2CON 0xE0200C40
#define GPH2DAT 0xE0200C44
#define rGPH0CON (*(volatile unsigned int *)GPH0CON)
#define rGPH0DAT (*(volatile unsigned int *)GPH0DAT)
#define rGPH2CON (*(volatile unsigned int *)GPH2CON)
#define rGPH2DAT (*(volatile unsigned int *)GPH2DAT)
#define EXT_INT_0_CON 0xE0200E00
#define EXT_INT_2_CON 0xE0200E08
#define EXT_INT_0_PEND 0xE0200F40
#define EXT_INT_2_PEND 0xE0200F48
#define EXT_INT_0_MASK 0xE0200F00
#define EXT_INT_2_MASK 0xE0200F08
#define rEXT_INT_0_CON (*(volatile unsigned int *)EXT_INT_0_CON)
#define rEXT_INT_2_CON (*(volatile unsigned int *)EXT_INT_2_CON)
#define rEXT_INT_0_PEND (*(volatile unsigned int *)EXT_INT_0_PEND)
#define rEXT_INT_2_PEND (*(volatile unsigned int *)EXT_INT_2_PEND)
#define rEXT_INT_0_MASK (*(volatile unsigned int *)EXT_INT_0_MASK)
#define rEXT_INT_2_MASK (*(volatile unsigned int *)EXT_INT_2_MASK)
void key_init(void)
{
rGPH0CON &= ~(
0xFF<<
8);
rGPH2CON &= ~(
0xFFFF<<
0);
}
static void delay20ms(void)
{
int i, j;
for (i=
0; i<
100; i++)
{
for (j=
0; j<
1000; j++)
{
i * j;
}
}
}
void key_polling(void)
{
while (
1)
{
if (rGPH0DAT & (
1<<
2))
{
led_off();
}
else
{
delay20ms();
if (!(rGPH0DAT & (
1<<
2)))
{
led1();
printf(
"key left.\n");
}
}
if (rGPH0DAT & (
1<<
3))
{
led_off();
}
else
{
led2();
printf(
"key down.\n");
}
if (rGPH2DAT & (
1<<
0))
{
led_off();
}
else
{
led3();
}
}
}
void key_init_interrupt(void)
{
rGPH0CON |=
0xFF<<
8;
rGPH2CON |=
0xFFFF<<
0;
rEXT_INT_0_CON &= ~(
0xFF<<
8);
rEXT_INT_0_CON |= ((
2<<
8)|(
2<<
12));
rEXT_INT_2_CON &= ~(
0xFFFF<<
0);
rEXT_INT_2_CON |= ((
2<<
0)|(
2<<
4)|(
2<<
8)|(
2<<
12));
rEXT_INT_0_MASK &= ~(
3<<
2);
rEXT_INT_2_MASK &= ~(
0x0f<<
0);
rEXT_INT_0_PEND |= (
3<<
2);
rEXT_INT_2_PEND |= (
0x0F<<
0);
}
void isr_eint2(void)
{
printf(
"isr_eint2_LEFT.\n");
rEXT_INT_0_PEND |= (
1<<
2);
intc_clearvectaddr();
}
void isr_eint3(void)
{
printf(
"isr_eint3_DOWN.\n");
rEXT_INT_0_PEND |= (
1<<
3);
intc_clearvectaddr();
}
void isr_eint16171819(void)
{
if (rEXT_INT_2_PEND & (
1<<
0))
{
printf(
"eint16\n");
}
if (rEXT_INT_2_PEND & (
1<<
1))
{
printf(
"eint17\n");
}
if (rEXT_INT_2_PEND & (
1<<
2))
{
printf(
"eint18\n");
}
if (rEXT_INT_2_PEND & (
1<<
3))
{
printf(
"eint19\n");
}
rEXT_INT_2_PEND |= (
0x0f<<
0);
intc_clearvectaddr();
}
start.S:
#define WTCON 0xE2700000
#define SVC_STACK 0xd0037d80
#define IRQ_STACK 0xd0037f80
.
global _start
.
global IRQ_handle
_start:
ldr r0, =WTCON
ldr r1, =
0x0
str r1, [r0]
bl clock_init
ldr sp, =SVC_STACK
mrc p15,
0,r0,c1,c0,
0;
orr r0, r0,
#(1<<12) // bit12 置1 开icache
mcr p15,
0,r0,c1,c0,
0;
bl main
b .
IRQ_handle:
ldr sp, =IRQ_STACK
sub lr, lr,
#4
stmfd sp!, {r0-r12, lr}
bl irq_handler
ldmfd sp!, {r0-r12, pc}^
main.c:
#include "stdio.h"
#include "int.h"
#include "main.h"
void uart_init(void);
#define KEY_EINT2 NUM_EINT2
#define KEY_EINT3 NUM_EINT3
#define KEY_EINT16_19 NUM_EINT16_31
void delay(int i)
{
volatile
int j =
10000;
while (i--)
while(j--);
}
int main(void)
{
uart_init();
key_init_interrupt();
system_init_exception();
printf(
"-------------key interrypt test--------------");
intc_setvectaddr(KEY_EINT2, isr_eint2);
intc_setvectaddr(KEY_EINT3, isr_eint3);
intc_setvectaddr(KEY_EINT16_19, isr_eint16171819);
intc_enable(KEY_EINT2);
intc_enable(KEY_EINT3);
intc_enable(KEY_EINT16_19);
while (
1)
{
printf(
"A ");
delay(
10000);
}
return
0;
}