Firefly开源社区

GPIO中断如何传递到应用程序

23

积分

0

威望

0

贡献

游客

积分
23
发表于 2017-11-30 17:50:05     
本帖最后由 Icefly 于 2017-12-15 18:01 编辑

朋友们好,我使用rk3399的板子学习GPIO驱动,跑了官网GPIO驱动的例子(http://wiki.t-firefly.com/index.php/Firefly-RK3399/GPIO),能够在内核log里看到相关的中断信息;
接着我想将该中断信息传递给上层应用程序,在应用程序里做出响应,不知道应该怎么做,新手上路请诸位多多指教。

从网上了解的的信息来看,有说用异步通信的,也有说使用input框架的,都看不太明白,如果能给个示例代码那最好啦。
参考网上的例子写了个用netlink实现用户空间和内核空间通信的例子,代码大致如下
gpio-firefly.c
  1. /*  * Driver for pwm demo on Firefly board.  *  * Copyright (C) 2016, Zhongshan T-chip Intelligent Technology Co.,ltd.  * Copyright 2006  JC.Lin  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU General Public License version 2 as  * published by the Free Software Foundation.  */
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>
  5. #include <linux/err.h>
  6. #include <linux/gpio.h>
  7. #include <linux/io.h>
  8. #include <linux/of.h>
  9. #include <linux/of_gpio.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/workqueue.h>

  13. #include <linux/types.h>
  14. #include <net/sock.h>
  15. #include <linux/netlink.h>

  16. /*
  17. #define NETLINK_TEST 16
  18. struct sock *nl_sk = NULL;
  19. EXPORT_SYMBOL_GPL(nl_sk);
  20. */
  21. #define NETLINK_USER 22
  22. #define USER_MSG (NETLINK_USER+1)
  23. #define USER_PORT 50
  24. static struct sock *netlinkfd = NULL;
  25. static void *netlinkdata = NULL;
  26. static int netlinkdatalen = 0;

  27. static struct workqueue_struct *queue=NULL;
  28. static struct work_struct my_wq;
  29. static void my_wq_func(struct work_struct *data);

  30. struct firefly_gpio_info
  31. {   
  32.     //struct device *dev;
  33.     //long firefly_param;
  34.     int firefly_gpio;
  35.     int gpio_enable_value;
  36.     int firefly_irq_gpio;     
  37.     int firefly_irq;     
  38.     int firefly_irq_mode;
  39. };

  40. /*
  41. void nl_data_ready(struct sk_buff *__skb)
  42. {
  43.     struct sk_buff *skb;
  44.     struct nlmsghdr *nlh;
  45.     u32 pid;
  46.     int rc;
  47.     int len = NLMSG_SPACE(1200);
  48.     char str[100];
  49.     printk("new_link: data is ready to read.\n");
  50.     skb = skb_get(__skb);
  51.     if(skb->len >= NLMSG_SPACE(0))
  52.     {
  53.         nlh = nlmsg_hdr(skb);
  54.         printk("net_link: recv %s.\n", (char *)NLMSG_DATA(nlh));
  55.         memcpy(str, NLMSG_DATA(nlh), sizeof(str));
  56.         pid = nlh->nlmsg_pid; //pid of sending process
  57.         printk("net_link: pid is %d\n", pid);
  58.         kfree_skb(skb);
  59.         skb = alloc_skb(len, GFP_ATOMIC);
  60.         if(!skb)        
  61.         {
  62.             printk(KERN_ERR "net_link: allocate failed.\n");
  63.             return;
  64.         }
  65.         nlh = nlmsg_put(skb, 0, 0, 0, 1200, 0);
  66.         NETLINK_CB(skb).pid = 0; //from kernel
  67.         memcpy(NLMSG_DATA(nlh), str, sizeof(str));
  68.         printk("net_link: going to send.\n");
  69.         rc = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
  70.         if(rc < 0)
  71.         {
  72.             printk(KERN_ERR "net_link: can not unicast skb (%d)\n", rc);
  73.         }
  74.         printk("net_link: send is ok.\n");
  75.     }
  76.     return;
  77. }

  78. static int test_netlink(void)
  79. {
  80.     nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 0, nl_data_ready, NULL, THIS_MODULE);
  81.     if(!nl_sk)
  82.     {
  83.         printk(KERN_ERR "net_link: Cannot create netlink socket.\n");
  84.         return -EIO;
  85.     }
  86.     printk("net_link: create socket ok.\n");
  87.     return 0;
  88. }
  89. */

  90. int send_msg(int8_t *pbuf, uint16_t len)
  91. {
  92.     struct sk_buff *nl_skb;
  93.     struct nlmsghdr *nlh;
  94.     int ret;
  95.     nl_skb = nlmsg_new(len, GFP_ATOMIC);
  96.     if(!nl_skb)
  97.     {
  98.         printk("netlink: netlink_alloc_skb error\n");
  99.         return -1;
  100.     }
  101.     nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);
  102.     if(nlh == NULL)
  103.     {
  104.         printk("netlink: nlmsg_put() error\n");
  105.         nlmsg_free(nl_skb);
  106.         return -1;
  107.     }
  108.     memcpy(nlmsg_data(nlh), pbuf, len);
  109.     ret = netlink_unicast(netlinkfd, nl_skb, USER_PORT, MSG_DONTWAIT);
  110.     return ret;
  111. }

  112. static void recv_cb(struct sk_buff *skb)
  113. {
  114.     struct nlmsghdr *nlh = NULL;
  115.     void *data = NULL;
  116.     printk("netlink: skb->len = %u\n", skb->len);
  117.     if(skb->len >= nlmsg_total_size(0))
  118.     {
  119.         nlh = nlmsg_hdr(skb);
  120.         data = NLMSG_DATA(nlh);
  121.         if(data)
  122.         {
  123.             printk("netlink: kernel receive data: %s\n", (int8_t *)data);
  124.             netlinkdata = data;
  125.             netlinkdatalen = nlmsg_len(nlh);
  126.             //send_msg(data, nlmsg_len(nlh));
  127.         }
  128.     }
  129. }

  130. struct netlink_kernel_cfg cfg =
  131. {
  132.     .input = recv_cb,
  133. };


  134. static int test_netlink(void)
  135. {
  136.     netlinkfd = netlink_kernel_create(&init_net, USER_MSG, &cfg);
  137.     if(!netlinkfd)
  138.     {
  139.         printk(KERN_ERR "netlink: can not create a netlink socket!\n");
  140.         return -1;
  141.     }
  142.     printk("netlink: create socket ok.\n");
  143.     return 0;
  144. }


  145. //static struct fasync_struct *gpio_irq_async;

  146. static void my_wq_func(struct work_struct *data)
  147. {
  148.     printk("Enter firefly gpio irq my_wq_func!\n");
  149.     //test_netlink();
  150.     if (netlinkdatalen > 0)
  151.     {
  152.         send_msg(netlinkdata, netlinkdatalen);
  153.         netlinkdatalen = 0;
  154.         printk("firefly netlink send_msg\n");
  155.     }
  156.     printk("Exit firefly gpio irq my_wq_func!\n");
  157. }

  158. static irqreturn_t firefly_gpio_irq(int irq, void *dev_id)
  159. {     
  160.     printk("Enter firefly gpio irq test program!\n");        
  161.     //kill_fasync(&gpio_irq_async, SIGIO,POLL_IN);
  162.     schedule_work(&my_wq);
  163.     return IRQ_HANDLED;
  164. }

  165. /*
  166. static int firefly_gpio_fasync(int fd, struct file *filp, int mode)
  167. {
  168.         //struct scull_pipe *dev = filp->private_data;

  169.         return fasync_helper(fd, filp, mode, &gpio_irq_async);
  170. }*/

  171. /*
  172. static ssize_t gpio_firefly_attr_show(struct device *dev, struct device_attribute *attr, char *buf)
  173. {
  174.     struct firefly_gpio_info *gpio_info = dev_get_drvdata(dev);
  175.     int len;
  176.     len = sprintf(buf, "%ld\n", gpio_info->firefly_param);
  177.     if (len < 0)
  178.     {
  179.         dev_err(dev, "firefly_gpio_info  gpio_firefly_attr_show: Invalid sprintf, len= %d\n", len);
  180.     }
  181.     return len;
  182. }

  183. static ssize_t gpio_firefly_attr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  184. {
  185.     struct firefly_gpio_info *gpio_info = dev_get_drvdata(dev);
  186.     int ret;
  187.     ret = kstrtol(buf, 10, &gpio_info->firefly_param);
  188.     if (ret != 0)
  189.     {
  190.         dev_err(dev, "firefly_gpio_info gpio_firefly_attr_store: kstrtol failed, ret= %d\n", ret);
  191.     }
  192.     return count;
  193. }

  194. static DEVICE_ATTR(firefly_param, S_IRUGO | S_IWUSR, gpio_firefly_attr_show, gpio_firefly_attr_store);

  195. static struct attribute *firefly_gpio_attrs[] =
  196. {
  197.     &dev_attr_firefly_param.attr,
  198.     NULL,
  199. };

  200. static struct attribute_group firefly_gpio_attr_group =
  201. {
  202.     .name = "firefly_gpio_info",
  203.     .attrs = firefly_gpio_attrs,
  204. };
  205. */

  206. static int firefly_gpio_probe(struct platform_device *pdev)
  207. {     
  208.     int ret;     
  209.     int gpio;     
  210.     //int error;
  211.     enum of_gpio_flags flag;     
  212.     struct firefly_gpio_info *gpio_info;     
  213.     struct device_node *firefly_gpio_node = pdev->dev.of_node;     
  214.     printk("Firefly GPIO Test Program Probe\n");
  215.        
  216.     gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct firefly_gpio_info *), GFP_KERNEL);        
  217.     if (!gpio_info)
  218.     {         
  219.         dev_err(&pdev->dev, "devm_kzalloc failed!\n");
  220.         return -ENOMEM;        
  221.     }     

  222.     /*
  223.     gpio_info->dev = &pdev->dev;
  224.     platform_set_drvdata(pdev, gpio_info);
  225.     */

  226.     gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio", 0, &flag);     
  227.     if (!gpio_is_valid(gpio))
  228.     {         
  229.         dev_err(&pdev->dev, "firefly-gpio: %d is invalid\n", gpio);         
  230.         return -ENODEV;     
  231.     }     
  232.     if (gpio_request(gpio, "firefly-gpio"))
  233.     {         
  234.         dev_err(&pdev->dev, "firefly-gpio: %d request failed!\n", gpio);         
  235.         gpio_free(gpio);         
  236.         return -ENODEV;     
  237.     }     
  238.     gpio_info->firefly_gpio = gpio;     
  239.     gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;     
  240.     gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);     
  241.     printk("Firefly gpio putout\n");   

  242.     /*
  243.     gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio1", 0, &flag);     
  244.     if (!gpio_is_valid(gpio))
  245.     {         
  246.         dev_err(&pdev->dev, "firefly-gpio1: %d is invalid\n", gpio);         
  247.         return -ENODEV;     
  248.     }     
  249.     if (gpio_request(gpio, "firefly-gpio1"))
  250.     {         
  251.         dev_err(&pdev->dev, "firefly-gpio1: %d request failed!\n", gpio);         
  252.         gpio_free(gpio);         
  253.         return -ENODEV;     
  254.     }     
  255.     gpio_info->firefly_gpio = gpio;     
  256.     gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;     
  257.     gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);     
  258.     printk("Firefly gpio1 putout\n");
  259.     */

  260.     gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-irq-gpio", 0, &flag);     
  261.     printk("firefly:the gpio:%d\n",gpio);     
  262.     if (!gpio_is_valid(gpio))
  263.     {         
  264.         dev_err(&pdev->dev, "firefly-irq-gpio: %d is invalid\n", gpio);         
  265.         return -ENODEV;     
  266.     }         
  267.     gpio_info->firefly_irq_gpio = gpio;     
  268.     gpio_info->firefly_irq_mode = flag;     
  269.     gpio_info->firefly_irq = gpio_to_irq(gpio_info->firefly_irq_gpio);     
  270.     if (gpio_info->firefly_irq)
  271.     {         
  272.         if (gpio_request(gpio, "firefly-irq-gpio"))
  273.         {            
  274.             dev_err(&pdev->dev, "firefly-irq-gpio: %d request failed!\n", gpio);            
  275.             gpio_free(gpio);            
  276.             return IRQ_NONE;         
  277.         }             
  278.         ret = request_irq(gpio_info->firefly_irq, firefly_gpio_irq, flag, "firefly-gpio", gpio_info);             
  279.         if (ret != 0)
  280.         {            
  281.             free_irq(gpio_info->firefly_irq, gpio_info);                     
  282.             dev_err(&pdev->dev, "firefly-gpio Failed to request IRQ: %d\n", ret);         
  283.         }
  284.         queue = create_singlethread_workqueue("firefly-irq-gpio");
  285.         if (!queue)
  286.         {
  287.             return -1;
  288.         }
  289.         INIT_WORK(&my_wq, my_wq_func);     
  290.     }
  291.     /*     
  292.         error = sysfs_create_group(&pdev->dev.kobj, &firefly_gpio_attr_group);
  293.         if (error) {
  294.                 dev_err(&pdev->dev, "Unable to export firefly param, error: %d\n",
  295.                         error);
  296.                 return error;
  297.         }
  298.     */
  299.     test_netlink();
  300.     return 0;
  301. }

  302. static int firefly_gpio_remove(struct platform_device *pdev)
  303. {
  304. //    sysfs_remove_group(&pdev->dev.kobj, &firefly_gpio_attr_group);
  305.     if (netlinkfd != NULL)
  306.     {
  307.         sock_release(netlinkfd->sk_socket);
  308.         printk(KERN_DEBUG "netlink exit\n");
  309.     }
  310.     return 0;
  311. }

  312. /*
  313. struct file_operations firefly_gpio_fops = {
  314.         .owner =        THIS_MODULE,
  315.         .llseek =        no_llseek,
  316.         .fasync =        firefly_gpio_fasync,
  317. };*/

  318. static struct of_device_id firefly_match_table[] =
  319. {        
  320.     { .compatible = "firefly,rk3399-gpio",},         {}, };
  321.     static struct platform_driver firefly_gpio_driver =
  322.     {        
  323.     .driver = {                
  324.     .name = "firefly-gpio",                
  325.     .owner = THIS_MODULE,                
  326.     .of_match_table = firefly_match_table,        
  327.     },        
  328.     .probe = firefly_gpio_probe,
  329.     .remove = firefly_gpio_remove,
  330. };

  331. static int firefly_gpio_init(void)
  332. {        
  333.     return platform_driver_register(&firefly_gpio_driver);
  334. }

  335. module_init(firefly_gpio_init);

  336. static void firefly_gpio_exit(void)
  337. {        
  338.     platform_driver_unregister(&firefly_gpio_driver);
  339. }

  340. module_exit(firefly_gpio_exit);

  341. MODULE_AUTHOR("linjc <service@t-firefly.com>");
  342. MODULE_DESCRIPTION("Firefly GPIO driver");
  343. MODULE_ALIAS("platform:firefly-gpio");
  344. MODULE_LICENSE("GPL");
复制代码

用户空间代码:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <string.h>
  5. #include <linux/netlink.h>
  6. #include <stdint.h>
  7. #include <unistd.h>
  8. #include <errno.h>

  9. #define NETLINK_USER 22
  10. #define USER_MSG (NETLINK_USER+1)
  11. #define MSG_LEN 100

  12. #define MAX_PLOAD 100

  13. struct _my_msg
  14. {
  15.         struct nlmsghdr hdr;
  16.         int8_t data[MSG_LEN];
  17. };

  18. int main(int argc, char **argv)
  19. {
  20.         char *data = "hello kernel";
  21.         struct sockaddr_nl local, dest_addr;
  22.         int skfd;
  23.         struct nlmsghdr *nlh = NULL;
  24.         struct _my_msg info;
  25.         int ret;
  26.         int socklen;
  27.         int recvcount = 0;
  28.         skfd = socket(AF_NETLINK, SOCK_RAW, USER_MSG);
  29.         if(skfd == -1)
  30.         {
  31.                 printf("create socket error... %s\n", strerror(errno));
  32.                 return -1;
  33.         }
  34.         memset(&local, 0, sizeof(local));
  35.         local.nl_family = AF_NETLINK;
  36.         local.nl_pid = 50;
  37.         local.nl_groups = 0;
  38.         if(bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0)
  39.         {
  40.                 printf("bind() error\n");
  41.                 close(skfd);
  42.                 return -1;
  43.         }
  44.         memset(&dest_addr, 0, sizeof(dest_addr));
  45.         dest_addr.nl_family = AF_NETLINK;
  46.         dest_addr.nl_pid = 0;
  47.         dest_addr.nl_groups = 0;
  48.         nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));
  49.         memset(nlh, 0, sizeof(struct nlmsghdr));
  50.         nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD);
  51.         nlh->nlmsg_flags = 0;
  52.         nlh->nlmsg_type = 0;
  53.         nlh->nlmsg_seq = 0;
  54.         nlh->nlmsg_pid = local.nl_pid;
  55.         memcpy(NLMSG_DATA(nlh), data, strlen(data));
  56.         while(1)
  57.         {
  58.         ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_nl));
  59.     if(!ret)
  60.     {
  61.         perror("sendto error1\n");
  62.         close(skfd);
  63.         exit(-1);
  64.     }
  65.     printf("wait kernel msg!\n");
  66. //    while(1)
  67. //    {
  68.     memset(&info, 0, sizeof(info));
  69.     socklen = sizeof(dest_addr);
  70.     ret = recvfrom(skfd, &info, sizeof(struct _my_msg), 0, (struct sockaddr *)&dest_addr, (socklen_t*)&socklen);
  71.     if(!ret)
  72.     {
  73.         perror("recv from kernel error\n");
  74.         close(skfd);
  75.         exit(-1);
  76.     }
  77.     printf("msg receive from kernel: %s, %d\n", info.data, recvcount++);
  78.     if (recvcount%2 == 0)
  79.     {
  80.         system("./light on");
  81.     }
  82.     else
  83.     {
  84.         system("./light off");
  85.     }
  86.     }
  87.     close(skfd);
  88.     free((void *)nlh);
  89.     return 0;
  90. }
复制代码


回复

使用道具 举报

46

积分

0

威望

0

贡献

游客

积分
46
发表于 2017-12-7 16:36:11     
顶一个
回复

使用道具 举报

23

积分

0

威望

0

贡献

游客

积分
23
发表于 2017-12-12 18:19:16     

额,谢谢朋友。对于这个问题你有没有什么建议。
回复

使用道具 举报

46

积分

0

威望

0

贡献

游客

积分
46
发表于 2017-12-14 14:46:46     
Icefly 发表于 2017-12-12 18:19
额,谢谢朋友。对于这个问题你有没有什么建议。

我也是新手,需求跟你差不多,目前也在研究,楼主有什么突破吗
回复

使用道具 举报

23

积分

0

威望

0

贡献

游客

积分
23
发表于 2017-12-14 18:39:11     
mengduo 发表于 2017-12-14 14:46
我也是新手,需求跟你差不多,目前也在研究,楼主有什么突破吗

握握手先,估计问的问题太基础了,所以都没人回答。最近这几天我研究了一下,我认为我想达到的目的是实现内核空间和用户空间的通信,搜了一下其方式又很多种,我本来想尝试用ioctl或者fasync,但由于找不到platform driver里file_operations,所以我又尝试了sysfs和netlink的方式,sysfs尝试失败,原因不明。。;但netlink的方式成功了,回来我把代码贴上来,看看对你有没有帮助。
回复

使用道具 举报

3

积分

0

威望

0

贡献

游客

积分
3
发表于 2017-12-25 18:08:38     
必须要写内核代码吗?
Linux原生的 sys/class/gpio/gpio??/edge 机制不能用吗?
回复

使用道具 举报

22

积分

0

威望

0

贡献

技术小白

积分
22
发表于 2018-5-17 10:40:18     
第一个想到的是用IOCTL,然后一直读,有中断来了就返回,请问博主如何编译程序,我现在写了个hello world 用aarch64-。。。。。。
这个编译器编译不过
回复

使用道具 举报

63

积分

0

威望

0

贡献

技术小白

积分
63
发表于 2019-4-17 13:17:28     
我顶一个,赞楼主
回复

使用道具 举报

50

积分

0

威望

0

贡献

技术小白

积分
50
发表于 2019-8-24 13:21:31     
安卓的话要往应用层传数据就用JNI,这个android.mk用ndk编so包,然后给Java native调用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表