linux,中断处理_第1页
linux,中断处理_第2页
linux,中断处理_第3页
linux,中断处理_第4页
linux,中断处理_第5页
已阅读5页,还剩6页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、中断处理本章目标掌握设备驱动中中断处理例程的实现方法本章结构一、 中断处理程序架构1.什么是中断? 中断是指CPU在执行程序的过程中,出现了某些突发事件 CPU必须暂停执行当前程序,转去处理突发事件 处理完毕后CPU又返回原程序被中断的位置并继续执行。 2.中断分类 按中断来源分类: 内部中断 外部中断 按中断是否可屏蔽分类: 可屏蔽中断 不可屏蔽中断(NMI 按中断入口跳转方法的不同分类 向量中断 非向量中断 二、 安装中断处理例程1.申请和释放irq / 申请中断int request_irq(unsigned int irq,void(*handler(int,void*,struct

2、pt_regs*,unsigned long irqflag,const char *devname, void *dev_id;参数1:中断号,所申请的中断向量,比如EXIT0、uart中断等参数2:中断服务程序参数3:中断属性设置/ SA_INTERRUPT, 快速中断,禁止其他中断/ SA_SHIRQ, 共享中断/ SA_SAMPLE_RANDOM, 中断可能被用来产生随机数/ dev_id: 在共享中断时用于区分不同的中断处理程序参数4:中断名字,cat /proc/interrupts 可察看系统中断申请与使用情况参数5:中断参数,作为共享中断时的中断区别参数/ 释放中断void f

3、ree_irq(unsigned int irq, void *dev_id; 参数1:所要清除中断服务程序的中断号 参数2:中断参数,同申请时的值一致2.申请和释放IRQ实例/*中断处理函数*/irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs/*中断处理的具体内容*/ /*设备驱动模块加载函数*/int _init xxx_init(void/*申请中断*/result = request_irq(xxx_irq, xxx_interrupt, SA_INTERRUPT, “xxx”, NULL;/*设

4、备驱动模块卸载函数*/void _exit xxx_exit(void/*释放中断*/free_irq(xxx_irq,NULL; 3.禁用/使能单个中断 void disable_irq(int irq;void disable_irq_nosync(int irq;void enable_irq(int irq;void local_irq_save(unsigned long flags;void local_irq_disable(void;void local_irq_restore(unsigned long flags;void local_irq_enable(void;三、

5、中断顶半部和底半部1.为什么将中断处理程序分成顶半部和底半部?需求: 中断处理要求尽快结束,而不能使中断阻塞的时间过长 而有些处理例程确实要完成耗时的任务 解决方案 :顶半部,让中断阻塞尽可能的短 底半部,完成耗时的任务 顶半部: 是实际响应中断的例程 用request_irq注册的中断例程 它在很短的时间内完成 底半部: 被顶半部调度,并在稍后更安全的时间内执行的例程。 四、 实现底半部的机制 tasklet Work queue(工作队列二者的区别 tasklet 速度快,优先选择 原子操作,运行于中断上下文,基于软中断的机制 Work queue(工作队列高延迟 允许休眠,运行于进程上下

6、文 1、tasklet的使用声明tasklet DECLARE_TASKLET(name, function, data; 例如:void xxx_do_tasklet(unsigned long;DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, data; /* 定义一个 tasklet 结构xxx _tasklet ,与xxx _tasklet_func(data 函数相关联 */ void tasklet_schedule(struct tasklet_struct *t 在需要调度 tasklet 的时候引用一个 tasklet_schedule

7、(函数就能使系统在适当的时候进行调度运行,如下所示: tasklet_schedule(&xxx _tasklet;2、tasklet使用模板 /*定义tasklet和底半部函数并关联*/void xxx_do_tasklet(unsigned long;DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0;/*中断处理底半部*/void xxx_do_tasklet(unsigned long /*中断处理顶半部*/irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *

8、regstasklet_schedule(&xxx_tasklet;3、Work queue(工作队列的使用创建新的工作队列 /一个工作队列可对应多个内核线程struct workqueue_struct *create_workqueue(const char *name;/一个工作队列对应单个内核线程struct workqueue_struct *create_singlethread_workqueue(const char *name;向工作队列提交任务,首先填充一个work_struct 结构 DECLARE_WORK(name,void(*function(void *,

9、void *data;INIT_WORK(struct work_struct *work,void(*function(void *,void *data;PREPARE_WORK(struct work_struct *work,void(*function(void *,void *data 提交任务 int queue_work(struct workqueue_struct *queue, struct work_struct *work;int queue_delayed_work(struct workqueue_struct *queue, struct work_struct

10、 *work, unsigned long delay; 取消某个队列的入口项 int cancel_delayed_work(struct work_struct *work; != 0:内核会确保不会初始化给定入口项的执行 =0:则说明该入口项已经在其他处理器上运行 因此在cancel_delayed_work返回后可能仍在运行,怎么办?之后,需要清工作队列 void flush_workqueue(struct workqueue_struct *queue; 销毁工作队列 void destroy_workqueue(struct workqueue_struct *queue; 共享

11、工作队列 可能驱动不需要自己的工作队列,只是偶尔地向工作队列添加任务 使用内核提供的共享的默认工作队列 不应该长期独占该队列,即不能长时间休眠 更长的时间延迟 使用共享队列 初始化 INIT_WORK(struct work_struct *work,void(*function(void *,void *data; 调度 int schedule_work(struct work_struct *work;int schedule_delayed_work(struct work_struct *work,unsigned long delay;刷新 void flush_scheduled

12、_work(void; 4、Work queue的使用模板 /*定义工作队列和关联函数*/struct work_struct xxx_wq;void xxx_do_work(unsigned long;/*中断处理底半部*/void xxx_do_work(unsigned long/*中断处理顶半部*/irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regsschedule_work(&xxx_wq; /*设备驱动模块加载函数*/int _init xxx_init(void/*申请中断*/resul

13、t = request_irq(xxx_irq, xxx_interrupt, SA_INTERRUPT, “xxx”,NULL;/*初始化工作队列*/INIT_WORK(&xxx_wq, (void (*(void * xxx_do_work, NULL; 5、中断共享共享中断的多个设备在申请中断时都应使用SA_SHIRQ标志 设备结构指针可以作为request_irq(, void *dev_id)的最后一个参数dev_id 传入。 在中断到来时,所有共享该中断的中断处理程序都会被执行,它们会根据硬件中断寄存器中的信息判断是否是本设备的中断,若不是,应迅速返回。6、共享中断使用模板 /*中断处理顶半部*/irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regsint status = read_int_status(;/获知中断源 if(!is_myint(dev_int, status /判断是否是本设备中断 return

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论