Linux Kernel Driver hello world 驱动续
程序员文章站
2024-02-29 16:43:10
...
介绍
不干嘛,就注册一个中断号,看一眼,中断被触发一次,我们就打印一条日志。
代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
MODULE_DESCRIPTION("Frocheng: Driver for DEMO!");
MODULE_AUTHOR("Frodo Cheng");
MODULE_LICENSE("GPL");
MODULE_VERSION("V0.0.1");
#define HELLO_IRQ (36U)
static char* dev = "hello";
static irqreturn_t irq_handle_cb(int irq, void * arg)
{
printk("===[frocheng]===[%s]===[%s]===[%d]===[irq: %d]===\n",__FILE__, __func__, __LINE__, irq);
return IRQ_NONE;
}
static int __init hello_init(void)
{
printk("===[frocheng]===[%s]===[%s]===[%d]===[Hello !]===\n",__FILE__, __func__, __LINE__);
irqreturn_t ret;
ret = request_irq(HELLO_IRQ, irq_handle_cb, IRQF_SHARED, "hello", (void*)dev);
return 0;
}
static void __exit hello_exit(void)
{
free_irq(HELLO_IRQ, (void*)dev);
printk("===[frocheng]===[%s]===[%s]===[%d]===[Bye bye...]===\n",__FILE__, __func__, __LINE__);
}
module_init(hello_init);
module_exit(hello_exit);
代码写完了,看似很简单,但是,需要特别说明几点:
第一:中断号,这是最重要的,牵涉到我们能不能有效的看到我们的实验效果。
cat /proc/interrupts
最左边一列,就是中断号,中间的表示该中断在各个CPU上已经触发的次数,我们挑选一个多的。所以选中了36.后面东西,暂且不用管。
第二,中断处理函数
这个callback 函数其实是有问题的,在于耗时太长。因为其中有prink,这是一个io操作,现在实验,所以无所谓,后续我们根据linux系统提供的技术,去做优化。
返回值, irqreturn_t:
是个 enum,我们其实不能阻断这个中断的处理,而是旁路查看,所以,要小心,中断处理函数的返回值 IRQ_NONE,表示,我们并没有真正处理这个中断。
第三:注册中断处理函数
flags的取值:IRQF_SHARED,如下图的定义,这个中断号,我们跟其他设备去共享 。
第四,dev参数
如论是注册函数,还是 free 函数,dev 参数,不要空,因为,我们实验的驱动模块,不仅会加载,还会卸载。为了保证不对其他的模块有影响,我们需要精准的定义dev,然后,注册以及free 时,要传入同一个 dev指针。大家可以自己试试两个函数的dev 都给NULL会是什么效果。
编译,以及加载卸载,我们参考前面的博客即可。
结果
我们成功的看到了我们的中断处理函数,被调用了,我们的驱动成功的响应了对应的中断。