前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux驱动开发-外部中断的注册使用(按键为例)

Linux驱动开发-外部中断的注册使用(按键为例)

作者头像
DS小龙哥
发布2022-04-08 09:09:05
5K1
发布2022-04-08 09:09:05
举报
文章被收录于专栏:嵌入式项目开发

1. 外部中断介绍

前面有篇文章使用杂项设备完成了按键驱动的编写,实现了按键轮询检测,通过read函数向应用层传递按键值,这篇文章使用按键为例,介绍Linux内核里中断的注册方法,使用中断的方式检测按键是否按下,中断在单片机、设备驱动开发里使用的都非常多,可以更加实时的检测到按键触发的情况。

Linux内核提供了中断的注册接口:

(1)注册中断

代码语言:javascript
复制
头文件	     include\linux\interrupt.h

定义文件	include\linux\interrupt.h

函数原型	int request_irq(unsigned int irq,/*做实参传递给中断服务函数第1个参数*/
			irq_handler_t handler, /*中断服务函数指针*/
           unsigned long flags,
           const char *name,
           void *dev_id); 			/*做实参传递给中断服务函数第2个参数*/

函数功能	向内核注册一个中断服务函数;
当发生中断号为 irq 的中断时候,会执行 handler 指针函数。

函数参数	
irq:中断编号(每个中断源有惟一的编号)。

handler:中断服务函数指针。
          原型 typedef irqreturn_t (*irq_handler_t)(int, void *)。
flag:中断的标志,用来描述本中断的基本特征的。 
      有固定的值,由中断源的特征决定;
      比如外中断有:上升沿,下降沿触发中断这类标志。
name:中断名字, 注册后会出现cat /proc/interrupts
dev_id: 这个参数是传递给中断服务函数。
         对共享中断来说, 这个参数一定有要; 
         当注销共享中断中的其中一个时, 用这个来标识要注销哪一个。 
         对于有惟一入口的中断,可以传递 NULL;
         但是一般来说都会传递一个有意义指针,在中断程序中使用, 以方便编程。

    
返回值	0 表示成功
-EINVAL (无效参数22)表示中断号无效。
-EBUSY (设备或者资源忙16)表示中断已经被占用。

(2)注销中断

代码语言:javascript
复制
void free_irq(unsigned int irq,void * dev_id)
irq: 要注销的中断号
dev_id:其实就是注册时候使用的dev参数,在共享中断必不可少,不能传递NULL。
注意:为了防止在注销时同时发生中断,调用时候,先禁止中断。

(3)中断开启与关闭

代码语言:javascript
复制
禁止中断
void disable_irq_nosync(unsigned int irq);
void disable_irq(unsigned int irq);
参数:irq,要禁止的中断对应的编号。 
注意:在中断服务程序中不能使用 disable_irq 这个函数,否则内核崩溃,可以使用 disable_irq_nosync。
disable_irq:函数调用后,函数不会马上返回,而等待中断程序执行完成才返回,在中断调用会导致死锁。
disable_irq_nosync:调用后,函数马上返回。

使能中断
void enable_irq(unsigned int irq);
参数:irq,要使能的中断对应的编号 

(4)获取irq中断号

代码语言:javascript
复制
int gpio_to_irq(unsigned gpio);

2. 外部中断驱动编写

2.1 按键原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ElkgCQ6V-1648429520818)(https://gitee.com/dsxiaolong/blog-drawing-bed/raw/master/img/image-20211226144741837.png)]

2.2 驱动示例代码

insmod 安装驱动之后就直接注册按键中断,没有注册字符设备框架,当按键按下之后,直接在驱动层通过printk打印数据提示到终端。

代码语言:javascript
复制
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>

/*存放按键的信息*/
struct m_key_info
{
	int gpio;
	char name[50];
	int val;
	int irq;
};

struct m_key_info key_info[]=
{
	{EXYNOS4_GPX3(2),"key_irq_1",0x01},
	{EXYNOS4_GPX3(3),"key_irq_2",0x02},
	{EXYNOS4_GPX3(4),"key_irq_3",0x03},
	{EXYNOS4_GPX3(5),"key_irq_4",0x04},
};


/*
中断服务函数
*/
static irqreturn_t key_irq_handler(int irq, void *dev)
{
    struct m_key_info *p=(struct m_key_info*)dev;
	
	if(gpio_get_value(p->gpio)==0) //判断按键是否按下
	{
		printk("按键值:%#x\n",p->val);
	}
	else
	{
		printk("按键值:%#x\n",p->val|0x80);
	}
	return IRQ_HANDLED;
}

static int __init tiny4412_interrupt_drv_init(void)
{
	int i;
	for(i=0;i<sizeof(key_info)/sizeof(key_info[0]);i++)
	{
		/*1. 获取中断号*/
		key_info[i].irq=gpio_to_irq(key_info[i].gpio);

		/*2. 注册中断*/
		if(request_irq(key_info[i].irq,key_irq_handler,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,key_info[i].name,&key_info[i]))
		{
			printk("中断号%d注册失败:%s\n",key_info[i].irq,key_info[i].name);
		}
	}
    printk("按键中断 驱动注册-安装成功.\n");
    return 0;
}

static void __exit tiny4412_interrupt_drv_exit(void)
{
	/*注销中断*/
	int i=0;
	for(i=0;i<sizeof(key_info)/sizeof(key_info[0]);i++)
	{
		free_irq(key_info[i].irq,&key_info[i]);
	}
    printk("按键中断 驱动注销成功.\n");
}

/*驱动入口*/
module_init(tiny4412_interrupt_drv_init);
/*驱动出口*/
module_exit(tiny4412_interrupt_drv_exit);
/*许可证*/
MODULE_LICENSE("GPL");

2.3 makefile代码

代码语言:javascript
复制
KER_DRI=/home/wbyq/work/linux-3.5/linux-3.5
all:
	make -C $(KER_DRI) M=`pwd` modules
	cp *.ko /home/wbyq/work/rootfs/code -f
	make -C $(KER_DRI) M=`pwd` modules clean
obj-m += interrupt_key.o
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/03/29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 外部中断介绍
  • 2. 外部中断驱动编写
    • 2.1 按键原理图
      • 2.2 驱动示例代码
        • 2.3 makefile代码
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档