因为飞凌开发板自己在内核里面集成了矩阵键盘的驱动,所以要用按键做实验必须先禁用之前的驱动模块,否则的话无法注册中断,去查看free_irq的代码(在kernel/irq/manage.c中),可以发现,出现这个Trying to free already-free IRQ 101 告警的原因是 存在该中断号对应的中断描述符desc ,而相印的中断服务程序却不存在。 说明有驱动程序占用了该中断号。 因而,我们要去掉这个驱动程序,方法:make menuconfig->Device Drivers->input device support->Key Boards->GPIO Buttons 去掉前面的*,即不选该项即可。
实验方法,加载了内核之后,可以通过使用exec 5<dev/led来执行内核中的open函数,然后按住按键,使用dmesg可以查看相关的执行irq打印信息。注意查看cat /proc/interrupt来知道是否注册进入了中断中。
最后可以运用 exec 5<&- 解除驱动程序被使用的状态 然后卸载驱动程序。
重新编译内核,就好了。
下面是简单的驱动程序
/*头文件的选取可以参照内核中其他驱动程序的实例*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/irqflags.h>
#include <linux/irqreturn.h>
#include <linux/irqnr.h>
#include <linux/interrupt.h>
static ssize_t third_driver_write(struct file *file, const char __user * buf
, size_t count, loff_t * ppos)
{
return 0;
}
static int major;
static struct class *third_driver_class;
static struct device *third_driver_device;
static irqreturn_t key_pressed(int irq, void *dev_id) /*这是中断处理函数 只是打印一些语句*/
{
printk(KERN_INFO "irq = %d\r\n",irq);
printk(KERN_INFO " interrupt is invoked\r\n");
return IRQ_HANDLED;
}
static int third_driver_open(struct inode *inode, struct file *file) /*open中申请中断 打印出中断号*/
{
int i;
i = request_irq(IRQ_EINT(0),key_pressed,IRQF_TRIGGER_RISING , "S10", 1);
printk(KERN_INFO " i = %d\r\n", i);
return 0;
}
static ssize_t third_driver_read(struct file *file, char __user *buf, size_t
count, loff_t *ppos)
{
return 0;
}
static struct file_operations third_driver_fops = {
.owner = THIS_MODULE,
.read = third_driver_read,
.open = third_driver_open,
.write = third_driver_write,
};
static int third_driver_init(void)
{
major = register_chrdev(0, "third_driver", &third_driver_fops); /*注册*/
third_driver_class = class_create(THIS_MODULE, "third_driver"); /*创建类*/
third_driver_device = device_create(third_driver_class, NULL, MKDEV(
major, 0), NULL, "led"); /*在类下创建设备*/
printk(KERN_INFO "init\r\n");
return 0;
}
static void third_driver_exit(void)
{
printk(KERN_INFO "exit\r\n");
<span style="white-space:pre"> </span> free_irq(IRQ_EINT(0),1); /*先释放中断 然后依次 释放主设备号 设备和类*/
unregister_chrdev(major, "third_driver");
device_unregister(third_driver_device);
<span style="white-space:pre"> </span> class_destroy(third_driver_class);
}
module_init(third_driver_init);
module_exit(third_driver_exit);
MODULE_LICENSE("GPL");
实验方法,加载了内核之后,可以通过使用exec 5<dev/led来执行内核中的open函数,然后按住按键,使用dmesg可以查看相关的执行irq打印信息。注意查看cat /proc/interrupt来知道是否注册进入了中断中。
最后可以运用 exec 5<&- 解除驱动程序被使用的状态 然后卸载驱动程序。