您当前的位置:首页 > 美文摘抄 > 内容

linux中断驱动编程_Linux中断编程

linux中断驱动编程_Linux中断编程

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

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

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

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

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

1.1相关接口函数获取中断号gpio_to_irq在Linux内核中提供了一个方便的获取pin中断号的函数。

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

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

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

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

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

2.2工作相关函数接口工作结构struct work _ struct # includes struct network _ struct { atomic _ long _ tdata;struct list_head条目;work _ func _ t func# ifdefconfig _ lockdepstruct lock deep _ map lock deep _ map;# endif };在工作结构中,我们需要关心的成员是工作处理函数:work_func_t func。简单来说,一个作业对应一个处理功能。工作处理功能的原型如下:

# include typedef void(* work _ func _ t)(struct work _ struct * work);初始化工作INIT _ Work # define INIT _ Work(_ Work,_ func)函数:初始化工作,以宏的形式实现形参:_ Work-工作结构体指针_ func-工作处理函数Work schedule _ Work(struct work_struct * Work)2.3工作队列使用步骤定义工作结构struct Work _ struct并初始化工作INIT _ Work;编写工作处理函数void(* work _ func _ t)(struct work _ struct * work);将工作分派到合适的地方(一般在中断的上半部分);2.4工作队列使用示例:以按键为例实现中断按键检测,通过工作队列处理下半部分代码,通过杂项设备框架实现设备注册。

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(' key % d按下n 'key _ p-key _ num);}else {printk(' key%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)

审核汤梓红


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

上一篇: 汉阳馆(关于汉阳馆的介绍)

下一篇: 网站查询ip地址查询(怎么查网站的ip地址)



推荐阅读

网站内容来自网络,如有侵权请联系我们,立即删除! | 软文发布 | 粤ICP备2021106084号