IMX257实现GPIO-IRQ中断按键驱动程序

发布时间:2024-08-16  

    昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有按键,应用程序while循环中的read函数也不断的在运行,严重的导致了CPU资源的浪费。


    本文中,我们在前面按键查询驱动程序的基础上来修改。


    大概介绍一下设计思路吧:


    和前面的差不多,当我们加载驱动时,首先在init函数中,对GPIO功能进行模式设置,都设置为GPIO模式,然后申请GPIO引脚的内存,


接着,当我们应用程序使用ioctl函数的gpio_input命令时,将所有的GPIO引脚设置为输入,并且22K上拉模式,当应用程序使用read函数读取时,如果按键没有按下,则会在read函数中睡眠(可被中断唤醒),交出CPU的使用权,当按键按下时,首先会在中断程序中进行唤醒操作,在read函数中接着运行,读取GPIO引脚的电平,并且将数据从内核空间传递到用户空间中,并且打印出来。


    最后,当我们不要用驱动程序时,rsmod会调用exit函数,释放所有我们已经申请的GPIO资源。


    好了,大概的思路就是这样,和前面的查询驱动程序,差不多,只不过就加了一个中断,和睡眠而已。


附上驱动程序代码:


  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 

 19 #include 'mx257_gpio.h'

 20 #include 'mx25_pins.h'

 21 #include 'iomux.h'

 22 

 23 #define Driver_NAME 'key_interrupt'

 24 #define DEVICE_NAME 'key_interrupt'

 25 

 26 #define GPIO2_21    MX25_PIN_CLKO

 27 #define GPIO3_15    MX25_PIN_EXT_ARMCLK

 28 #define GPIO2_10    MX25_PIN_A24

 29 #define GPIO2_11    MX25_PIN_A25

 30 #define GPIO2_8     MX25_PIN_A22

 31 #define GPIO2_9     MX25_PIN_A23

 32 #define GPIO2_6     MX25_PIN_A20

 33 #define GPIO2_7     MX25_PIN_A21

 34 //command

 35 #define key_input     0

 36 #define version        1

 37 

 38 //interrupt head

 39 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);

 40 static volatile unsigned char ev_press;  

 41 

 42 static int major=0;

 43 

 44 //auto to create device node

 45 static struct class *drv_class = NULL;

 46 static struct class_device *drv_class_dev = NULL;

 47 

 48 

 49 /* 应用程序对设备文件/dev/key_query执行open(...)时,

 50  * 就会调用key_open函数*/

 51 static int key_open(struct inode *inode, struct file *file)

 52 {

 53     printk('<0>function open!nn');

 54     

 55     return 0;

 56 }

 57 

 58 /* 中断程序key_irq */

 59 static irqreturn_t key_irq(int irq, void *dev_id)

 60 {

 61     //发生了中断

 62     printk('<0>function interrupt key_irq!nn');

 63     ev_press = 1;

 64     wake_up_interruptible(&key_interrupt_wait);

 65 

 66     return IRQ_RETVAL(IRQ_HANDLED);

 67 }

 68 

 69 

 70 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

 71 {

 72     int ret;

 73     //nt cnt=0;

 74     unsigned char key_vals[8];

 75 

 76     //如果按键没有按下,没有中断,休眠

 77     wait_event_interruptible(key_interrupt_wait,ev_press);

 78 

 79     // reading the pins value

 80     key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;

 81     key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;

 82     key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;

 83     key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;

 84     key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;

 85     key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;

 86     key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;

 87     key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;

 88     

 89     ret = copy_to_user(buff,key_vals,sizeof(key_vals));

 90     if(ret){

 91         ;

 92     }

 93     ev_press = 0;

 94     //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]); 

 95 

 96     return sizeof(key_vals);

 97 }

 98 

 99 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

100 {

101     printk('<0>function write!nn');

102     

103     return 1;

104 }

105 

106 static int  key_release(struct inode *inode, struct file *filp)

107 {

108     printk('<0>function release!nn');

109     //释放中断

110     free_irq(IOMUX_TO_IRQ(GPIO2_21), (void *)1);

111     //free_irq(IOMUX_TO_IRQ(GPIO3_15), (void *)1);

112     free_irq(IOMUX_TO_IRQ(GPIO2_11), (void *)1);

113     free_irq(IOMUX_TO_IRQ(GPIO2_10), (void *)1);

114     free_irq(IOMUX_TO_IRQ(GPIO2_9), (void *)1);

115     //free_irq(IOMUX_TO_IRQ(GPIO2_8), (void *)1);

116     free_irq(IOMUX_TO_IRQ(GPIO2_7), (void *)1);

117     free_irq(IOMUX_TO_IRQ(GPIO2_6), (void *)1);

118     return 0;

119 }

120 

121 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)

122 {

123     int ret;

124     printk('<0>function ioctl!nn');

125     switch (command) {

126         case key_input:    

127             //设置所有的引脚为输入

128             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));

129             gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));

130             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));

131             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));

132             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));

133             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));

134             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));

135             gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));

136             printk('<0>have setting all pins to gpio input mod !n');

137             //设置GPIO引脚为上拉模式

138             mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

139             mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

140             //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

141             mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

142             mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

143             mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

144             mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

145             //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

146 

147             //设置GPIO引脚中断  ,下降沿触发

148             request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_7', (void *)1);

149             request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_6', (void *)1);

150             request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_9', (void *)1);

151             request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_10', (void *)1);

152             request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_11', (void *)1);

153             request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_21', (void *)1);

154             //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO3_15', (void *)1);

155             //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, 'key_GPIO2_8', (void *)1);

156             printk('<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !n');

157 

158             break;

159         case version:

160             printk('<0>hello,the version is 0.1.0nn');

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

相关文章

    要存储在两个主要的地方 A、电脑中,我们编写的程序源代码(主程序和中断程序都存储在main.c中) B、编译完成形成二进制代码下载到单片机的程序存储器中(ProgramFlash) a、首先我们要找到中断程序......
    中断是什么?PLC的三大类中断事件;中断的概念:中断是计算机独有的一种工作方式;在主程序执行的过程中,中断主程序的执行;在执行子程序的过程中,中断子程序的执行。中断程序......
    正在删除 s3c6410裸机程序(2);  本来以为自己可以很快就把中断程序写好的,但是没想到知道昨天才有了点眉目,虽然还不知道对不对,但是写出来给大家批评指正。   笔者......
    s3c6410裸机程序(2);本来以为自己可以很快就把中断程序写好的,但是没想到知道昨天才有了点眉目,虽然还不知道对不对,但是写出来给大家批评指正。 笔者自从上次写了一个轮询式的按键驱动LED灯之后就一直在弄中断......
    以一次动作所需要的时间就是运算周期也叫扫描时间,那么中断与扫描周期有什么联系呢,中断就是不按照从上到下顺序的完整执行,而是中断程序优先单独运行程序处理而且是立即输出不参与整个周期运算。   中断的作用是什么呢,我们知道plc扫描......
    入口地址送入PC,PC是程序指针,CPU取指令就根据PC中的值,PC中是什么值,就会到什么地方去取指令,所以程序就会转到中断入口处继续执行。这些工作都是由硬件来完成的,不必我们去考虑。这里还有个问题,大家......
    名称重定义 重新定义管脚名称,符合 MC Workbench 生成的命名 3.9 规划 NVIC 的中断优先级 这边特别注意中断优先级别的设定,将影响到程序运行。 3.10 不生成电机相关的中断程序......
    优先级别的设定,将影响到程序运行。 3.10 不生成电机相关的中断程序 因为电机相关的中断程序中电机库中已经有了,这边不使用 CubeMx 生成中断代码 3.11 系统其他的配置 分别配置 RCC......
    ,所处理的紧急事件或另一项工作,就叫做中断程序,处理完问题再回过来继续原来的工作。 PLC同样也有中断,CPU正常执行程序,如中途发生的系统认定的动作或参数达到设定要求,则中断程序执行,去处理所设定的程序......
    mode bits设置为0x12,将I位置为1,屏蔽IRQ中断,将T位置为1,进入ARM状态)        保存返回地址:将下一条指令的地址(被打断程序)保存在LR(异常模式下LR_excep)中......

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

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

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

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

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

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

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