您当前的位置:首页 > 今日分享头条 > 正文

linux中断处理程序(Linux中断编程)

linux中断处理程序(Linux中断编程)

Linux中断编程中断:是指CPU运行过程中发生某种异常事件,需要CPU先暂停当前工作,再处理新产生的异常事件,然后返回暂停的事件继续执行。比如我们正在用手机进行微信文章聊天,突然有人打来电话。此时手机的处理方法是,来电铃声响起,通知用户来电。

中断是为了处理未来可能发生的事件。中断事件也称为异常事件。有了中断处理,CPU处理效率可以大大提高。

在单片机中,我们也经常使用中断模式来处理一些紧急事件,这有助于我们快速响应一些实时事件。所以我们写中断服务函数的时候,代码尽量简洁,一定不能处理无限循环。如果有很多事情要处理,就要在中断中设置标志位,然后把逻辑代码放到主函数中实现。

在Linux内核中,我们通常将中断分为上半部分和下半部分。顶层部分主要处理耗时短的代码(像单片机中设置标志位),启动底层部分代码;底层部分主要处理耗时较长的代码,以及中断响应完成后的事件处理。

1.在Linux下使用外部中断,需要完成中断号(irq)、中断服务功能和中断触发方式(电平触发和边沿触发)三个中断元素的配置。

1.1相关接口函数获取中断号gpio_to_irq为函数获取Linux内核中的pin中断号提供了便利。

GPIO _ to _ irq (unsigned gpio)函数function:获取中断号返回值:成功返回对应GPIO寄存器中断请求的中断号IRQ _ IRQ int request _ IRQ(Unsigned int IRQ,IRQ _ handler _ t handler,Unsigned long flags,constchar * name,void * dev)函数function:寄存器中断参数:irq -中断号,GPIO _ to _ irq函数的返回值。处理程序中断服务功能。服务原型:typedef IRQ return _ t(* IRQ _ handler _ t)(int,void *);标志-中断触发模式。#定义irqf _ trigger _ rising0x 00000001//上升沿#定义irqf _ trigger _ falling0x 0000002//下降沿#定义irqf _ trigger _ high0x 0000004//高电平#定义irqf _ trigger _ Low0x 0000008//低电平#定义irqf _ shared0x 0000080//共享中断名称-中断注册标志。传递给中断服务函数的Dev参数。返回值:成功返回0,失败返回其他值。服务函数typedef IRQ return _ t(* IRQ _ handler _ t)(int,void *);函数:中断服务函数参数:第一个参数是中断号;第二个参数是注册函数传入的参数dev的返回值:enum irqreturn {IRQ_NONE=(0 0),//如果不是为了这个中断,就返回这个值。共享中断中只会用到IRQ _ handled=(10),//正确执行中断程序会返回这个值,常用的有IRQ _ wake _ thread=(11),//注意:IRQ return _ t(* IRQ _ handler _ t)(int,void *);有休眠的函数,比如msleep函数,不能出现在函数中;该函数必须返回值。

Unregister free _ IRQ free _ IRQ(unsigned int IRQ,void * dev _ id)函数功能:unregister中断参数:irq -中断号,gpio_to_irq函数返回值。传递给中断服务函数的Dev参数。需要和注册一致。2.工作队列的中断处理功能分为上半部分中断和下半部分中断。代码的上面部分实现为中断服务函数,而代码的下面部分可以由工作队列完成。

2.1工作队列简介在操作系统中,如果我们需要执行一个工作进程,往往需要创建一个任务加入内核的调度队列。一个任务对应一个处理功能。如果您想要执行不同的事务,您需要创建多个不同的任务。作为任务CPU调度的基本单位,任务数量越大,调度成本越高。工作队列机制简化了基本的任务创建和处理机制。一个工作队列对应一个实体任务处理,工作队列中可以挂载多个工作实体,每个工作可以对应不同的工作处理功能。也就是说,用户只需要创建一个工作队列,就可以完成多个具有不同处理功能的工作队列。

工作队列还有一个推迟工作执行的机制。工作队列可以将工作延期,交给一个内核线程执行,也就是说,下半部分可以在进程的上下文中执行。最重要的是允许工作队列重新调度甚至休眠。

工作队列的处理取决于任务task。一个工作队列会创建与之关联的任务task,一个工作队列会挂载多个作业进行处理,每个作业都有一个作业处理功能。当工作队列被调度时,即其相关联的任务被运行时,在每个任务的调度期间,将从工作队列中按顺序取出一个工作进行处理。workqueue模块初始化时会创建一个系统默认的工作队列,用户可以根据需要将工作添加到队列中执行。

2.2工作相关函数接口工作结构structwork _ struct #包含struct work _ struct { atomic _ long _ tdata;struct list_head条目;work _ func _ t func# ifdefconfig _ lockdepstruct lock dep _ maplockdep _ map;# endif };在工作结构中,我们需要关心的成员是工作处理函数:work_func_t func,简单来说就是一个作业会有一个处理函数。处理函数的原型如下:

# include typedef void(* work _ func _ t)(struct work _ struct * work);初始化作业init _ work #定义init _ work (_ work,_ func)函数作用:初始化作业,在宏中实现形参:_ WORK-工作结构指针_ func-工作处理函数WORK schedule _ WORK int schedule _ WORK(struct work_struct * WORK)2.3工作队列使用步骤定义工作结构struct WORK _ struct并初始化work INIT _ WORK;编写工作处理函数void(* work _ func _ t)(struct work _ struct * work);在适当的地方调整调度工作(一般在中断的上半部分);2.4工作队列使用示例下面以key为例实现中断模式key检测。下半部分代码由工作队列处理,设备注册由杂项设备框架实现。

k1gpx 3 _ 2k 2-gpx 3 _ 3k 3-gpx 3 _ 4k 4-gpx 3 _ 5 # include # include # include # include # include # include # include # include # include # include # include struct work _ struct key _ work;struct _ KEY { unsigned int gpio;char name[20];int IRQ;int key _ num;};static struct _ KEY KEY _ GPIO _ PIN[]={ { exy nos 4 _ gpx 3(2),key1 ,0,1},{EXYNOS4_GPX3(3),key2 ,0,2},{EXYNOS4_GPX3(4),key3 ,0,3},{EXYNOS4_GPX3(5),key4 ,0,4},};静态struct _ KEY * KEY _ p;静态无符号int key _ valvoid key _ work _ func(struct work _ struct * work){ m sleep(30);if(gpio _ get _ value(key _ p-gpio)==0){ printk(密钥% d按下n ,key _ p-key _ num);} else { printk(密钥%d松开n ,key _ p-key _ num);} key _ val=key _ p-key _ num;}static IRQ return _ t KEY _ IRQ _ handler(int IRQ,void * dev){ KEY _ p=(struct _ KEY *)dev;schedule _ work(key _ work);return IRQ _ HANDLED;} static int key _ open(struct inode * inode,struct file * file){ printk(设备打开成功n’);返回0;} static ssize _ t key _ read(struct file * file,char __user *buf,size_t cnt,loff _ t * seek){ int RES=copy _ to _ user(buf,key_val,4);key _ val=0;返回4分辨率;} static int key _ release(struct inode * inode,struct file * file){ printk(设备关闭成功n’);返回0;}static struct file _ operations key _ fops={ .所有者=这个模块,.open=key_open,.read=key_read,.释放=按键释放,};static struct misc device key _ misc dev={ .minor=MISC_DYNAMIC_MINOR,.name=tiny4412 _ key ,.fops=key_fops,};static int _ _ init tiny 4412 _ key _ module _ init(void){ int I=0;int resprintk('你好,驱动注册成功n’);INIT_WORK(key_work,key _ WORK _ func);for(I=0;i(key_gpio_pin)

审核汤梓红

标签:函数工作中断


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 华为股票行情查询(华为的股票代码是多少)

下一篇: 怎么彻底删除电脑上的软件,如何用电脑本身彻底删除电脑上的软件呢(售价23.29-52.99万元)



推荐阅读