CubieBoard中文论坛

 找回密码
 立即注册
搜索
热搜: unable
查看: 15935|回复: 15

Cubiebaord Linux 按键设备驱动(中断)

[复制链接]
发表于 2014-11-5 10:16:10 | 显示全部楼层 |阅读模式
本帖最后由 sunbeyond 于 2014-11-7 22:06 编辑

Cubiebaord 按键设备驱动(中断)
根据按键原理。本例子让 PI11 口 pin 脚接地模拟按键按下。只需要有根电线就行不要真正的按键。

说明:
gpio_request(unsigned gpio, const char *label)第一个参数 gpio 标号是如何获取。是根据
script.fex 中的 gpio_para 中子键 gpio_pin_1,gpio_pin_2,gpio_pin_3....对应的顺序 GPIO 标号依次是
1,2,3。

1 首先修改 scipt.fex 配置,这里以 PI11 作为按键中断口。对应的 gpio 标号原理跟上面讲的一样。
可知此处对应的标号也为 1。
[gpio_para]
gpio_used = 1
gpio_num = 2
gpio_pin_1 = portI11<0><1><default><default> ------》 PH11 对应 GPIO 标号 num = 1
gpio_pin_2 = portH21<1><default><default><1>
2 驱动代码:(红色部分为 GPIO 中断使用重点)
  1. button_drv.c
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/device.h>
  5. #include <linux/cdev.h>
  6. #include <linux/uaccess.h>
  7. #include <linux/interrupt.h>
  8. #include <linux/wait.h>
  9. #include <asm/io.h>
  10. #include <linux/irq.h>
  11. #include <asm/irq.h>
  12. #include <mach/irqs.h>
  13. #include <plat/sys_config.h>
  14. #include <mach/system.h>
  15. #include <linux/slab.h>
  16. #include <linux/gpio.h>
  17. #include <linux/init.h>
  18. #include <linux/fs.h>
  19. #include <asm/atomic.h>
  20. #include <linux/kthread.h>
  21. //分配 cdev
  22. struct cdev btn_cdev;
  23. wait_queue_head_t btn_wq; //分配等待队列头
  24. Copyright © Cubietech Limited. All right reserved  Website: http://cubieboard.org
  25. E-mail: s upport@cubiete ch.com
  26. //主设备号
  27. static int major;
  28. //设备类
  29. static struct class *cls;
  30. //按键操作标志
  31. static int is_press; // 1:按键操作 0:无按键操作
  32. static unsigned char key_val;
  33. //按按键按下次数
  34. int press_num = 1;
  35. //GPIO 标号,非常重要,通过 script.fex 中的 gpio_para 配置顺序。从上往下对应的 gpio 标号依次是
  36. 1,2,3......
  37. int num = 1;
  38. //中断号
  39. int irq ;
  40. static int button_open(struct inode *inode,
  41. struct file *file)
  42. {
  43. return 0;
  44. }
  45. static int button_close(struct inode *inode,
  46. struct file *file)
  47. {
  48. return 0;
  49. }
  50. static ssize_t button_read(struct file *file,
  51. char __user *buf,
  52. size_t count,
  53. loff_t *ppos)
  54. {
  55. /*.判断按键是否有操作,如果有,进行读取
  56. 键值,然后上报给用户,如果没有操作,
  57. 进程休眠
  58. */
  59. wait_event_interruptible(btn_wq, is_press != 0);
  60. is_press = 0;
  61. /*3.上报键值*/
  62. copy_to_user(buf, &key_val, sizeof(key_val));
  63. return count;
  64. }
  65. //设备的操作集合
  66. static struct file_operations btn_fops = {
  67. .owner = THIS_MODULE,
  68. .open = button_open,
  69. Copyright © Cubietech Limited. All right reserved  Website: http://cubieboard.org
  70. E-mail: s upport@cubiete ch.com
  71. .release = button_close,
  72. .read = button_read
  73. };
  74. static irqreturn_t button_isr(int irq,
  75. void *dev_id)
  76. {
  77. unsigned long status;
  78. /*1. 获取按键状态*/
  79. status = gpio_get_value(num);
  80. /*2. 更新按键键值 key_val*/
  81. if (status == 1) {
  82. //松开
  83. key_val = 0x50;
  84. } else if (status == 0)
  85. //按下
  86. key_val = 0x51;
  87. /*3. 唤醒休眠的进程*/
  88. wake_up_interruptible(&btn_wq);
  89. is_press = 1;
  90. return IRQ_HANDLED;
  91. }
  92. static int button_init(void)
  93. {
  94. dev_t dev_id;
  95. /*1.申请设备号*/
  96. if (major) {
  97. dev_id = MKDEV(major, 0);
  98. register_chrdev_region(dev_id, 1, "button");
  99. } else {
  100. alloc_chrdev_region(&dev_id, 0, 1, "button");
  101. major = MAJOR(dev_id);
  102. }
  103. /*2.分配初始化 cdev*/
  104. /*2.2 初始化 cdev*/
  105. cdev_init(&btn_cdev, &btn_fops);
  106. //初始化等待队列头
  107. init_waitqueue_head(&btn_wq);
  108. /*3.注册 cdev*/
  109. cdev_add(&btn_cdev, dev_id, 1);
  110. /*4.自动创建设备节点*/
  111. Copyright © Cubietech Limited. All right reserved  Website: http://cubieboard.org
  112. E-mail: s upport@cubiete ch.com
  113. cls = class_create(THIS_MODULE, "button");
  114. device_create(cls, NULL, dev_id, NULL, "button");
  115. /*5.申请 GPIO 资源*/
  116. if (gpio_request(num,"gpio_pin")){
  117. printk("request gpio error\n");
  118. }
  119. /*6.获取中断号*/
  120. irq = gpio_to_irq(num);
  121. /*7 注册中断*/
  122. int error = request_irq(irq,button_isr,IRQF_TRIGGER_FALLING|
  123. IRQF_TRIGGER_RISING,"key_1",&press_num);
  124. if(error){
  125. printk("request irq error\n");
  126. }
  127. return 0;
  128. }
  129. static void button_exit(void)
  130. {
  131. dev_t dev_id = MKDEV(major, 0);
  132. /*释放中断*/
  133. /*释放 GPIO 资源*/
  134. free_irq(irq, &press_num);
  135. gpio_free(num);
  136. /*删除设备节点*/
  137. device_destroy(cls, dev_id);
  138. class_destroy(cls);
  139. /*删除 cdev*/
  140. cdev_del(&btn_cdev);
  141. /*释放设备号*/
  142. unregister_chrdev_region(dev_id, 1);
  143. }
  144. module_init(button_init);
  145. module_exit(button_exit);
  146. MODULE_LICENSE("GPL");

复制代码
测试代码:button_test.c
  1. 测试代码: button_test.c
  2. #include
  3. #include
  4. #include
  5. #include
  6. <stdio.h>
  7. <sys/types.h>
  8. <sys/stat.h>
  9. <fcntl.h>
  10. int main(int argc, char *argv[])
  11. {
  12. int fd;
  13. unsigned char key_val;
  14. fd = open("/dev/button", O_RDWR);
  15. if (fd < 0) {
  16. printf("open failed.\n");
  17. return -1;
  18. }
  19. while(1) {
  20. read(fd, &key_val, sizeof(key_val));
  21. printf("key_val = %#x\n", key_val);
  22. }
  23. close(fd);
  24. return 0;
  25. }
复制代码
3 加载驱动,运行测试代码:
$ insmod button_drv.ko
根据按键原理。可让 PI11 口 pin 脚接地模拟按键按下。
$ ./button_test (有按键按下返回 0x51,松开按键返回 0x50)

回复

使用道具 举报

发表于 2014-11-11 11:20:45 | 显示全部楼层
先顶顶,,回来有空了尝试一下,,,收藏了,,,thank you for your share
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-11-11 12:13:18 | 显示全部楼层
hades 发表于 2014-11-11 11:20
先顶顶,,回来有空了尝试一下,,,收藏了,,,thank you for your share  ...

恩 有什么问题反馈一下
回复 支持 反对

使用道具 举报

发表于 2015-10-14 10:33:54 | 显示全部楼层
LZ,你好!我参照论坛的教程构建的debian系统。现在想做基于gpio的中断驱动。自己做的驱动在gpio to  irq 这一步失败,获取的irq为-22。看到你的帖子,复制粘贴,修改.fex的gpiopara,编译没问题,加载驱动的时候同样在gpio to irq这一步获得的irq为-22.
“root@CubieBoard2:~# insmod button_drv.ko
GPIO<1> request the irq is -22
[   48.781065] GPIO<1> request the irq is -22
request irq error
[   48.787647] request irq error
root@CubieBoard2:~# ”
现在的使用的debian下面并没有gpio-sunxi.ko驱动,这个驱动与我编译的驱动有没有关联?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-15 09:27:21 | 显示全部楼层
simon_zhangss 发表于 2015-10-14 10:33
LZ,你好!我参照论坛的教程构建的debian系统。现在想做基于gpio的中断驱动。自己做的驱动在gpio to  irq 这 ...

gpio-sunxi.ko 获取.fex 的参数。 你要先加载gpio-sunxi.ko模块。    应该是有的可能驱动选上把。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-15 09:27:23 | 显示全部楼层
simon_zhangss 发表于 2015-10-14 10:33
LZ,你好!我参照论坛的教程构建的debian系统。现在想做基于gpio的中断驱动。自己做的驱动在gpio to  irq 这 ...

gpio-sunxi.ko 获取.fex 的参数。 你要先加载gpio-sunxi.ko模块。    应该是有的可能驱动选上把。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-15 09:27:27 | 显示全部楼层
simon_zhangss 发表于 2015-10-14 10:33
LZ,你好!我参照论坛的教程构建的debian系统。现在想做基于gpio的中断驱动。自己做的驱动在gpio to  irq 这 ...

gpio-sunxi.ko 获取.fex 的参数。 你要先加载gpio-sunxi.ko模块。    应该是有的可能驱动选上把。
回复 支持 反对

使用道具 举报

发表于 2015-10-15 10:25:14 | 显示全部楼层
本帖最后由 simon_zhangss 于 2015-10-15 10:28 编辑
sunbeyond 发表于 2015-10-15 09:27
gpio-sunxi.ko 获取.fex 的参数。 你要先加载gpio-sunxi.ko模块。    应该是有的可能驱动选上把。 ...


现在使用的内核是3.4.43.昨天后面有尝试加载gpio-sunxi.ko模块。下面是打印信息:

打印信息第二行显示:GPIO irq support disabled in this platform。
#define EINT_NUM gpio_eint_count
不明白,然后在gpio_sunxi.c中搜索打印信息,
        /* configure EINTs for the detected SoC */
        sunxi_gpio_eint_probe();

        /* This needs additional system irq numbers (NR_IRQ=NR_IRQ+EINT_NUM) */
        if (EINT_NUM > 0) {
                sunxi_chip->irq_base = irq_alloc_descs(-1, 0, EINT_NUM, 0);
                if (sunxi_chip->irq_base < 0) {
                        pr_err("Couldn't allocate virq numbers. GPIO irq support disabled\n");
                        err = sunxi_chip->irq_base;
                }
        } else
                pr_info("GPIO irq support disabled in this platform\n");
进入_devinit sunxi_gpio_eint_probe(),仅有
if (sunxi_is_a10())
{
gpio_eint_list = a10;
gpio_eint_count = 32;
}
else if (sunxi_is_a13())
{
gpio_eint_list = a13;
gpio_eint_count = 32;
}
else
{
gpio_eint_list = none;
gpio_eint_count = 0;
}
这意思是不支持a20?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-15 20:02:33 | 显示全部楼层
simon_zhangss 发表于 2015-10-15 10:25
现在使用的内核是3.4.43.昨天后面有尝试加载gpio-sunxi.ko模块。下面是打印信息:

打印信息第二行显示: ...

你这内核源码哪里下载的啊? 感觉不是cubie官方的。官方放的都是3.4.79

https://github.com/cubieboard/linux-sdk-kernel-source
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-10-15 20:02:39 | 显示全部楼层
simon_zhangss 发表于 2015-10-15 10:25
现在使用的内核是3.4.43.昨天后面有尝试加载gpio-sunxi.ko模块。下面是打印信息:

打印信息第二行显示: ...

你这内核源码哪里下载的啊? 感觉不是cubie官方的。官方放的都是3.4.79

https://github.com/cubieboard/linux-sdk-kernel-source
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|粤ICP备13051116号|cubie.cc---深刻的嵌入式技术讨论社区

GMT+8, 2024-5-5 07:44 , Processed in 0.029470 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2012 Comsenz Inc. | Style by Coxxs

返回顶部