依然是为了复习之用,都是自己遇到的问题,肯定不全。
我用的OK6410 Linux2.6.36.2内核
1、首先要说的是几个必须要加的头文件。
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-n.h>
#include <mach/irqs.h>
map.h里面是各个端口的物理地址与虚拟地址之间的映射,使用端口地址的时候用的是虚拟地址。可以自己通过物理地址手动映射。但更好的是用内核提供的端口,方便一些。我因为要用中断用的是S3C64XX_GPNCON等三个,他们定义在gpio-bank-n.h中,这个头文件的使用以regs-gpio.h为基础,而这个regs-gpio.h又以map.h为基础。所以这三个都不能少。都要写。
irqs.h(注意这个是mach下的irqs.h,内核里还有个irq.h)这个头文件中,所有中断号都在这里。我要用外部中断0,用的宏就是IRQ_EINT(x)。来求取外部中断x的中断号。
2、申请中断时候的那几个flag变了。不再是SA_INTERRUPT SA_SHIRED等。变成下面这些:
These flags used only by the kernel as part of the 41 * irq handling routines. 42 * 43 * IRQF_DISABLED - keep irqs disabled when calling the action handler. 44 * DEPRECATED. This flag is a NOOP and scheduled to be removed 45 * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator 46 * IRQF_SHARED - allow sharing the irq among several devices 47 * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur 48 * IRQF_TIMER - Flag to mark this interrupt as timer interrupt 49 * IRQF_PERCPU - Interrupt is per cpu 50 * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing 51 * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is 52 * registered first in an shared interrupt is considered for 53 * performance reasons) 54 * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished. 55 * Used by threaded interrupts which need to keep the 56 * irq line disabled until the threaded handler has been run. 57 * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
我也就用了IRQF_DISABLED IRQF_SHARED两个。这两个和SA版本的效果应该是一样的。我没看源码,使用上至少没差别。
3、IRQF_SHARED类型中断申请irq的时候,
request_irq(irq_dev->IO_irq3,irq_interrupt3,IRQF_SHARED,"Myirq3";&irq_dev);
最后那个参数必须独一无二,我开始还写了个NULL。。。。唉。。弄的申请不上中断研究半天。。笨了。。
哦,上面那个IO_irq3是我申请的中断号,irq。获得方法是:irq_dev->IO_irq3 = IRQ_EINT(2);即上面说的内核提供的宏,获取irq的。
4、我在module_init中获取的irq值,然后有个很重要的函数需要去调用
int set_irq_type(unsigned int irq, unsigned int type)
type种类有很多,如下所示:/* 37 * IRQ line status. 38 * 39 * Bits 0-7 are reserved for the IRQF_* bits in linux/interrupt.h 40 * 41 * IRQ types 42 */ 43#define IRQ_TYPE_NONE 0x00000000 /* Default, unspecified type */ 44#define IRQ_TYPE_EDGE_RISING 0x00000001 /* Edge rising type */ 45#define IRQ_TYPE_EDGE_FALLING 0x00000002 /* Edge falling type */ 46#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) 47#define IRQ_TYPE_LEVEL_HIGH 0x00000004 /* Level high type */ 48#define IRQ_TYPE_LEVEL_LOW 0x00000008 /* Level low type */ 49#define IRQ_TYPE_SENSE_MASK 0x0000000f /* Mask of the above */ 50#define IRQ_TYPE_PROBE 0x00000010 /* Probing in progress */
这个函数就是在控制中断的触发方式,上升沿,下降沿等等,肯定很重要了,不然你还要自己处理防抖。irq是想要设置触发方式的irq号,type对应上面那些。我写的这样的:
set_irq_type(irq_dev->IO_irq3, IRQ_TYPE_EDGE_RISING);
但是这个防抖并不是十分的好,大约按个三五下就会有抖动现象出现。