字符设备驱动第十二课-----中断
来源:互联网 发布:淘宝的权重是什么意思 编辑:程序博客网 时间:2024/05/17 09:03
概述
1.中断描述表
是一个数组,每个元素是一个结构体,描述一个中断
<include/linux/interrupt.h>struct irqaction { irq_handler_t handler; //中断服务子程序函数指针 void *dev_id; //设备标识 void __percpu *percpu_dev_id; struct irqaction *next; //指向下一个描述符 irq_handler_t thread_fn; struct task_struct *thread; struct irqaction *secondary; unsigned int irq; //IRQ线 unsigned int flags; //中断标志 unsigned long thread_flags; unsigned long thread_mask; //中断掩码 const char *name; //IO设备名 struct proc_dir_entry *dir; //指向IRQ相关的/proc/irq/n目录描述符} ____cacheline_internodealigned_in_smp;
2.
函数接口
1.中断总开关
/** 功能:禁止所有中断*/raw_local_irq_save(x)
/** 功能:使能所有中断*/raw_local_irq_enable()
2.申请中断:
<include/linux/interrupt.h>/** 功能;注册中断* 输入参数:unsigned int irq: 软中断号* irq_handler_t handler:中断服务程序指针* unsigned long flags: 触发方式* const char *name: 名字* void *dev: 设备* 返回值:成功:0 失败:负数**/request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
/** 功能;注册中断* 输入参数:struct device *dev: 设备句柄* unsigned int irq: 软中断号* irq_handler_t handler:中断服务程序指针* unsigned long flags: 触发方式* const char *devname: 设备名 * void *dev_id: 设备ID* 返回值:成功:0 失败:负数**/devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
3.注销中断:
/** 功能:注销中断* 输入参数:unsigned int irq:中断号* void *dev: 注册中断时怎么写,这里就怎么写*/void free_irq(unsigned int irq,void *dev);
/** 功能:注销中断* 输入参数:struct device *dev; 设备句柄* unsigned int irq: 中断号* void *dev: 注册中断时怎么写,这里就怎么写*/extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
3.触发方式宏:
<include/linux/interrupt.h>#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 | \ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)#define IRQF_TRIGGER_PROBE 0x00000010#define IRQF_SHARED 0x00000080 //共享中断
4.中断服务子函数:
/** 功能:中断服务子程序* 输入参数: int irq: 软中断号* void *dev 设备ID,一般为NULL* 返回值:枚举量: enum irqreturn {* IRQ_NONE = (0 << 0),//处理失败* IRQ_HANDLED = (1 << 0),//处理成功* IRQ_WAKE_THREAD = (1 << 1),//* };*/enum irq_handle(int irq,void *dev);
5.从设备树中选出特定的gpio:
<include/linux/of_gpio.h>/** 功能:从指定节点中提取指定属性(提取GPIO)* 输入参数:struct device_node *fsnd: 设备节点* const char *nasme; 属性名字* int index: 索引(属性名下的第几个cell)* 返回值: gpio的cell编号*/int of_get_named_gpio(struct device_node *fsnd, const char *nasme, int index);
<include/linux/gpio.h>/** 功能:判断上一步找出的标号是否是gpio* 输入参数:int number:GPIO编号* 返回值: */bool gpio_is_valid(int number)
6.为gpio指定中断号:
<include/linux/gpio.h>/** 功能:将gpio的复用功能能设置成中断功能* 输入参数:unsigned int gpio: gpio号* unsigned long flags: 模式,如GPIOF_IN(定义在include/linux/gpio.h中的宏)* const char *label: 本gpio名字* 返回值:成功:0 失败:负数*/int gpio_request_one(unsigned int gpio, unsigned long flags, const char *label)
<include/linux/gpio.h>/** 功能:为gpio申请一个软中断号* 输入参数:unsigned int gpio: gpio号* 返回值:成功:软中断号 失败:负数,其绝对值是错误码*/ int gpio_to_irq(unsigned int gpio)
<include/linux/gpio.h>/** 功能:释放gpio* 输入参数:unsigned gpio: gpio号* 返回值:none*/void gpio_free(unsigned gpio)
工程实例
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/of.h>#include <linux/of_gpio.h>#include <linux/of_irq.h>#include <linux/interrupt.h>#include <linux/gpio.h>static int irq;static int gpio;/*自己写的中断服务回调函数*/static irqreturn_t handler_t(int irq, void *dev){ printk(KERN_INFO "%s : %s : %d - ok.\n", __FILE__, __func__, __LINE__); return IRQ_HANDLED;}static int __init demo_init(void){ struct device_node *np = NULL; int ret; printk(KERN_INFO "%s : %s : %d - ok.\n", __FILE__, __func__, __LINE__); np = of_find_node_by_name(NULL, "key");//从设备树中找到key这个设备 if(NULL == np){ return -EINVAL; } gpio = of_get_named_gpio(np, "key-intr", 0);//从设备中的key-intr属性域的cell0中找出gpio if(gpio_is_valid(gpio)){//判断是不是一个可用的gpio号 ret = gpio_request_one(gpio, GPIOF_IN, "key-intr");//将这个gpio的引脚复用功能设置成中断功能 if(ret){ printk(KERN_INFO "%s : %s : %d - gpio_request_one fail.\n", __FILE__, __func__, __LINE__); return ret; } irq = gpio_to_irq(gpio);//为gpio申请一个软中断号 if(0 > irq){ printk(KERN_INFO "%s : %s : %d - gpio_to_irq fail.\n", __FILE__, __func__, __LINE__); return irq; } ret = request_irq(irq, handler_t, IRQF_TRIGGER_RISING, "demo", NULL);//将申请到的软中断号注册进内核(绑定回调函数) if(ret){ printk(KERN_INFO "%s : %s : %d - request_irq fail.\n", __FILE__, __func__, __LINE__); return ret; } }else{ printk(KERN_INFO "%s : %s : %d - of_get_named_gpio fail.\n", __FILE__, __func__, __LINE__); return gpio; } return 0;}static void __exit demo_exit(void){ printk(KERN_INFO "%s : %s : %d - ok.\n", __FILE__, __func__, __LINE__); free_irq(irq, NULL); //注销软中断号 gpio_free(gpio); //注销gpio号}module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Farsight");MODULE_DESCRIPTION("Demo for kernel module");
0 0
- 字符设备驱动第十二课-----中断
- 字符设备驱动----中断程序
- 字符设备驱动--外部中断
- 字符设备驱动之中断按键驱动
- 字符设备驱动之Buttons-中断
- Linux字符设备驱动之中断按键
- 字符设备驱动-中断方式操控按键
- 字符设备驱动-----按键驱动(中断+poll机制)
- 字符设备驱动-----按键驱动(中断+poll机制)
- 字符设备驱动--中断方式下的按键驱动
- 韦东山第12课-字符设备、中断方式查询驱动
- 字符设备驱动之Buttons-中断上下部(tasklet)
- 字符设备驱动之笔记-中断处理过程情景分析
- 字符设备驱动之笔记-中断上下部
- 基于platform总线的中断(按键)字符设备驱动设计
- 字符设备驱动之按键中断——FS2410
- 基于platform总线的中断(按键)字符设备驱动设计
- 基于platform总线的中断(按键)字符设备驱动设计
- 【Unity】打字机效果
- 错误: 找不到符号 符号: 类 DaggerActivityComponent错误解决
- JavaScript自动切换图像
- 【路由与交换】交换机和集线器
- Android常用检查判断方法(本人忘性大留个备份没事看看)
- 字符设备驱动第十二课-----中断
- 第十四周项目1(2) 验证分块查找算法
- Linux join命令使用不详解
- SpringMVC拦截器学习记录
- 一套多快好省的性能测试方法论,必须安利
- 现在完成时、过去完成时、完成进行时
- 理解Socket
- libcef函数名与windowsx.h宏定义冲突的解决办法
- 第十五周--项目二