zoukankan      html  css  js  c++  java
  • 20150218【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

    【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

    2015-02-18 李海沿

    前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序

    这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开。

    一、首先在前面代码的基础上来一个简单的信号

    1.定义一个全局的整形变量

    2.在打开函数中,每次进入打开函数canopen都自减1,

    3.当我们不使用时,在realease 中canopen自加1

    4.这样就实现了一个简单的信号量,我们编译,测试

    当我们使用两个应用程序来同时打开设备时,看看会发生什么:

    可以发现,由于我们后台已经打开一个应用程序了,所以,如果此时我们再用另外一个应用程序打开的话,则会报错,can't open

    好了,到这里,我们已经基本上实现了一个简陋的信号量程序。

    附上驱动代码

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

    附上应用程序代码:

     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

    二、改进 原子操作

    由于前面的代码中信号量自减和检测信号量不是同时进行的,可能被打断,虽然概率很小,但是,也是有可能会发生。

    为了避免这个问题,这里我们使用原子操作来实现信号量的改变。

    所谓原子操作,就是不可被打断,从而保证了前面我们所说到的问题。

    具体方法如下。

    atomic_t v = ATOMIC_INIT(0);        //定义原子信号v,并且赋初值为0

    atomic_read(atomic_t *v);            //返回原子变量的值

    void atomic_inc(atomic_t *v);            //原子变量增加1

    void atomic_dec(atomic_t *v);        //原子变量减少1

    int atomic_dec_and_test(atomic_t *v);

        //自减操作后测试是否为0,为0则返回true,否则返回false

    驱动程序中修改如下:

    1. 定义原子信号canopen,并且赋初值1

    2.在open函数中检测信号量是否为1,否则就无法打开。

    3.在释放函数中信号量值加1

    4.编译和测试,可以发现结果和上面的代码一样

    附上驱动程序源程序:

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

    三、改进 信号量

    前面的代码中,如果驱动程序已经有一个应用程序在使用是,如果是另一个驱动程序再次来申请,则会报错can't open直接退出,我们如何让其不退出呢,而是在等待队列中等待信号量呢?

    使用信号量,方法如下:

    struct semaphore sem;        //定义信号量

    void sema_init(struct semaphore *sem, int val);    //初始化信号量

    void init_MUTEX(struct semaphore *sem);            //初始化信号量为0

    void down(struct semaphore *sem);                //获取信号量

    int down_interruptible(struct semaphore *sem);    

    int down_trylock(struct semaphore *sem);            //获取信号量,不成功则返回

    void up(struct semaphore *sem);                    //释放信号量

    操作步骤:

    1.定义信号量

    2.在init函数中初始化信号量

    3.和前面一样在open函数中申请信号量

    4.在release函数中释放信号量

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

    四、改进 应用程序不阻塞,属性O_NONBLOCK

    实现不阻塞操作,在开打开文件是,要加入属性O_NONBLOCK

    1.在应用程序中:加入属性O_NONBLOCK

    2.接下来就是在驱动程序中实现对O_NONBLOCK的解析

    首先注释前面信号量操作相关的代码:

    在read函数中,我们用file结构体来获取我们的flag

    if(filp->f_flags & O_NONBLOCK)            //判断是否设置O_NONBLOCK

    如果定义了,则不再会运行代码

    wait_event_interruptible(key_interrupt_wait,ev_press);

    那也就不会阻塞

    3.为了让应用程序不会运行太快,这里增加一个延时5s

    4.编译测试

     附上驱动程序代码:

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

    附上应用程序代码:

     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 | O_NONBLOCK);
    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         printf("%04d key pressed: 0x%x
    ",cnt++,key_val[0]);    
    40         sleep(5);
    41         /*if(ret == 0)
    42             printf("time out
    ");
    43         else{
    44             read(fd,key_val,1);
    45             printf("%04d key pressed: 0x%x
    ",cnt++,key_val[0]);    
    46         }*/
    47     }
    48     return 0;
    49 }
    View Code

    总结一下:

    前面的这几种方法都是很简单的,如果熟练了单片机程序的话,在驱动程序的基础上理解这个信号量,是很简单的,加油!

    对了,差点忘了,今天是除夕,在这里给爱好者们拜一个年:

    新年快乐!祝大家学习顺利,心想事成,happy new year!!!

  • 相关阅读:
    C++ 学习笔记
    面向对象
    多线程
    Spring-扫描注解原理,注解自动扫描原理分析
    Eclipse 中报错的阅读顺序
    Eclipse 常用技巧及常见问题解决
    JAVA高级复习-自定义泛型类、泛型接口的注意点
    JAVA高级复习-泛型的使用
    IntelliJ IDEA学习笔记连载一IntelliJ IDEA中创建Maven工程
    JAVA高级复习-多线程的创建方式二
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4295961.html
Copyright © 2011-2022 走看看