欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

Linux Kernel Driver hello world 驱动续

最左边一列,就是中断号,中间的表示该中断在各个CPU上已经触发的次数,我们挑选一个多的。所以选中了36.后面东西,暂且不用管。

第二,中断处理函数

Linux Kernel Driver hello world 驱动续

这个callback 函数其实是有问题的,在于耗时太长。因为其中有prink,这是一个io操作,现在实验,所以无所谓,后续我们根据linux系统提供的技术,去做优化。

返回值, irqreturn_t:

Linux Kernel Driver hello world 驱动续

是个 enum,我们其实不能阻断这个中断的处理,而是旁路查看,所以,要小心,中断处理函数的返回值 IRQ_NONE,表示,我们并没有真正处理这个中断。

第三:注册中断处理函数

flags的取值:IRQF_SHARED,如下图的定义,这个中断号,我们跟其他设备去共享 。

Linux Kernel Driver hello world 驱动续

第四,dev参数

如论是注册函数,还是 free 函数,dev 参数,不要空,因为,我们实验的驱动模块,不仅会加载,还会卸载。为了保证不对其他的模块有影响,我们需要精准的定义dev,然后,注册以及free 时,要传入同一个 dev指针。大家可以自己试试两个函数的dev 都给NULL会是什么效果。

编译,以及加载卸载,我们参考前面的博客即可。

结果

Linux Kernel Driver hello world 驱动续

我们成功的看到了我们的中断处理函数,被调用了,我们的驱动成功的响应了对应的中断。 

相关标签: linux 嵌入式