码迷,mamicode.com
首页 > 其他好文 > 详细

20150216 IMX257实现GPIO-查询按键驱动程序

时间:2015-02-16 22:03:53      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:

20150216IMX257实现GPIO-查询按键驱动程序

2015-02-16 李海沿

前面我们介绍了简单的通用字符设备驱动程序,接下来,我们在它的基础上来实现GPIO的查询按键功能。

先附上驱动程序代码

技术分享
  1 /******************************
  2     linux key_query
  3  *****************************/
  4 #include <linux/module.h>
  5 #include <linux/init.h>
  6 #include <linux/kernel.h>
  7 #include <linux/delay.h>
  8 #include <linux/types.h>
  9 #include <linux/ioctl.h>    
 10 #include <linux/gpio.h>
 11 #include <linux/fs.h>
 12 #include <linux/device.h>    //包含了用于自动创建设备节点的函数device_create
 13 #include <linux/uaccess.h>  //包含了copy_to_user 函数等
 14 
 15 #include "mx257_gpio.h"
 16 #include "mx25_pins.h"
 17 #include "iomux.h"
 18 
 19 #define Driver_NAME "key_query"
 20 #define DEVICE_NAME "key_query"
 21 
 22 #define GPIO2_21    MX25_PIN_CLKO
 23 #define GPIO3_15    MX25_PIN_EXT_ARMCLK
 24 #define GPIO2_10    MX25_PIN_A24
 25 #define GPIO2_11    MX25_PIN_A25
 26 #define GPIO2_8     MX25_PIN_A22
 27 #define GPIO2_9     MX25_PIN_A23
 28 #define GPIO2_6     MX25_PIN_A20
 29 #define GPIO2_7     MX25_PIN_A21
 30 //command in ioctl
 31 #define key_input     0        
 32 #define version        1
 33 
 34 //用于保存主设备号
 35 static int major=0;
 36 
 37 //用于自动创建设备节点 代替了手动敲mknod命令
 38 static struct class *drv_class = NULL;
 39 static struct class_device *drv_class_dev = NULL;
 40 
 41 
 42 /* 应用程序对设备文件/dev/key_query执行open(...)时,
 43  * 就会调用key_open函数*/
 44 static int key_open(struct inode *inode, struct file *file)
 45 {
 46     printk("<0>function open!\n\n");
 47     
 48     return 0;
 49 }
 50 
 51 /*当应用程序中read(fd,buff,sizeof(buff))时调用此key_read函数*/
 52 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
 53 {
 54     int ret;
 55     //nt cnt=0;
 56     unsigned char key_vals[8];
 57     // reading the pins value
 58     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
 59     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
 60     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
 61     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
 62     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
 63     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
 64     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
 65     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
 66     
 67     ret = copy_to_user(buff,key_vals,sizeof(key_vals));
 68     if(ret){
 69         ;
 70     }
 71     
 72     //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d\n",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]); 
 73 
 74     return sizeof(key_vals);
 75 }
 76 
 77 /* 当应用程序中使用write函数时,调用此函数**/
 78 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
 79 {
 80     printk("<0>function write!\n\n");
 81     
 82     return 1;
 83 }
 84 
 85 static int  key_release(struct inode *inode, struct file *filp)
 86 {
 87     printk("<0>function release!\n\n");
 88     return 0;
 89 }
 90 /* 当用户调用ioctl(fd,version,NULL);时,会进入此函数,
 91  * 在SWITCH中配对command,然后执行相应的语句 
 92  * 注意command 一定为整数,需在前面定义*/
 93 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
 94 {
 95     printk("<0>function ioctl!\n\n");
 96     switch (command) {
 97         case key_input:
 98                         //配置GPIO引脚为输入模式
 99             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
100             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
101             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
102             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
103             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
104             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
105             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
106             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
107             printk("<0>have setting all pins to gpio input mod !\n");
108             break;
109         case version:
110             printk("<0>hello,the version is 0.1.0\n\n");
111             break;
112         default:
113               printk("<0>command error \n");
114             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");
115             printk("<0>command: <key_input> <version>\n\n");
116             return -1;
117     }
118     return 0;    
119 }
120 
121 /* 这个结构是字符设备驱动程序的核心
122  * 当应用程序操作设备文件时所调用的open、read、write等函数,
123  * 最终会调用这个结构中指定的对应函数
124  */
125 static struct file_operations key_fops = {
126     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
127     .open   =    key_open,     
128     .read      =    key_read,       
129     .write      =    key_write,       
130         .release=    key_release,
131          .ioctl   =    key_ioctl,    
132 };
133     
134 /*
135  * 执行insmod命令时就会调用这个函数 
136  */
137 static int __init key_init(void)
138 {
139     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
140     //register and mknod
141     //注册字符设备,系统会自动分配一个主设备号,保存在major中
142     major = register_chrdev(0,Driver_NAME,&key_fops);
143     //自动在/dev/目录下创建设备节点
144     drv_class = class_create(THIS_MODULE,Driver_NAME);
145     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/
146 
147     //set all pins to GPIO mod  ALF5
148         //设置所有的GPIO引脚为GPIO功能
149         mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
150     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
151       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
152        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
153     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
154     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
155     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
156     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
157     //request IOMUX GPIO
158         gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
159      gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
160      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
161        gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
162         gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
163      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
164       gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
165     gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
166     
167 
168     return 0;
169 }
170 
171 /*
172  * 执行rmmod命令时就会调用这个函数 
173  */
174 static void __exit key_exit(void)
175 {
176     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
177 
178     //卸载字符设备,释放主设备号
179     unregister_chrdev(major,Driver_NAME);
180     //卸载字符设备的设备节点
181     device_unregister(drv_class_dev);
182     class_destroy(drv_class);
183 
184     /* free gpios */
185     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
186         mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
187         mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
188         mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
189         mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
190         mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
191         mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
192         mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
193 
194         gpio_free(IOMUX_TO_GPIO(GPIO2_21));
195         gpio_free(IOMUX_TO_GPIO(GPIO3_15));
196         gpio_free(IOMUX_TO_GPIO(GPIO2_10));
197         gpio_free(IOMUX_TO_GPIO(GPIO2_11));
198         gpio_free(IOMUX_TO_GPIO(GPIO2_8));
199         gpio_free(IOMUX_TO_GPIO(GPIO2_9));
200         gpio_free(IOMUX_TO_GPIO(GPIO2_6));
201         gpio_free(IOMUX_TO_GPIO(GPIO2_7));
202 
203 }
204 
205 /* 这两行指定驱动程序的初始化函数和卸载函数 */
206 module_init(key_init);
207 module_exit(key_exit);
208 
209 /* 描述驱动程序的一些信息,不是必须的 */
210 MODULE_AUTHOR("Lover雪儿");
211 MODULE_VERSION("0.1.0");
212 MODULE_DESCRIPTION("IMX257 key Driver");
213 MODULE_LICENSE("GPL");
214 
215     
View Code

 


如程序所示,
 

static int __init key_init(void)

我们把注册字符设备,创建设备节点,GPIO地址映射,以及GPIO模式的初始化,都在此函数中实现。

 

static void __exit key_exit(void)

在此函数中我们 做了一下三件事,卸载字符设备,释放主设备函,释放GPIO

 

static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

当应用程序中调用

read(fd, key_vals,sizeof(key_vals));

时,该函数就是负责,读取此时,我们GPIO引脚的电平,然后通过COPY_TO_USER函数将我们的gpio引脚的电平传递给应用程序。

 

static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)

当应用程序中,执行代码

ioctl(fd,key_input,NULL);

时,就会执行

技术分享

switch的case key_input中的代码,将所有的gpio引脚都设置成输入模式。

 

 

附上应用程序代码

技术分享
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 #include <termios.h>
 8 #include <errno.h>
 9 #include <limits.h>
10 #include <asm/ioctls.h>
11 #include <time.h>
12 #include <pthread.h>
13 
14 #include "mx257_gpio.h"
15 
16 #define key_input     0
17 #define version               1
18 
19 
20 int main(int argc, char **argv)
21 {
22     int fd;
23     int i=0,cnt=0;
24     unsigned char key_vals[8];
25     
26     fd = open("/dev/key_query",O_RDWR);
27     if(fd < 0){
28         printf("can‘t open !!!\n");
29     }
30     ioctl(fd,key_input,NULL);
31     while(1){
32         read(fd, key_vals,sizeof(key_vals));
33         if(!key_vals[0] | !key_vals[1] | !key_vals[2] | !key_vals[3] | !key_vals[4] | !key_vals[5] | !key_vals[6] | !key_vals[7] )
34             printf("%04d key pressed: %d %d %d %d %d %d %d %d\n",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]);    
35     }
36     return 0;
37 }
View Code

 


在应用程序中,
 

  1. 我们首先使用open来打开设备/dev/key_query。
  1. 使用ioctl函数将所有的GPIO引脚配置为输入模式
  1. 在while循环中使用read函数来不断的读取gpio引脚的电,一旦检测到低电平,就打印所有GPIO引脚当前的电平值

 

附上MAKEFILE代码

技术分享
 1 ifeq ($(KERNELRELEASE),)
 2     KERNELDIR ?= /home/study/system/linux-2.6.31
 3     PWD := $(shell pwd)
 4 modules:
 5     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
 6 modules_install:
 7     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
 8 clean:
 9     rm -rf *.o *~ core .depend  *cmd *.ko *.mod.c .tmp_versions *.markers *.order *.symvers
10 
11 else
12     obj-m := key.o
13 endif
View Code

 


 
 

 

编译、加载驱动:

使用交叉编译工具:

make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

insmod key.ko

ll /dev/key*

 

执行应用程序:

cd key/

arm-none-linux-gnueabi-gcc key_test.c –o key_test

./key_test

 

20150216 IMX257实现GPIO-查询按键驱动程序

标签:

原文地址:http://www.cnblogs.com/lihaiyan/p/4294510.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!