Linux设备驱动之中断---thread使用示例

前几篇文章介绍了中断的原理、基本框架、上下部使用之工作队列,这篇文章介绍另一种方法—线程化中断 thread.

我使用的硬件是imx6q,原理都一样。原来的beep引脚是output模式,电路上把它改成了按键。

下面程序的文件名为interrupt_threaded.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/gpio.h>

#include <asm/io.h>
#include <asm/irq.h>



#define IMX_GPIO_NR(bank, nr)               (((bank) - 1) * 32 + (nr)) //平台相关,不用关心
#define CYNO_GPIO_BEEP_NUM                  IMX_GPIO_NR(6,10)  //获得gpio端口

//定义gpio引脚的结构体
static struct pin_desc{
    int irq;
    unsigned char *name;
    unsigned int pin;
};

//实例化一个具体的引脚
static struct pin_desc beep_desc = {
    0,
    "beep_num",
    CYNO_GPIO_BEEP_NUM
};

//上半部处理代码
static irqreturn_t beep_interrupt_top_handler(int irq, void *dev_id)
{
    printk(KERN_INFO "%s\n", __func__);
    return IRQ_WAKE_THREAD ;     //只要返回 IRQ_WAKE_THREAD, 系统默认开始调用下半部的处理代码,所以一定要返回这个flag
}

//下半部处理代码
static irqreturn_t beep_interrupt_bottom_handler(int irq, void *dev_id)
{
    //私有数据示例
    struct pin_desc *dev_beep = dev_id;

    printk(KERN_INFO "%s\n", __func__);
    printk(KERN_INFO "%s : dev_beep->irq = %d\n", __func__, dev_beep->irq);
    printk(KERN_INFO "%s : dev_beep->name = %s\n", __func__, dev_beep->name);
    printk(KERN_INFO "%s : dev_beep->pin = %d\n", __func__, dev_beep->pin);
    return IRQ_HANDLED;
}

//模块初始化代码,驱动安装时被调用
static int interrupt_threaded_init(void)
{
    int ret;

    printk(KERN_INFO "%s\n", __func__);

    //申请对应的gpio
    if(gpio_request(beep_desc.pin ,beep_desc.name)){
        printk(KERN_ERR "%s : request gpio %d error\n", __func__, beep_desc.pin);
        goto err_gpio_request;
    }
    //设置gpio为输入
    gpio_direction_input(beep_desc.pin);
    //动态获取irq端口号
    beep_desc.irq = gpio_to_irq(beep_desc.pin);
    printk(KERN_INFO "%s : the irq num is %d\n", __func__, beep_desc.irq);
    //申请线程化中断
    ret = request_threaded_irq(beep_desc.irq, beep_interrupt_top_handler, beep_interrupt_bottom_handler , IRQF_ONESHOT | IRQF_TRIGGER_FALLING , beep_desc.name , &beep_desc);       //一定要添加IRQF_ONESHOT标志位,该标志位表述线程化中断执行结束以后再次打开本中断,开始执行时默认关闭本中断
    if(ret){
        printk(KERN_ERR "%s : request_irq is error\n", __func__);
        goto err_request_irq;
    }
    printk("%s : init end\n", __func__);

    return 0;

//处理错误
err_request_irq:
    free_irq(beep_desc.irq, &beep_desc);

err_gpio_request:
    gpio_free(beep_desc.pin);
    return -1;
}

//驱动卸载调用代码
static void interrupt_threaded_exit(void)
{
    printk("%s\n", __func__);
    free_irq(beep_desc.irq, &beep_desc);
    gpio_free(beep_desc.pin);
}

module_init(interrupt_threaded_init);
module_exit(interrupt_threaded_exit);

MODULE_AUTHOR("xiaolei");
MODULE_DESCRIPTION("interrupt threaded use");
MODULE_LICENSE("GPL");

线程化中断中要注意IRQF_ONESHOT标志位的使用,实践过程中,如果不添加此标志位,编译会报错。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
rt-thread是一个实时嵌入式操作系统,它提供了设备驱动开发的指南,帮助开发者更好地编写设备驱动程序。 首先,在rt-thread中进行设备驱动开发之前,需要了解rt-thread设备驱动框架,包括设备驱动的结构、设备驱动的注册和使用方法等。同时,开发者也需要了解rt-thread设备模型,包括设备设备驱动设备节点的概念,以便更好地理解设备驱动的开发流程。 其次,在编写设备驱动程序时,需要遵循rt-thread设备驱动编程规范,包括设备驱动的命名规范、接口函数的实现规范等。同时,还需要了解不同类型设备的特点和使用方法,以便更好地编写对应的设备驱动程序。 另外,rt-thread提供了丰富的设备驱动接口和函数,开发者可以根据需求选择合适的接口和函数进行设备驱动的开发。在编写设备驱动程序时,还需要注意设备驱动的稳定性和可靠性,及时处理错误和异常情况,以提高设备驱动程序的质量和可靠性。 最后,在设备驱动程序开发完成后,还需要进行设备驱动的测试和调试工作,确保设备驱动程序能够正常工作并符合需求。同时,还需要关注设备驱动程序的性能和优工作,以提高设备驱动程序的效率和性能。 总之,rt-thread设备驱动开发指南提供了设备驱动开发的规范和方法,帮助开发者更好地编写设备驱动程序,并最终实现嵌入式系统的稳定和可靠运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值