zoukankan      html  css  js  c++  java
  • 20150218【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

    【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

    2015-02-18 李海沿

    按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用Poll函数,来控制一定时间内,如果有按键发生,则立即返回键值。

    同时,poll也可以同时监控多个(比如说按键,鼠标,等)一旦发生事件则立即返回。

    我们在linux查看帮助:

    从帮助中的说明得知,

    poll, ppoll - wait for some event on a file descriptor

    poll就是监控某个设备的事件。

    修改驱动程序

    1.增加头文件 #include <linux/poll.h>

    2.增加key_poll 方法

    static unsigned key_poll(struct file *file,poll_table *wait)

    file_opreation中增加:

    .poll = key_poll,

    3.在key_poll函数中设置函数不睡眠

    4.此时可以把以前的read函数中的中断睡眠代码注释掉

    5.编译代码,测试

    附上驱动程序。

      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>
     13 #include <linux/uaccess.h>
     14 #include <linux/irq.h>
     15 #include <linux/wait.h>
     16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared 
     17 #include <linux/interrupt.h>
     18 #include <linux/poll.h>
     19 
     20 #include "mx257_gpio.h"
     21 #include "mx25_pins.h"
     22 #include "iomux.h"
     23 
     24 #define Driver_NAME "key_interrupt"
     25 #define DEVICE_NAME "key_interrupt"
     26 
     27 #define GPIO2_21    MX25_PIN_CLKO
     28 #define GPIO3_15    MX25_PIN_EXT_ARMCLK
     29 #define GPIO2_10    MX25_PIN_A24
     30 #define GPIO2_11    MX25_PIN_A25
     31 #define GPIO2_8     MX25_PIN_A22
     32 #define GPIO2_9     MX25_PIN_A23
     33 #define GPIO2_6     MX25_PIN_A20
     34 #define GPIO2_7     MX25_PIN_A21
     35 //command
     36 #define key_input     0
     37 #define version        1
     38 //定义各个按键按下的键值
     39 struct pin_desc{
     40     unsigned int pin;
     41     unsigned int key_val;
     42 };
     43 //当按键按下时,键值分别为 以下值
     44 struct pin_desc pins_desc[8] = {
     45     {GPIO2_6,    0x01},
     46     {GPIO2_7,    0x02},
     47     {GPIO2_8,    0x03},
     48     {GPIO2_9,    0x04},
     49     {GPIO2_10,    0x05},
     50     {GPIO2_11,    0x06},
     51     {GPIO2_21,    0x07},
     52     {GPIO3_15,    0x08},
     53 };
     54 //定义一个全局变量,用于保存按下的键值
     55 static unsigned int key_val;
     56 
     57 //interrupt head
     58 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
     59 static volatile unsigned char ev_press;  
     60 
     61 static int major=0;
     62 
     63 //auto to create device node
     64 static struct class *drv_class = NULL;
     65 static struct class_device *drv_class_dev = NULL;
     66 
     67 
     68 /* 应用程序对设备文件/dev/key_query执行open(...)时,
     69  * 就会调用key_open函数*/
     70 static int key_open(struct inode *inode, struct file *file)
     71 {
     72     printk("<0>function open!
    
    ");
     73     
     74     return 0;
     75 }
     76 
     77 /* 中断程序key_irq */
     78 static irqreturn_t key_irq(int irq, void *dev_id)
     79 {
     80     struct pin_desc * pindesc = (struct pin_desc *)dev_id;
     81     //发生了中断
     82     //printk("<0>function interrupt key_irq!
    
    ");
     83     //获取按键键值
     84     if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
     85         /* 按下 */
     86         key_val = pindesc->key_val;
     87     }else{
     88         key_val = 0x80 | pindesc->key_val;
     89     }
     90     printk("<0>get key 0x%x",key_val);    
     91     ev_press = 1;
     92     wake_up_interruptible(&key_interrupt_wait);
     93 
     94     return IRQ_RETVAL(IRQ_HANDLED);
     95 }
     96 
     97 
     98 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
     99 {
    100     int ret;
    101     //如果按键没有按下,没有中断,休眠
    102     //wait_event_interruptible(key_interrupt_wait,ev_press);
    103 
    104     ret = copy_to_user(buff,&key_val,sizeof(key_val));
    105     if(ret){
    106         ;
    107     }
    108     ev_press = 0;
    109     return sizeof(key_val);
    110 
    111     //int cnt=0;
    112     //unsigned char key_vals[8];
    113 
    114     /*
    115     // reading the pins value
    116     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
    117     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
    118     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
    119     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
    120     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
    121     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
    122     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
    123     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
    124     
    125     //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d
    ",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]); 
    126     */
    127 }
    128 
    129 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
    130 {
    131     printk("<0>function write!
    
    ");
    132     
    133     return 1;
    134 }
    135 
    136 static int  key_release(struct inode *inode, struct file *filp)
    137 {
    138     printk("<0>function release!
    
    ");
    139     //释放中断
    140     free_irq(IOMUX_TO_IRQ(GPIO2_21),  &pins_desc[6]);
    141     //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
    142     free_irq(IOMUX_TO_IRQ(GPIO2_11),  &pins_desc[5]);
    143     free_irq(IOMUX_TO_IRQ(GPIO2_10),  &pins_desc[4]);
    144     free_irq(IOMUX_TO_IRQ(GPIO2_9),   &pins_desc[3]);
    145     //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
    146     free_irq(IOMUX_TO_IRQ(GPIO2_7),   &pins_desc[1]);
    147     free_irq(IOMUX_TO_IRQ(GPIO2_6),   &pins_desc[0]);
    148     return 0;
    149 }
    150 
    151 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
    152 {
    153     int ret;
    154     printk("<0>function ioctl!
    
    ");
    155     switch (command) {
    156         case key_input:    
    157             //设置所有的引脚为输入
    158             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
    159             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
    160             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
    161             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
    162             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
    163             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
    164             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
    165             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
    166             printk("<0>have setting all pins to gpio input mod !
    ");
    167             //设置GPIO引脚为上拉模式
    168             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    169             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    170             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    171             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    172             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    173             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    174             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    175             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
    176 
    177             //设置GPIO引脚中断  ,下降沿触发
    178             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
    179             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
    180             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
    181             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
    182             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
    183             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
    184             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
    185             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
    186             printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !
    ");
    187 
    188             break;
    189         case version:
    190             printk("<0>hello,the version is 0.1.0
    
    ");
    191             break;
    192         default:
    193               printk("<0>command error 
    ");
    194             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;
    ");
    195             printk("<0>command: <key_input> <version>
    
    ");
    196             return -1;
    197     }
    198     return 0;    
    199 }
    200 static unsigned key_poll(struct file *file,poll_table *wait)
    201 {
    202     unsigned int mask = 0;
    203     //程序不立即睡眠,而是继续等待
    204     poll_wait(file,&key_interrupt_wait,wait);
    205     //如果按键按下
    206     if(ev_press)
    207         mask |= POLLIN | POLLRDNORM;
    208 
    209     return mask;
    210 }
    211 
    212 /* 这个结构是字符设备驱动程序的核心
    213  * 当应用程序操作设备文件时所调用的open、read、write等函数,
    214  * 最终会调用这个结构中指定的对应函数
    215  */
    216 static struct file_operations key_fops = {
    217     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    218     .open   =   key_open,     
    219     .read    =    key_read,       
    220     .write    =    key_write,       
    221     .release=   key_release,
    222     .ioctl  =   key_ioctl,    
    223     .poll   =   key_poll,
    224 };
    225     
    226 /*
    227  * 执行insmod命令时就会调用这个函数 
    228  */
    229 static int __init  key_irq_init(void)
    230 {
    231     printk("<0>
    Hello,this is %s module!
    
    ",Driver_NAME);
    232     //register and mknod
    233     major = register_chrdev(0,Driver_NAME,&key_fops);
    234     drv_class = class_create(THIS_MODULE,Driver_NAME);
    235     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);    /*/dev/key_query*/
    236 
    237     //set all pins to GPIO mod  ALF5
    238     mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
    239     mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
    240       mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
    241        mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
    242     mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
    243     mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
    244     mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
    245     mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
    246     //request IOMUX GPIO
    247     gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
    248      gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
    249      gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
    250        gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
    251     gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
    252      gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
    253       gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
    254     gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
    255     
    256 
    257     return 0;
    258 }
    259 
    260 /*
    261  * 执行rmmod命令时就会调用这个函数 
    262  */
    263 static void __exit key_irq_exit(void)
    264 {
    265     printk("<0>
    Goodbye,%s!
    
    ",Driver_NAME);
    266 
    267     unregister_chrdev(major,Driver_NAME);
    268     device_unregister(drv_class_dev);
    269     class_destroy(drv_class);
    270 
    271     /* free gpios */
    272     mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
    273     mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
    274     mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
    275     mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
    276     mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
    277     mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
    278     mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
    279     mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
    280 
    281     gpio_free(IOMUX_TO_GPIO(GPIO2_21));
    282     gpio_free(IOMUX_TO_GPIO(GPIO3_15));
    283     gpio_free(IOMUX_TO_GPIO(GPIO2_10));
    284     gpio_free(IOMUX_TO_GPIO(GPIO2_11));
    285     gpio_free(IOMUX_TO_GPIO(GPIO2_8));
    286     gpio_free(IOMUX_TO_GPIO(GPIO2_9));
    287     gpio_free(IOMUX_TO_GPIO(GPIO2_6));
    288     gpio_free(IOMUX_TO_GPIO(GPIO2_7));
    289 
    290 }
    291 
    292 /* 这两行指定驱动程序的初始化函数和卸载函数 */
    293 module_init(key_irq_init);
    294 module_exit(key_irq_exit);
    295 
    296 /* 描述驱动程序的一些信息,不是必须的 */
    297 MODULE_AUTHOR("Lover雪");
    298 MODULE_VERSION("0.1.0");
    299 MODULE_DESCRIPTION("IMX257 key Driver");
    300 MODULE_LICENSE("GPL");
    View Code

    修改应用程序

    1.我们首先包含头文件 #include <poll.h>

    2.定义结构体

    struct pollfd fds[1]; //方括号中为要监控的设备数量

    fds[0].fd = fd; //加入要监控的设备描述符

    fds[0].events = POLLIN;

    3. 监控的结果是 POLLIN

    POLLIN There is data to read.

    从帮助得知,一旦时间发送就意思有消息读取,接着,一旦我们poll监控到数据,我们就开始read函数来读取数据。

    附上修改后的应用程序代码:

     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 #include <poll.h>
    14 
    15 #include "mx257_gpio.h"
    16 
    17 #define key_input     0
    18 #define version       1
    19 
    20 
    21 int main(int argc, char **argv)
    22 {
    23     int fd;
    24     int i=0,cnt=0;
    25     unsigned char key_val[1];
    26     struct pollfd fds[1];    
    27     int ret;
    28     fd = open("/dev/key_interrupt",O_RDWR);
    29     if(fd < 0){
    30         printf("can't open !!!
    ");
    31     }
    32     ioctl(fd,version,NULL);
    33     ioctl(fd,key_input,NULL);
    34 
    35     fds[0].fd = fd;
    36     fds[0].events = POLLIN;
    37     while(1){
    38         ret = poll(fds,1,5000);
    39         if(ret == 0)
    40             printf("time out
    ");
    41         else{
    42             read(fd,key_val,1);
    43             printf("%04d key pressed: 0x%x
    ",cnt++,key_val[0]);    
    44         }
    45     }
    46     return 0;
    47 }
    View Code

    运行程序:

    可以发现,其实程序时不断的在查询,每5秒之内若是没有时间发生则打印time out,若是有时间发生,则立即读取内核空间的键值。

    既然是不断的查询,那我们来看一下,它是不是很耗费CPU资源呢:

    后台运行,使用top命令查看cpu使用率

    可以发现,函数在不断的运行,每过5s打印time out

    使用top命令,查看cpu资源

    可以发现,虽然这个程序没有使用中断休眠函数,也是在不断的查询,但是使用poll后,cpu几乎不占用。

    kill 杀死后台程序

  • 相关阅读:
    centos添加图形桌面
    centos 复制并重命名文件
    山东省第八届ACM程序设计大赛总结
    RMQ
    图的深度优先搜索
    ACM知识点清单
    优先队列(priority_queue)
    Contest Print Server
    k8s之证书签发(二)
    k8s环境之bind 9 (一)
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4295960.html
Copyright © 2011-2022 走看看