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

来源:互联网 发布:js 淘宝左侧 分类导航 编辑:程序博客网 时间:2024/06/05 18:13

原实现底半部的方法参考: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");
原创粉丝点击