在驱动中定义中断
2015-11-23 10:23
190 查看
1. 中断
涉及头文件:
#include <linux/interrupts>
中断的注册
int
request_irq(
unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char *name,
void *dev
);
@irq: 中断号
外部中断号:
a. irqnum gpio_to_irq(gpio);
EXYNOS4X12_GPM4();
//arm/mach-exynos/include/mach/gpio.h
b. IRQ_EINT(eintnum);
//arm/plat-samsung/include/plat/irqs.h
内部中断:
arch/arm/mach-exynos/include/mach/irqs.h
@handler: 中断处理函数
typedef irqreturn_t (*irq_handler_t)(int, void *);
中断处理函数的返回值:IRQ_HANDLED, IRQ_NONE;
型参:第一个int对应的是发生中断的中断号。
第二个void*型的实参是注册中断时的第5个参数dev。
@flags: 注册中断的标记
#define IRQF_TRIGGER_NONE 0x00000000
#define IRQF_TRIGGER_RISING 0x00000001
#define IRQF_TRIGGER_FALLING 0x00000002 //
#define IRQF_TRIGGER_HIGH 0x00000004 //高电平
#define IRQF_TRIGGER_LOW 0x00000008 //低电平
#define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
#define IRQF_SHARED 0x00000080
@name: 中断的名字
@dev: 传给中断处理函数的第二参数的实参
中断的共享
2. 中断的下半部
-------------------------------------------------------------------
实现中断的下半部机制1: tasklet 机制
涉及到的核心结构体:
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long); //下半部的任务函数
unsigned long data; //下半部的任务函数需要的参数
};
使用步骤:
首先,实例化一个struct tasklet_struct的对象,代表下半部将被内核调度器调度的任务。
a. struct tasklet_struct task;
tasklet_init(&task, service_bh, dev);
b. DECLARE_TASKLET(task, service_bh, dev); //task是给tasklet起的名字,service_bh是执行tasklet时调用的函数,dev是一个用来传递给tasklet函数的ul类型的值
其次,在中断处理函数(上半部)中将下半部的任务交给调度器调度
tasklet_schedule(&task);
最后,如果写的是驱动模块,需要在模块的出口移除下半部的任务
tasklet_kill(&task);
-------------------------------------------------------------------
中断下半部的实现机制2: 工作队列机制
涉及到的核心结构体:
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func; //下半部的任务函数
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
//下半部任务函数的类型:
typedef void (*work_func_t)(struct work_struct *work);
实现步骤:
首先,实例化对象
方法1,
struct work_struct work;
INIT_WORK(&work, service_bh);
方法2,
DECLARE_WORK(work, service_bh); \
其次,在中断的上半部将下半部的任务交给调度器调度
schedule_work(&work);
最后,驱动模块的出口需要等待下半部的任务完成
flush_work(&work);
涉及头文件:
#include <linux/interrupts>
中断的注册
int
request_irq(
unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char *name,
void *dev
);
@irq: 中断号
外部中断号:
a. irqnum gpio_to_irq(gpio);
EXYNOS4X12_GPM4();
//arm/mach-exynos/include/mach/gpio.h
b. IRQ_EINT(eintnum);
//arm/plat-samsung/include/plat/irqs.h
内部中断:
arch/arm/mach-exynos/include/mach/irqs.h
@handler: 中断处理函数
typedef irqreturn_t (*irq_handler_t)(int, void *);
中断处理函数的返回值:IRQ_HANDLED, IRQ_NONE;
型参:第一个int对应的是发生中断的中断号。
第二个void*型的实参是注册中断时的第5个参数dev。
@flags: 注册中断的标记
#define IRQF_TRIGGER_NONE 0x00000000
#define IRQF_TRIGGER_RISING 0x00000001
#define IRQF_TRIGGER_FALLING 0x00000002 //
#define IRQF_TRIGGER_HIGH 0x00000004 //高电平
#define IRQF_TRIGGER_LOW 0x00000008 //低电平
#define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
#define IRQF_SHARED 0x00000080
@name: 中断的名字
@dev: 传给中断处理函数的第二参数的实参
中断的共享
2. 中断的下半部
-------------------------------------------------------------------
实现中断的下半部机制1: tasklet 机制
涉及到的核心结构体:
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long); //下半部的任务函数
unsigned long data; //下半部的任务函数需要的参数
};
使用步骤:
首先,实例化一个struct tasklet_struct的对象,代表下半部将被内核调度器调度的任务。
a. struct tasklet_struct task;
tasklet_init(&task, service_bh, dev);
b. DECLARE_TASKLET(task, service_bh, dev); //task是给tasklet起的名字,service_bh是执行tasklet时调用的函数,dev是一个用来传递给tasklet函数的ul类型的值
其次,在中断处理函数(上半部)中将下半部的任务交给调度器调度
tasklet_schedule(&task);
最后,如果写的是驱动模块,需要在模块的出口移除下半部的任务
tasklet_kill(&task);
-------------------------------------------------------------------
中断下半部的实现机制2: 工作队列机制
涉及到的核心结构体:
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func; //下半部的任务函数
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
//下半部任务函数的类型:
typedef void (*work_func_t)(struct work_struct *work);
实现步骤:
首先,实例化对象
方法1,
struct work_struct work;
INIT_WORK(&work, service_bh);
方法2,
DECLARE_WORK(work, service_bh); \
其次,在中断的上半部将下半部的任务交给调度器调度
schedule_work(&work);
最后,驱动模块的出口需要等待下半部的任务完成
flush_work(&work);
相关文章推荐
- 时间转换,自适应文字高度,手机和邮箱验证
- background-size background-positon合并的写法
- Oracle--用户管理与权限分配
- .top域名总量15强:西数易名中国数据占前三
- Caused by: java.lang.IllegalArgumentException: Can't use FLAG_RECEIVER_BOOT_UPGRADE here的解决
- 在ubuntu上软件安装的几种格式dev,rpm,bin,tar.gz
- 读写XML
- ORACLE用JDBC操作CLOB
- 使用JavaMail接收邮件的示例
- Unity3D游戏开发之C++插件接入
- 最简单Android音乐播放器
- Android编程实现泡泡聊天界面实例详解(附源码)
- ie6,ie7常见兼容性问题总结
- js日期时间选择器bootstrap
- android android studio使用教程(五)gradle环境配置
- JSP基本指令
- selenium python (一) 开发环境搭建
- __weak
- iOS开发者遇到审核失败的原因及解决办法
- 第九章 控制抽象