首页 > 其他 > 详细

中断下文之tasklet

时间:2021-05-14 15:40:39      阅读:34      评论:0      收藏:0      [点我收藏+]

linux kernel version:4.4.38

硬件平台:exynos4412-tiny4412

参考链接:https://www.cnblogs.com/ethandlwang/p/14759735.html

基于之前按键点灯程序,我引入了中断下文tasklet机制。

在中断处理程序中处理对紧急事务,使用tasklet来处理触发中断后需要处理得事务中不紧急的事情

  1 #include <linux/err.h>
  2 #include <linux/gpio.h>
  3 #include <linux/fs.h>
  4 #include <linux/gpio/consumer.h>
  5 #include <linux/kernel.h>
  6 #include <linux/leds.h>
  7 #include <linux/module.h>
  8 #include <linux/of.h>
  9 #include <linux/of_gpio.h>
 10 #include <linux/of_irq.h>
 11 #include <linux/platform_device.h>
 12 #include <linux/property.h>
 13 #include <linux/slab.h>
 14 #include <linux/workqueue.h>
 15 #include <linux/interrupt.h>
 16 #include <linux/acpi.h>
 17 
 18 static void my_task_handle(unsigned long data);
 19 static struct gpio_desc    *gpiod;
 20 static DECLARE_TASKLET(my_task, my_task_handle, 0);
 21 
 22 static void my_task_handle(unsigned long data)
 23 {
 24     printk(KERN_ALERT "my_task_handle data=%d\n", data);
 25     return;
 26 }
 27 
 28 static ssize_t myled_status_show(struct device *dev,
 29                      struct device_attribute *attr, char *buf)
 30 {
 31     int level = gpiod_get_value(gpiod);
 32     printk(KERN_ALERT "%s %d level=%d\n", __FUNCTION__, __LINE__, level);
 33     return 0;
 34 
 35 }
 36 
 37 static ssize_t myled_status_store(struct device *dev,
 38                    struct device_attribute *attr,
 39                    const char *buf, size_t len)
 40 {
 41     printk(KERN_ALERT "%s %d buf=%s len=%d\n", __FUNCTION__, __LINE__, buf, len);
 42     int level = 1;
 43     if(len >= 2){
 44         if(buf[0] == 0){
 45             level = 0;
 46         } 
 47     }
 48     gpiod_set_value(gpiod, level);
 49     return len;
 50 }
 51 
 52 static DEVICE_ATTR_RW(myled_status);
 53 
 54 static struct attribute* myled_status_attrs[] = {
 55     &dev_attr_myled_status.attr,
 56     NULL
 57 };
 58 
 59 static const struct attribute_group myled_group = {
 60     .attrs        = myled_status_attrs,
 61 };
 62 
 63 static irqreturn_t my_irq(int irqno, void *dev_id)
 64 {
 65     int level = gpiod_get_value(gpiod);
 66     tasklet_schedule(&my_task);
 67     printk(KERN_ALERT "%s %d irqno=%d level=%d\n", __FUNCTION__, __LINE__, irqno, level);
 68     gpiod_set_value(gpiod, !level);
 69     return IRQ_HANDLED;
 70 }
 71 
 72 static int hello_probe(struct platform_device *pdev)
 73 {
 74     int error = 0;
 75     unsigned int irq;
 76     int ret;
 77     struct device_node* np = pdev->dev.of_node;
 78 
 79     if(np == NULL){
 80         printk(KERN_ALERT "%s %d of_node is NULL\n", __FUNCTION__, __LINE__);
 81         goto NO_DEV_OF_NODE;
 82     }
 83 
 84 
 85     irq = platform_get_irq(pdev, 0);
 86     if(irq < 0){
 87         printk(KERN_ALERT "platform_get_irq fail!!! irq = %d\n", irq);
 88         goto PLATFORM_GET_IRQ_FAIL;
 89     }
 90     
 91     ret = devm_request_irq(&pdev->dev, irq, my_irq, 0, dev_name(&pdev->dev), NULL);
 92     if(ret){
 93         printk(KERN_ALERT "devm_request_irq fail!!! ret = %d\n", ret);
 94         goto REQUEST_IRQ_FAIL;
 95     }
 96     
 97     gpiod = devm_gpiod_get_optional(&pdev->dev, "key1", GPIOD_OUT_LOW);
 98     if(gpiod == NULL){
 99         printk(KERN_ALERT "devm_gpiod_get_optional fail!!!\n");
100         goto GPIOD_GET_FAIL;
101     }
102  
103     ret = sysfs_create_group(&pdev->dev.kobj, &myled_group);
104     if(ret){
105         printk(KERN_ALERT "sysfs_create_group fail!!! ret=%d\n", ret);
106         goto SYS_CREATE_GTOUP_FAIL;
107     }
108 
109 NO_DEV_OF_NODE:
110 PLATFORM_GET_IRQ_FAIL:
111 REQUEST_IRQ_FAIL:
112 GPIOD_GET_FAIL:
113 SYS_CREATE_GTOUP_FAIL:
114     tasklet_kill(&my_task);
115 
116     printk(KERN_ALERT "%s %d success===\n", __FUNCTION__, __LINE__);
117     return error;
118 }
119 
120 static int hello_remove(struct platform_device *pdev)
121 {
122     sysfs_remove_group(&pdev->dev.kobj,&myled_group);
123     tasklet_kill(&my_task);
124     printk(KERN_ALERT "%s %d success===\n", __FUNCTION__, __LINE__);
125     return 0;
126 
127 }
128 
129 static void hello_shutdown(struct platform_device *pdev)
130 {
131     printk(KERN_ALERT "%s %d success===\n", __FUNCTION__, __LINE__);
132 }
133 
134 static struct of_device_id of_platform_hello_match[] = {
135     { .compatible = "interrupt-keys",},
136     { },
137 };
138 MODULE_DEVICE_TABLE(of, of_platform_hello_match);
139 
140 static struct platform_driver platform_hello_driver = {
141     .probe        = hello_probe,
142     .remove        = hello_remove,
143     .shutdown    = hello_shutdown,
144     .driver        = {
145         .name    = "my_keys",
146         //.owner  = THIS_MODULE,
147         .of_match_table = of_platform_hello_match,
148     },
149 };
150 
151 module_platform_driver(platform_hello_driver);
152 MODULE_AUTHOR("EthanDL");
153 MODULE_DESCRIPTION("platform hello");
154 MODULE_LICENSE("GPL");

20行:以静态的方式申请和初始化tasklet,my_task_handle为处理函数,0为my_task_handle参数

66行:在中断处理函数中调用tasklet_schedule,在触发中断后调用,在中断处理函数执行完毕后的一个很小的时间间隔,执行my_task_handle,使中断处理函数迅速返回。my_task_handle随后参与调度被cpu执行。

123行:在确定不使用tasklet时,将其注销。

实验结果:

技术分享图片

 

 在按下按键后,触发中断,执行中断处理函数,67行被先打印,虽然tasklet_schedule先被调用,但是my_task_handle中的打印会在最后打印,这就是中断下文的效果。

 

中断下文之tasklet

原文:https://www.cnblogs.com/ethandlwang/p/14767801.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!