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

发布时间:2024-08-16  

前面我们使用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 //error: 'TASK_INTERRUPTIBLE' undeclared 

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

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    HSC3 CV=PV(当前值 = 预设值) Y Y 33 HSC5 CV=PV N Y 34 PTO2 脉冲计数完成 N Y 35 I7.0 上升沿(信号板) N Y 36 I7.0......
    带制动器的伺服电机其制动器是否已经打开;监视伺服驱动器的面板确认脉冲指令是否输入; d、Run运行指令正常; e、控制模式务必选择位置控制模式; f、伺服驱动器设置的输入脉冲类型和指令脉冲......
    后执行者有效。 微分指令(PLS/PLF)(1)PLS(上升沿微分指令) 在输入信号上升沿产生一个扫描周期的脉冲输出 (2)PLF(下降沿微分指令) 在输入信号下降沿产生一个扫描周期的脉冲输出。利用微分指令......
    来复位积算定时器和计数器; 2)对于同一目标元件,SET、RST可多次使用,顺序也可随意,但最后执行者有效; 6 微分指令(PLS/PLF) 1)PLS(上升沿微分指令) 在输入信号上升沿产生一个扫描周期的脉冲......
    伺服驱动器的进步而将定位死循环控制移入驱动器内执行。(也就是将速度环移到了驱动器内部)。运动控制卡输出脉冲指令来同时控制马达的位置及转速,同时读回encoder位置以作定位修正之用。 不论......
    plc中断的作用是什么呢;  plc这样理解中断功能,在理解中断时,首先要清楚plc的运算周期或者说是扫描周期,有必要说下plc顺控循环执行的流程,这是理解中断的前提,必须要掌握,分为三部分,输入......
    浅析PLC的上升沿与下降沿;有网友留言说:上升沿就是在信号从断开到接通的那一瞬间接通,下降沿就是在信号从接通到断开的那一瞬间接通。但是现在的问题它的实际用处是用在哪一些情况。我身边也有PLC可以做个什么......
    后,计数器的CD端每输入一个脉冲上升沿,计数值就减1,当计数值减到0时,CTD的状态变为1并停止计数。1.指令说明减计数器指令说明如表4-13所示。 表4-13 减计数器指令说明 2.指令使用举例减计数器指令......
    ;= D108 C251]是什么意思? 答:[D<= D108 C251]是触点比较指令,前面带D表示该指令是32位的触点比较指令,比较32位数(D109,D108)的值是否小于等于计数器C251的当......
    中断程序优先单独运行程序处理而且是立即输出不参与整个周期运算。 中断的作用是什么呢,我们知道plc扫描周期是很短的,因此我们很难看出plc顺控执行过程,这里我们不妨假设扫描周期为10s的时间,就是执行全部的程序需要10s的时间,有一......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>