13 linux内核里实现中断底半部处理的新方法

原实现底半部的方法参考:http://blog.csdn.net/jklinux/article/details/73550804

现内核提供了新的中断请求函数,这个中断请求函数用于指定中断号为irq的中断顶半部和底半部的处理, 底半部是由内核线程来实现处理的(此底半部里可以作休眠的处理).
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
             irq_handler_t thread_fn, unsigned long irqflags,
             const char *devname, void *dev_id);

参数irq指定中断号. handler用于指定中断的顶半部处理函数地址, 如果为NULL而thread_fn不为NULL, 则系统会安排一个默认的处理函数. thread_fn用于指定在线程里中断底半部处理函数地址.

如果handler和thread_fn都分别指定了函数地址,则handler指向的处理函数的返回值应为IRQ_WAKE_THREAD, 它可以在顶半部处理函数完成后唤醒底半部线程处理thread_fn指向的函数.
当handler为NULL而thread_fn不为NULL时, irqflags标志需要包含有IRQF_ONESHOT(不可嵌套执行底半部的中断处理函数).

devname与创建出来的底半部线程名有关,线程名为:"irq/中断号-devname".

dev_id用于提供handler和thread_fn指向的函数的(void *)参数.

请求中断成功返回0, 失败会返回相应的错误码.

如实现一个按键中断的中断底半部处理:

/* mydrv.c */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/delay.h>

irqreturn_t irqbh_func(int irqno, void *arg)
{
    msleep(1000);
    printk("irqbh  irqbh\n");
    return IRQ_HANDLED;
}

int myprobe(struct platform_device *pdev)
{
    struct gpio_desc *gpiod = devm_gpiod_get(&pdev->dev, "btn", GPIOD_IN);
    int ret;    

    if (IS_ERR(gpiod))
    {
        printk("gpiod get failed\n");
        return -ENODEV;
    }

    ret = devm_request_threaded_irq(&pdev->dev, gpiod_to_irq(gpiod), NULL, irqbh_func,  IRQF_TRIGGER_FALLING|IRQF_ONESHOT, pdev->name, gpiod);
    if (ret < 0)
        goto err0;

    platform_set_drvdata(pdev, gpiod);
    printk("probe done\n");
    return 0;
err0:
    devm_gpiod_put(&pdev->dev, gpiod);
    return ret;

}

int myremove(struct platform_device *pdev)
{
    struct gpio_desc *gpiod = platform_get_drvdata(pdev);

    devm_free_irq(&pdev->dev, gpiod_to_irq(gpiod), gpiod);
    devm_gpiod_put(&pdev->dev, gpiod);
    printk("in myremove\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "mykeys"},
    {},
};

struct platform_driver mydrv = {
    .probe = myprobe,
    .remove = myremove,

    .driver = {
        .owner = THIS_MODULE,
        .name = "mydrv" ,

        .of_match_table = ids,
    },
};

module_platform_driver(mydrv);
MODULE_LICENSE("GPL");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值