抑郁症健康,内容丰富有趣,生活中的好帮手!
抑郁症健康 > 一 linux驱动开发-4.1-按键输入

一 linux驱动开发-4.1-按键输入

时间:2023-05-08 04:19:55

相关推荐

目录

一、前言

二、程序编写

2.1、修改设备树

2.1.1、添加pinctrl节点

2.1.2、添加key节点

2.2、驱动编写

2.3、应用程序编写

三、测试

一、前言

下面演示下linux下GPIO输入驱动的编写。

在驱动中使用一个整形变量来表示按键值,应用程序通过read函数来读取按键值,因为驱动要对这个整形变量写入按键值,应用程序要读取按键值,因此该整形变量就是共享资源,需要进行保护,对于整形变量,我们首选就是原子操作,通过原子操作对该变量进行赋值与读取。

二、程序编写

2.1、修改设备树

2.1.1、添加pinctrl节点

在 iomuxc 节点的 imx6ul-evk 子节点下添加一个pinctrl_key的子节点:

2.1.2、添加key节点

在根节点“/”下创建key节点,节点名字为gpiokey。

make dtbs重新编译设备树,然后启动linux系统,在/proc/decive-tree目录下查看“gpiokey”节点是否存在。

2.2、驱动编写

添加一个原子变量保存按键值。

#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/uaccess.h>#include <linux/io.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/of.h>#include <linux/of_address.h>#include <linux/of_gpio.h>#define GPIOKEY_CNT1#define GPIOKEY_NAME "gpiokey"#defineKEY_ON0xF0#define KEY_OFF0x00//设备结构体struct gpiokey_dev{dev_t devid;struct cdev cdev;struct class *class;struct device *device;int major;int minor;struct device_node *nd;//设备节点int key_gpio;//key所使用的GPIO编号atomic_t value; //按键值};struct gpiokey_dev gpiokey; static int key_init(void){int ret = 0;//通过节点名字查找节点gpiokey.nd = of_find_node_by_name(NULL, "gpiokey");if (gpiokey.nd == NULL){printk("find %s fail\r\n", "gpiokey");goto fail_nd;}//获取GPIO编号gpiokey.key_gpio = of_get_named_gpio(gpiokey.nd, "key-gpio", 0);if (gpiokey.key_gpio < 0){printk("get gpio fail\r\n");goto fail_nd;}ret = gpio_request(gpiokey.key_gpio, GPIOKEY_NAME);if (ret < 0){printk("fail to request the key gpio\r\n");goto fail_nd;}//设置key状态ret = gpio_direction_input(gpiokey.key_gpio);if (ret < 0){printk("set key status fail\r\n");goto fail_setinput;}fail_setinput:gpio_free(gpiokey.key_gpio);fail_nd:return ret;return 0;}static int key_open(struct inode *inode, struct file *filp){int ret = 0;filp->private_data = &gpiokey;ret = key_init();if (ret < 0)return ret;return 0;}static ssize_t key_read(struct file *filp, __user char *buf, size_t count, loff_t *ppos){int ret = 0;int value;struct gpiokey_dev *dev = filp->private_data;if (gpio_get_value(dev->key_gpio) == 0) //按下{while(!gpio_get_value(dev->key_gpio));//等待松开atomic_set(&dev->value, KEY_ON);}else {//没按下atomic_set(&dev->value, KEY_OFF);}value = atomic_read(&dev->value);ret = copy_to_user(buf, &value, sizeof(value));return ret;}static ssize_t key_write(struct file *filp, const char __user *buf, size_t count, loff_t *oppos){printk("key write\n");return 0;}static int key_release(struct inode *inode, struct file *filp){printk("key release\n");return 0;}static const struct file_operations key_fops = {.owner = THIS_MODULE,.open = key_open,.read = key_read,.write = key_write,.release = key_release,};static int __init mykey_init(void){int ret = 0;//按键值初始化atomic_set(&gpiokey.value, KEY_OFF);//分配设备号if ( gpiokey.major) {gpiokey.devid = MKDEV( gpiokey.major, 0);register_chrdev_region( gpiokey.devid, GPIOKEY_CNT, GPIOKEY_NAME);} else {alloc_chrdev_region(&gpiokey.devid, 0, GPIOKEY_CNT, GPIOKEY_NAME);gpiokey.major = MAJOR(gpiokey.devid);gpiokey.minor = MINOR(gpiokey.devid);}printk(" gpiokey major=%d, minor= %d\r\n", gpiokey.major, gpiokey.minor);//初始化cdevgpiokey.cdev.owner = THIS_MODULE;cdev_init(&gpiokey.cdev, &key_fops);//添加cdevret = cdev_add(&gpiokey.cdev, gpiokey.devid, GPIOKEY_CNT);if (ret < 0){printk("cdev add fail\r\n");goto fail_cdev;}//创建类gpiokey.class = class_create(THIS_MODULE, GPIOKEY_NAME);if (IS_ERR(gpiokey.class)){printk("creat class fail\r\n");ret = PTR_ERR(gpiokey.class);goto fail_class;}//创建设备gpiokey.device = device_create(gpiokey.class, NULL, gpiokey.devid, NULL, GPIOKEY_NAME);if (IS_ERR(gpiokey.device)){printk("creat device fail\r\n");ret = PTR_ERR(gpiokey.device);goto fail_device;}return 0;fail_device:class_destroy(gpiokey.class);fail_class:cdev_del(&gpiokey.cdev);fail_cdev:unregister_chrdev_region(gpiokey.devid, GPIOKEY_CNT);return ret;}static void __exit mykey_exit(void){//删除设备的类device_destroy(gpiokey.class, gpiokey.devid);//删除类class_destroy(gpiokey.class);//删除设备cdev_del(&gpiokey.cdev);//注销设备号unregister_chrdev_region(gpiokey.devid, GPIOKEY_CNT);printk(" dev exit\n");}module_init( mykey_init);module_exit( mykey_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("ZK");

2.3、应用程序编写

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#define KEY0VALUE0xF0#define INVAKEY 0x00/*@argc:应用程序参数个数@argv[]:具体的参数内容,字符串形式@ ./keyAPP /dev/key*/int main(int argc, char *argv[]){int ret = 0;int fd = 0;int value = 0;char *filename;if (argc != 2){printf("Error usage!\r\n");return -1;}filename = argv[1];fd = open(filename, O_RDWR);if (fd < 0){printf("can't open file\r\n", filename);return -1;}while(1) {read(fd, &value, sizeof(value));if (value == KEY0VALUE) {printf("KEY0 Press, value = %d\r\n", value);}}/*close*/ret = close(fd);if (ret < 0){printf("close file %s failed\r\n", filename);}return 0;}

三、测试

如果觉得《一 linux驱动开发-4.1-按键输入》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。