中断处理流程:
中断源:
硬件底板原理图
能过查看硬件原理图,得知,key1,key2分别连接到CPU的GPH0_0和GPH0_1这两个管脚。
GPH0:
key1:外部中断0 ,EXT_INT[0],bit[3:0] = 1111
key2:外部中断1,EXT_INT[0],bit[7:4] = 1111
禁止这两个管脚的内部上下拉电阻,bit[3:0] = 0000
使能中断:
0:使能外部中断0
1:关闭该外部中断
当在初始化时,应该先关闭
该寄存器表示中断是否产生,当key1来了,该寄存器的bit[0]会被自动置1 ,如果中断控制器使能,ARM核中断响应使能,则CPU会响应中断,但必须在中断服务程序中将该bit清除,否则,CPU会一直响应。
写 1 清零,写 0 无效
在配置时,应该先清除中断标志
中断的触发方式:
电平触发:(高电平、低电平)
边沿触发:(上升沿、下降沿),只有在电平发生跳变时才触发
如果采用低电平触发,若按键按下不松开,就会一直触发中断
此处采用下降沿触发
中断配置方法:
禁止滤波功能,按键去抖
中断源的配置:
1,关闭中断源
2,中断标志清除
3,确定中断源,比如,按键key1,GPH0_0
GPH0_0 GPH0CON bit[3:0] = 111设置为中断
GPH0PUD bit[1:0] = 0,禁用内部上下拉电阻
4,设置该中断的中断触发方式,下降沿触发
5,禁止该中断源的滤波
中断控制器
p559
支持几个中断源
s5pv210处理器支持93个中断源
分组方式:4给VIC0(32),VICI(32),VIC2(32),VIC3(32)
128编号
key1 和 key2位于VIC0组
s5pc100处理器
此图为s5pc100处理器中中断控制器结构图,以此作为参考:
1,使能中断寄存器(VICNTCLEAR)
2,清除中断寄存器(VICNTCLEAR)
3, TZIC0的select寄存器,是走IRQ还是FIQ(TZICINTSELECT)
4,VIC0的select寄存器,是走IRQ还是FIQ(VICINTSELECT)
VIC0 -> nNSFIQIN -> TZIC0 -> nTZICFIQ -> cortex-a8
5,中断处理程序寄存器(VICVECTADDR)
6,中断向量寄存器(VICADDRESS)
使能中断寄存器(VICNTCLEAR)
使能中断,一个bit对应一个中断源
读0:中断关闭
读1:中断打开
写0:无效
写入:打开中断
清除中断寄存器:
写0,无效
写1,实现将VICINTENABLE寄存器的对应的bit清0,关闭中断
配置时,应该先关闭中断
TZIC0的select寄存器
走IRQ,bit[0] = 0
VIC0的select寄存器:
走IRQ,bit[0] = 0
中断处理程序寄存器:
128个,93个中断源,每个中断源都有一个此寄存器,用来保存对就的中断源的具体的中断处理程序的地址,在初始化中断的时候,就必须提交对应中断处理程序的地址。
中断向量寄存器:
每组只有一个,当中断来了,中断控制器会将该中断源对应保存了中断处理程序地址寄存器中的值(VICVCTADDR)读到VICADDRESS,执行VICADDRESS中函数即可,清VICADDRESS。
通过按键实现key1点灯案例:
irq.h
//寄存器的定义略....
IRQ_EXTERN void irq_init(void);
irq.c
typedef void(*irq_func_t)(void);
//中断处理函数
void exint0_func(void)
{
uart0_puts("\n exint0_func");
led_on();
EXINT0PEND |= 1;//清中断
}
void c_irq_hadler(void)
{
uart0_puts("\n c_irq_hadler \n");
irq_func_t func;
func = (irq_func_t)VIC0ADDRESS;//从寄存器读取函数地址
if(func)
{
func();//调用函数
}
VIC0ADDRESS = 0;
}
void irq_init(void)
{
//中断源的配置
//1,关闭中断(还没有配置,为了避免无谓的错误,先关闭)
EXINT0MASK = 0xFFFFFFFF;
//2,清除中断标志
EXINT0PEND = 0xFFFFFFFF;
//3,配置GPH0_0为外部中断0
GPH0CFG |= 0xF;
//4,禁止该管脚的内部上下拉电阻
GPH0PUD &= ~0x3;//位清除
//5,中断触发方式为下降沿触发
EXINT0CON = (EXINT0CON & (~7))
//6,禁止滤波
EXINT0FLT = 0;
//中断控制器配置
//1,关中断
VIC0INTCLEAR |= 1;
// 2,TZICselect IRQ选择
TZICINTSELECT = 0;
//3,VICselect IRQ选择
VICSELECT = 0;
//4,VIC0ADDRESS = 0(一组只有一个)
VCI)ADDRESS = 0;
//5,VIC0VECTADDR 0 = func(一组有32个)
VIC0VECTADDR0 = (unsigned int)exint0_func;//函数名称的地转转换为int类型的数据存放到寄存器
//开中断
//1,开中断源的中断
EXINT0MASK &= ~1;
//2,开中断控制器的中断
VIC0INTENABLE |= 1;
//3,开启ARM核的中断控制
enable_irq();
}