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

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

2015-02-18 李海沿

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

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

 

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

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

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

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

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

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

 

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

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

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

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

可以发现,由于我们后台已经打开一个应用程序了,所以,如果此时我们再用另外一个应用程序打开的话,则会报错,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!\n\n");

 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!\n\n");

 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\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]); 

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!\n\n");

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!\n\n");

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!\n\n");

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 !\n");

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 !\n");

196 

197             break;

198         case version:

199             printk("<0>hello,the version is 0.1.0\n\n");

200             break;

201         default:

202               printk("<0>command error \n");

203             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");

204             printk("<0>command: <key_input> <version>\n\n");

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>\nHello,this is %s module!\n\n",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>\nGoodbye,%s!\n\n",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 !!!\n");

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\n");

41         else{

42             read(fd,key_val,1);

43             printf("%04d key pressed: 0x%x\n",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,否则就无法打开。

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

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

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

 

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

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

 

附上驱动程序源程序:

 

  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!\n\n");

 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!\n\n");

 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\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]); 

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!\n\n");

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!\n\n");

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!\n\n");

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 !\n");

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 !\n");

201 

202             break;

203         case version:

204             printk("<0>hello,the version is 0.1.0\n\n");

205             break;

206         default:

207               printk("<0>command error \n");

208             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");

209             printk("<0>command: <key_input> <version>\n\n");

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>\nHello,this is %s module!\n\n",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>\nGoodbye,%s!\n\n",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.定义信号量

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

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

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

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

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

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

5.编译测试

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

可以发现,当第二个应用程序去申请信号量时,并不会像前面一样直接退出,而是一直在等待信号量到来。

附上驱动程序代码:

 

  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!\n\n");

 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!\n\n");

 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\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]); 

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!\n\n");

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!\n\n");

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!\n\n");

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 !\n");

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 !\n");

205 

206             break;

207         case version:

208             printk("<0>hello,the version is 0.1.0\n\n");

209             break;

210         default:

211               printk("<0>command error \n");

212             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");

213             printk("<0>command: <key_input> <version>\n\n");

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>\nHello,this is %s module!\n\n",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>\nGoodbye,%s!\n\n",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的解析

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

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

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

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

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

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

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

wait_event_interruptible(key_interrupt_wait,ev_press);

那也就不会阻塞

 

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

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

 

4.编译测试

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

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

 

 附上驱动程序代码:

  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!\n\n");

 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!\n\n");

 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\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]); 

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!\n\n");

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!\n\n");

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!\n\n");

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 !\n");

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 !\n");

209 

210             break;

211         case version:

212             printk("<0>hello,the version is 0.1.0\n\n");

213             break;

214         default:

215               printk("<0>command error \n");

216             printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;\n");

217             printk("<0>command: <key_input> <version>\n\n");

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>\nHello,this is %s module!\n\n",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>\nGoodbye,%s!\n\n",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 !!!\n");

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\n",cnt++,key_val[0]);    

40         sleep(5);

41         /*if(ret == 0)

42             printf("time out\n");

43         else{

44             read(fd,key_val,1);

45             printf("%04d key pressed: 0x%x\n",cnt++,key_val[0]);    

46         }*/

47     }

48     return 0;

49 }
View Code

 

 

总结一下:

 

 

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

 

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

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

 

你可能感兴趣的:(信号量)