前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序
这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开。
一、首先在前面代码的基础上来一个简单的信号
1.定义一个全局的整形变量
2.在打开函数中,每次进入打开函数canopen都自减1,
3.当我们不使用时,在realease 中canopen自加1
4.这样就实现了一个简单的信号量,我们编译,测试
当我们使用两个应用程序来同时打开设备时,看看会发生什么:
可以发现,由于我们后台已经打开一个应用程序了,所以,如果此时我们再用另外一个应用程序打开的话,则会报错,can't open
好了,到这里,我们已经基本上实现了一个简陋的信号量程序。
附上驱动代码
1 /******************************
2 linux key_query
3 *****************************/
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
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!nn");
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!nn");
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 %dn",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!nn");
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!nn");
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!nn");
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);