[arm驱动]linux内核中断编程
2014-04-08 19:54
513 查看
第一部分获取中断(开启硬件中断)
一、中断的申请注销:
1)中断的申请
dev__id:就是request_irq()中void *dev_id参数。
二、中断申请函数参数
irq:是要申请的硬件中断号。
handler:是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。
irqflags:是中断处理的属性,
a)若设置了IRQF_DISABLED,则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;
b)若设置了 IRQF_SHARED,则表示多个设备共享中断;//在另一篇文章会提到
c)若设置了IRQF_SAMPLE_RANDOM,表示对系统熵有贡献,对系统获取随机数有好处。
Tip:(flag是可以通过或的方式同时使用的)
devname:设置中断名称,通常是设备驱动程序的名称 在cat /proc/interrupts中可以看到此名称。
dev_id:在中断共享时会用到,一般设置为这个设备的设备结构体或者不使用时为NULL。因为在共享中断中同一个中断线(或可以说同一个中断号)可能挂载好几个设备,当使用void free_irq(unsigned int irq, void *dev_id)时,根据irq和dev_id可以找到中断线为irq上的标识为dev_id的某个具体设备。dev_id也经常在不是共享中断中的驱动传递数据
2)返回值:
a)request_irq()返回0表示成功;
b)返回-EINVAL表示无效的参数,如果返回这个值,应该看看传递给request_irq()的参数是否正确;
c)返回-EBUSY表示中断已经被占用且不能共享;
d)返回ENOMEM表示内存不足。嵌入式系统由于内存资源有限,经常会发生这样的错误。
3)扩展---unsigned long irqflags值
在include\linux\interrupt.h中
Tip:下面是老版本(2.4内核irqflags的值),不要在新版本使用。(2.6 内核及2.6以上内核都为新内核)
使用步骤:以外部中断为例
a)定义结构体,相当于定义(void *dev_id)中的(void *)
Tip:可以直接将IRQ_EINTn也在pins_desc定义,然后
一、中断的申请注销:
1)中断的申请
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)2)中断的注销
void free_irq(unsigned int irq, void *dev_id)3)中断处理函数
static irqreturn_t irq_handle(int irq, void *dev__id);参数:irq:表示中断号,这个参数还保留由于历史遗留问题,往后可能越来越没用了。由于第二个参数信息更强大
dev__id:就是request_irq()中void *dev_id参数。
二、中断申请函数参数
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)1)参数:
irq:是要申请的硬件中断号。
handler:是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。
irqflags:是中断处理的属性,
a)若设置了IRQF_DISABLED,则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;
b)若设置了 IRQF_SHARED,则表示多个设备共享中断;//在另一篇文章会提到
c)若设置了IRQF_SAMPLE_RANDOM,表示对系统熵有贡献,对系统获取随机数有好处。
Tip:(flag是可以通过或的方式同时使用的)
devname:设置中断名称,通常是设备驱动程序的名称 在cat /proc/interrupts中可以看到此名称。
dev_id:在中断共享时会用到,一般设置为这个设备的设备结构体或者不使用时为NULL。因为在共享中断中同一个中断线(或可以说同一个中断号)可能挂载好几个设备,当使用void free_irq(unsigned int irq, void *dev_id)时,根据irq和dev_id可以找到中断线为irq上的标识为dev_id的某个具体设备。dev_id也经常在不是共享中断中的驱动传递数据
2)返回值:
a)request_irq()返回0表示成功;
b)返回-EINVAL表示无效的参数,如果返回这个值,应该看看传递给request_irq()的参数是否正确;
c)返回-EBUSY表示中断已经被占用且不能共享;
d)返回ENOMEM表示内存不足。嵌入式系统由于内存资源有限,经常会发生这样的错误。
3)扩展---unsigned long irqflags值
在include\linux\interrupt.h中
/* * These correspond to the IORESOURCE_IRQ_* defines in * linux/ioport.h to select the interrupt line behaviour. When * requesting an interrupt without specifying a IRQF_TRIGGER, the * setting should be assumed to be "as already configured", which * may be as per machine or firmware initialisation. */ #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 /* * These flags used only by the kernel as part of the * irq handling routines. * * IRQF_DISABLED - keep irqs disabled when calling the action handler * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator * IRQF_SHARED - allow sharing the irq among several devices * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur * IRQF_TIMER - Flag to mark this interrupt as timer interrupt * IRQF_PERCPU - Interrupt is per cpu * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is * registered first in an shared interrupt is considered for * performance reasons) */ #define IRQF_DISABLED 0x00000020 #define IRQF_SAMPLE_RANDOM 0x00000040 #define IRQF_SHARED 0x00000080 #define IRQF_PROBE_SHARED 0x00000100 #define IRQF_TIMER 0x00000200 #define IRQF_PERCPU 0x00000400 #define IRQF_NOBALANCING 0x00000800 #define IRQF_IRQPOLL 0x00001000
Tip:下面是老版本(2.4内核irqflags的值),不要在新版本使用。(2.6 内核及2.6以上内核都为新内核)
/* * Migration helpers. Scheduled for removal in 9/2007 * Do not use for new code !//不要的新版本使用,2.6 内核及2.6以上内核都为新内核 */ static inline unsigned long __deprecated deprecated_irq_flag(unsigned long flag) { return flag; } #define SA_INTERRUPT deprecated_irq_flag(IRQF_DISABLED) #define SA_SAMPLE_RANDOM deprecated_irq_flag(IRQF_SAMPLE_RANDOM) #define SA_SHIRQ deprecated_irq_flag(IRQF_SHARED) #define SA_PROBEIRQ deprecated_irq_flag(IRQF_PROBE_SHARED) #define SA_PERCPU deprecated_irq_flag(IRQF_PERCPU) #define SA_TRIGGER_LOW deprecated_irq_flag(IRQF_TRIGGER_LOW) #define SA_TRIGGER_HIGH deprecated_irq_flag(IRQF_TRIGGER_HIGH) #define SA_TRIGGER_FALLING deprecated_irq_flag(IRQF_TRIGGER_FALLING) #define SA_TRIGGER_RISING deprecated_irq_flag(IRQF_TRIGGER_RISING) #define SA_TRIGGER_MASK deprecated_irq_flag(IRQF_TRIGGER_MASK)三、使用模板
使用步骤:以外部中断为例
a)定义结构体,相当于定义(void *dev_id)中的(void *)
struct pin_desc{//声明一个引脚描述的结构体pin_desc unsigned int pin;//引脚值,参考数据手册及板子电路原理图 unsigned int key_val;//值自已随便定义;看自己的项目需要 //................... };b)实例化结构体,相当于(void *dev_id)中的 dev_id
struct pin_desc pins_desc[3] = {//实例化结构体,以jz2440按键为列 {S3C2410_GPF0, 0x01},//S3C2410_GPFn在内核中定义好了 {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03}, };c)定义中断处理函数
static irqreturn_t irq_handle(int irq, void *dev__id){ struct pin_desc *pindesc = (struct pin_desc *)dev__id; //................ return IRQ_RETVAL(IRQ_HANDLED);//返回IRQ_HANDLED表示中断已经处理 }d)申请中断
request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH, "s2", &pins_desc[0]);//IRQ_EINTn在内核中定义好了 request_irq(IRQ_EINT2, irq_handle, IRQ_TYPE_EDGE_BOTH, "s3", &pins_desc[1]); request_irq(IRQ_EINT11, irq_handle, IRQ_TYPE_EDGE_BOTH, "s4", &pins_desc[2]);e)释放内存
free_irq(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2]);
Tip:可以直接将IRQ_EINTn也在pins_desc定义,然后
int i = 0; for(i = 0; i < 3; i++){ free_irq(pins_desc[i].irqnum, &pins_desc[i]); }实例见[arm驱动]Linux内核开发之阻塞非阻塞IO----轮询操作 中的实例(按键中断双边沿触发)
相关文章推荐
- [arm 驱动]linux内核驱动之中断下半部编程
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之三--Linux对异常和中断的处理
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之四--中断API
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之目录
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】中断服务下半部之工作队列详解
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之一--中断概述
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】中断服务下半部之七姑八姨
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之二--Linux中断的组织形式
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】中断服务下半部之老大-软中断softirq
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之三--Linux对异常和中断的处理
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】中断服务下半部之tasklet详解
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之四--中断API
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之一--中断概述
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】深入剖析Linux中断机制之二--Linux中断的组织形式
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Oops在Linux 2.6内核+PowerPC架构下的前世今生
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux系统调用的实现机制分析
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】详解Linux内核之双向循环链表
- ARM-Linux驱动--ADC驱动(中断方式)
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux系统调用的实现机制分析
- Linux学习二, 中断编程和字符设备驱动