TA的每日心情 | 开心 6 天前 |
---|
签到天数: 1082 天 连续签到: 3 天 [LV.10]以坛为家III
|
这节来学习下按键输入的linux驱动程序。
一、硬件电路
按键使用IO口是GPIO3_IO19。
二、驱动程序
2.1、dts文件定义
设备树文件/MYIR-i.MX8MM-Linux/arch/arm64/boot/dts/freescale/myb-fsl-imx8mm-evk.dts有关按键接口定义
2.2、驱动程序
userkey.c
- <font size="3">#include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/errno.h>
- #include <linux/gpio.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/of_gpio.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- #define KEY0VAL 0xF0
- #define INVAKEY 0x00
- #define KEY_CNT 1
- #define KEY_NAME "userkey"
- struct userkey_dev
- {
- dev_t devid;
- struct cdev cdev;
- struct class *class;
- struct device *device;
- int major;
- int minor;
- struct device_node *nd;
- int key_gpio;
- atomic_t keyval;
- };
- struct userkey_dev userkey;
- //key open
- static int key_open(struct inode *inode, struct file *filp)
- {
- filp->private_data = &userkey;
- return 0;
- }
- //key read
- static ssize_t key_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
- {
- int sta=0;
- unsigned char val;
- struct userkey_dev *dev = filp->private_data;
- {
- if(gpio_get_value(dev->key_gpio)==0)
- {
- while (!gpio_get_value(dev->key_gpio));
- atomic_set(&dev->keyval, KEY0VAL);
- }
- else
- {
- atomic_set(&dev->keyval,INVAKEY);
- }
- val=atomic_read(&dev->keyval);
- sta= copy_to_user(buf, &val, sizeof(val));
- return sta;
- };
- return 0;
- }
- //fops
- static struct file_operations userkey_fops = {
- .owner = THIS_MODULE,
- .open = key_open,
- .read = key_read,
- };
- //led init
- static int __init ourkey_init(void)
- {
- int ret = 0;
- atomic_set(&userkey.keyval,INVAKEY);
- userkey.nd = of_find_node_by_path("/gpio-keys/user");
- if(userkey.nd == NULL)
- {
- printk("userkey node not find!\r\n");
- return -EINVAL;
- }
- else
- {
- printk("userkey node find!\r\n");
- }
-
- userkey.key_gpio = of_get_named_gpio(userkey.nd, "gpios", 0);
- if(userkey.key_gpio < 0)
- {
- printk("can't get usergpio\r\n");
- return -EINVAL;
- }
- printk("key_gpio=%d\r\n",userkey.key_gpio);
- gpio_request(userkey.key_gpio, "key0");
- ret = gpio_direction_input(userkey.key_gpio);
- if(ret < 0)
- {
- printk("can't set userkey!\r\n");
- }
- if (userkey.major)
- {
- userkey.devid = MKDEV(userkey.major, 0);
- register_chrdev_region(userkey.devid, KEY_CNT, KEY_NAME);
- }
- else
- {
- alloc_chrdev_region(&userkey.devid, 0, KEY_CNT, KEY_NAME);
- userkey.major = MAJOR(userkey.devid);
- userkey.minor = MINOR(userkey.devid);
- }
- printk("userkey major=%d,minor=%d\r\n",userkey.major, userkey.minor);
-
- //cdev
- userkey.cdev.owner = THIS_MODULE;
- cdev_init(&userkey.cdev, &userkey_fops);
- cdev_add(&userkey.cdev, userkey.devid, KEY_CNT);
- userkey.class = class_create(THIS_MODULE, KEY_NAME);
- if (IS_ERR(userkey.class))
- {
- return PTR_ERR(userkey.class);
- }
- userkey.device = device_create(userkey.class, NULL, userkey.devid, NULL, KEY_NAME);
- if (IS_ERR(userkey.device))
- {
- return PTR_ERR(userkey.device);
- }
- return 0;
- }
- //led exit
- static void __exit ourkey_exit(void)
- {
- cdev_del(&userkey.cdev);
- unregister_chrdev_region(userkey.devid, KEY_CNT);
- device_destroy(userkey.class, userkey.devid);
- class_destroy(userkey.class);
- }
- module_init(ourkey_init);
- module_exit(ourkey_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("author");
- </font>
复制代码 2.3、Makefile文件 - <font size="3">KERNELDIR := /opt/04-Sources/MYIR-i.MX8MM-Linux
- CURRENT_PATH := $(shell pwd)
- obj-m := userkey.o
- build: kernel_modules
- kernel_modules:
- $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
- clean:
- $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean</font>
复制代码
2.4、编译程序后
生成userkey.ko文件
三、应用程序
3.1、userkeyApp.c
- <font size="3">#include <stdio.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <string.h>
- #define KEY0VAL 0xf0
- #define INVAKEY 0x00
- int main(int argc, char *argv[])
- {
- int fd, retvalue;
- char *filename;
- unsigned char keyval;
-
- if(argc != 2)
- {
- printf("Error Usage!\r\n");
- return -1;
- }
- filename = argv[1];
- fd = open(filename, O_RDWR);
- if(fd < 0)
- {
- printf("file %s open failed!\r\n", argv[1]);
- return -1;
- }
- printf("please input key \r\n");
- for(;;)
- {
- read(fd, &keyval, sizeof(keyval));
- if(keyval == KEY0VAL)
- {
- printf("KEY press, value= %#x\r\n",keyval);
- }
- }
-
- retvalue = close(fd);
- if(retvalue < 0)
- {
- printf("file %s close failed!\r\n", argv[1]);
- return -1;
- }
- return 0;
- }
- </font>
复制代码
3.2、Makefile
- <font size="3">include ../env.mk
- TARGET = userkeyledApp
- SRC = $(TARGET).c
- OBJS = $(patsubst %.c ,%.o ,$(SRC))
- .PHONY: all
- all: $(TARGET)
- $(TARGET) : $(OBJS)
- $(CC) -o $@ $^
- %.o : %.c
- $(CC) -c [ DISCUZ_CODE_151 ]lt; -o $@
- clean:
- $(RM) *.o $(TARGET)</font>
复制代码
3.3、编译程序
编译后生成userkeyApp
四、测试程序
4.1、将上面编译生成的两个文件拷贝到开发板 /opt目录下,
执行命令:
> insmod userkay.ko
> ./userkeyApp /dev/userkey
4.2、运行结果
按下按键一次,打印一帧数据。
|
|