tiny4412 设备树之按键中断(一)
来源:互联网 发布:java客户端服务端通信 编辑:程序博客网 时间:2024/06/15 18:02
开发板:tiny4412(1611)
内核:linux4.4
编译器: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320)
中断背后的知识:http://www.cnblogs.com/pengdonglin137/p/6349209.html
使用到的引脚是XEINT26,即GPX3_2
在设备树下添加节点:
interrupt_int26 { compatible = "tiny4412,interrupt_int26"; tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>; };
interrupt_int26是节点名,compatible属性用来匹配platform驱动
tiny4412,int_gpio1是我们自定义的一个属性,后面三个值分别是中断域(中断控制器) gpio引脚 flags
这里的flags即高电平有效
装载新的设备树后可以在sys/firmware/devicetree/base下看到interrupt_int26节点
驱动:#include <linux/init.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/gpio.h>#include <linux/of.h>#include <linux/of_gpio.h>#include <linux/interrupt.h>#include <linux/sched.h> #include <linux/cdev.h> #include <asm/uaccess.h>#include <linux/kdev_t.h>#include <linux/fs.h>typedef struct { int gpio; int irq; char name[20];}int_demo_data_t;#define INT_NUM 1 static struct class *int26_class= NULL;struct device *class_dev= NULL;static int_demo_data_t *data = NULL;static int major;static struct cdev int26_cdev;static const char* devname = "int26";static dev_t int_dev;static const struct file_operations int26_fops;static unsigned char key_val=1; static volatile int ev_press = 0; static DECLARE_WAIT_QUEUE_HEAD(int26_waitq); static irqreturn_t int26_irq(int irq, void *data) { ev_press = 1; wake_up_interruptible(&int26_waitq); return IRQ_HANDLED; } static int int26_open(struct inode * inode, struct file * filp){ printk("%s enter.\n", __func__);devm_request_any_context_irq(class_dev, data->irq,int26_irq, IRQF_TRIGGER_FALLING, data->name, data);return 0;} static ssize_t int26_read(struct file *filp, char __user *buffer,size_t length, loff_t *offset) { if (length != 1) return -EINVAL; wait_event_interruptible(int26_waitq, ev_press); copy_to_user(buffer, &key_val, sizeof(key_val)); ev_press = 0; return 1; } static int int26_release(struct inode *inode, struct file *file) { devm_free_irq(class_dev,data->irq,data); return 0; } static int int_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq_gpio = -1; int irq = -1; printk("%s enter.\n", __func__); if (!dev->of_node) { dev_err(dev, "no platform data.\n"); goto err1; } data = devm_kmalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(dev, "no memory.\n"); goto err0; } sprintf(data->name, "tiny4412,int_gpio1"); irq_gpio = of_get_named_gpio(dev->of_node,data->name, 0); if (irq_gpio < 0) { dev_err(dev, "Looking up %s property in node %s failed %d\n",data->name, dev->of_node->full_name, irq_gpio); goto err1; } data->gpio = irq_gpio; irq = gpio_to_irq(irq_gpio); if (irq < 0) { dev_err(dev,"Unable to get irq number for GPIO %d, error %d\n",irq_gpio, irq); goto err1; } data->irq = irq; printk("%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq); alloc_chrdev_region(&int_dev, 0, INT_NUM, "int26");major = MAJOR(int_dev);cdev_init(&int26_cdev, &int26_fops);cdev_add(&int26_cdev, MKDEV(major, 0), INT_NUM); int26_class=class_create(THIS_MODULE,"int26"); class_dev=device_create(int26_class, NULL, int_dev, NULL, "%s", devname); return 0; err1: devm_kfree(dev, data);err0: return -EINVAL;} static int int_remove(struct platform_device *pdev) {printk("%s enter.\n", __func__);unregister_chrdev_region(int_dev,INT_NUM);cdev_del(&int26_cdev);device_destroy(int26_class,MKDEV(major, 0));class_destroy(int26_class); return 0;} static const struct of_device_id dt_ids[] = { { .compatible = "tiny4412,interrupt_int26", }, {},};MODULE_DEVICE_TABLE(of, dt_ids); static struct platform_driver int26_driver = { .driver = { .name = "int26", .of_match_table = of_match_ptr(dt_ids), }, .probe = int_probe, .remove = int_remove,};static const struct file_operations int26_fops={ .owner = THIS_MODULE, .open = int26_open, .read = int26_read, .release= int26_release, }; static int __init int26_init(void){int ret; ret = platform_driver_register(&int26_driver); if (ret) printk(KERN_ERR "int demo: probe failed: %d\n", ret); return ret;}module_init(int26_init); static void __exit int26_exit(void){ platform_driver_unregister(&int26_driver);}module_exit(int26_exit);MODULE_LICENSE("GPL");
驱动中platform_driver中of_match_table匹配设备树的compatible属性,利用节点的tiny4412,int_gpio1属性来获得中断号,gpio_to_irq把引脚配置成中断模式,devm_request_any_context_irq向内核申请。
测试程序:
#include <stdio.h>#include <fcntl.h>int main(int argc,char *argv[]){ int fd; char buf; int num; fd=open("/dev/int26",O_RDONLY); if(fd<0){ printf("can not open /dev/int26\n"); return -1; } while(1){ num=read(fd,&buf,sizeof(char)); if(num!=sizeof(char)){ printf("read error\n"); return -1; } printf("read:%d\n",buf); }}
![](http://img.my.csdn.net/uploads/201708/31/1504187417_2435.png)
执行程序后,按下按键即可看到输出信息。目前驱动存在无法卸载的bug,待调试。。
阅读全文
0 0
- tiny4412 设备树之按键中断(一)
- tiny4412学习(四)之移植linux-设备树(1)设备树基础知识及GPIO中断
- tiny4412 设备树之pinctrl(番外)
- 基于tiny4412按键中断编程
- 字符设备之中断按键
- tiny4412 设备树之i2c设备(二)
- tiny4412 设备树之SD卡驱动(三)
- 字符设备实验之按键中断
- 字符设备驱动之中断按键驱动
- Linux字符设备驱动之中断按键
- linux设备驱动之按键中断
- 设备树学习之(一)GPIO中断
- 设备树学习之(一)GPIO中断
- 设备树学习之(一)GPIO中断
- 字符设备驱动之按键处理二(中断处理的按键驱动程序)
- tiny4412学习(四)之移植linux-设备树(2)设备树之LED点灯
- 按键驱动(一)-中断
- Tiny4412 字符设备驱动(一)
- 【java学习】Java网络通信基石Socket
- JAVA-初步认识-第三章-比较运算符逻辑运算符
- Selenium 3.5+python2.7打开IE浏览器报错
- redis集群的搭建
- c++基础之类型转换
- tiny4412 设备树之按键中断(一)
- 实验3 编程、编译、链接、跟踪
- Python的特殊方法
- Servletconfig和ServletContext
- c 内置函数
- 2018大疆创新A卷
- Navigating with Navit on the Raspberry Pi
- 美团点评笔试题
- mybatis自动生成器(mybatis.generator)使用