1.回顾裸板中按键中断异常是如何处理的
中断触发要做的三级配置
—>中断源级
------>配置中断的检测模式
------>中断使能
—>中断控制器
------>中断的优先级
------>中断使能
------>中断信号可以发往核
------>中断是以IRQ/FIQ上报
—>ARMcore级
------>中断使能
异常产生后硬件自动做的4件事
—>1)备份CPRS
—>2)修改CPRS
—>3)保存返回地址到LR
—>4)PC=vector_base + 0x18
vector_tab:
…
…
ldr pc, _irq
…
asm_do_irq:
保护现场
bl c_do_irq
恢复现场
c_do_irq:
判断哪个硬件触发的中断
调用对应硬件的中断处理函数hardware_isr
清除中断源、中断控制器级的pending
2.Linux系统中中断异常的处理过程和裸板中是一致的
但是Linux系统中已经将其中绝大部分代码实现完毕了(Linux中断子系统)
驱动开发人员需要完成:
1)检测模式的配置
2)hardware_isr
内核中提供了两个函数,用于驱动编程工组和Linux中断子系统的代码结合起来
#include <linux/interrupt.h>
#include <mach/platform.h>
static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
void free_irq(unsigned int irq, void *dev_id)
作用:注册中断服务程序,约定irq对应的硬件什么情况下产生中断信号,约定irq号硬件产生了中断 内核应该调用handler函数,约定内核在调用handler函数时传递的第二个参数值是dev
irq:中断号 s5p6818_irq.h
handler,具体硬件的中断服务程序(hardware_isr),其数据类型是irqreturn_t(*)(int,void *);
flags,常用取值
IRQF_TRIGGER_RISING
IRQF_TRIGGER_FALLING
下降沿触发中断
IRQF_TRIGGER_HIGH
IRQF_TRIGGER_LOW
name,名称
dev,用于指定当内核调用handler函数时传递给handler函数的第二个参数值,注销时需保持一致
返回值,0:注册成功 非0:注册失败
实验步骤:
电路原理图
----只关注SW6是否产生了按下动作, 下降沿触发中断
vi btn_drv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <mach/platform.h>
MODULE_LICENSE("GPL");
/*
*irq, 中断号
*dev, 注册时给定的最后一个参数
* */
irqreturn_t btn_isr(int irq, void *dev)
{
printk("<2>" "enter %s\n", __func__);
/*中断出来完毕*/
return IRQ_HANDLED;
}
int __init btn_drv_init(void)
{
if(request_irq(IRQ_GPIO_A_START+28, btn_isr, IRQF_TRIGGER_FALLING,"up", NULL))
{
printk("<2>" "request_irq failed!");
return -EAGAIN;
}
return 0;
}
void __exit btn_drv_exit(void)
{
free_irq(IRQ_GPIO_A_START+28, NULL);
}
module_init(btn_drv_init);
module_exit(btn_drv_exit);
make #结果复制到开发板
insmod btn_drv.ko #在开发板执行
报错注册中断失败
可能原因:
1)如果xxx_init函数返回非0 会使得模块安装失败
2)为什么会注册中断失败呢?
因为内核中自带的按键驱动程序,
在内核启动过程就内核注册了 IRQ_GPIO_A_START+28 中断源对应的中断服务程序
我们在安装btn_drv.ko 又向内核注册IRQ_GPIO_A_START+28对应的中断服务程序 注册不成功
3)解决注册中断不成功的方法:将内核中自带的按键驱动裁剪掉
#解决办法:
cd kernel/
make menuconfig
Device Drivers --->
Input device support --->
[*] Keyboards --->
< > SLsiAP push Keypad support
make uImage
cp arch/arm/boot/uImage /tftpboot
#重启开发板
insmod btn_drv.ko #安装中断驱动
cat /proc/interrupts #查看中断
...
中断号 中断产生的次数 中断来源模块 name
134: 0 GPIO up
...
可以看出中断的name = up 的相关信息
练习:
注册4个按键中断服务程序
按下四个按键打印不同的信息出来
up/down/left/right key is pressed!