Linux 中断驱动程序的几个知识点(irq_desc,request_irq)

Linux内核中断处理流程:

(1)      发生中断时,CPU执行异常向量vector_irq的代码(通过向量表跳转到异常向量处理区);

(2)      异常向量处理区会调用asm_do_IRQ函数,这是中断函数的总入口函数;

(3)      asm_do_IRQ 会根据中断号调用相应irq_desc[]数组项中的handler_irq;

(4)      handler_irq会先调用irq_desc结构体中的chip函数对底层进行操作,如开中断,禁止中断,清楚中断等;

(5)      handler_irq然后一一调用action链表中注册的中断处理函数handler(这个才是用户自己编写的中断处理函数,通过request_irq来注册)。

 

核心成员:

中断驱动程序中,request_irq()是驱动程序的核心,

内核支持中,irq_desc[]是中断结构体系的核心。

irq_desc[]是一个指向irq_desc结构的数组, irq_desc结构是各个设备中断服务例程的描述符。

硬件中断请求——异常向量表——异常向量处理函数(调用asm_do_IRQ)——根据中断号n跳转到irq_desc[n]的地址,这个地址也是一个入口函数handler_irq。

struct irq_desc {

irq_flow_handler_t handle_irq; 

//入口处理函数,依次调用chip中的函数与链表irqaction中注册的用户中断处理函数

struct irq_chip *chip;             //结构体地址,底层硬件操作

void *handler_data;

void *chip_data;

struct irqaction *action;          //用户注册的结构体链表,为用户中断处理函数

unsigned int status;

unsigned intdepth;

unsigned int wake_depth;

unsigned int irq_count;

unsigned int irqs_unhandled;

spinlock_t lock;

#ifdef CONFIG_SMP

cpumask_t affinity;

unsigned int cpu;

#endif

#ifdefined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)

cpumask_t pending_mask;

#endif

#ifdef CONFIG_PROC_FS

struct proc_dir_entry*dir;

#endif

const char *name;

} ____cacheline_aligned;

 

根据irq_desc的基础知识,request_irq的各个参数代表的意思如下:

int request_irq(
unsigned int irq,
    irqreturn_t (*handler)(int, void *,struct pt_regs *),
    unsigned long irqflags, 
    const char *devname, 
    void *dev_id );

irq 为中断号,即irq_desc[irq]数组中的下标。根据中断号irq可以找到对应的irq_desc[irq]。

handler为用户注册的中断处理函数,用来将其注册到structirqaction *action的链表当中。

irqflags中断标志,指定了快速中断或中断共享等中断处理属性,在structirqaction *action中需要用到。

devname指定设备驱动程序的名称。

dev_id:传入中断处理程序的参数,可以为NULL,在注册共享中断时,此参数不能为NULL,作为共享中断时的中断区别参数。

当不同设备共用同一个中断时,这个时候需要对中断进行区别,使用dev_id,因为中断号是一样的,但是主设备是不一样的。


用户开发中断驱动需要做的工作:

(1)      字符设备驱动基本的操作,见笔记linux 驱动.docx

(2)      ko模块中的fops成员组中,open()函数增加向内核注册中断处理函数request_irq(),以及从内核释放已注册中断处理函数free_irq()。

(3)      ko模块中的fops成员组中,增加read()函数,此函数实现休眠功能,如果有动作,则读取,如果没有则休眠。

(4)      ko模块中,增加用户中断处理函数,用于注册。

(5)      用户使用时中,先insmod .ko,(再mknod /dev/deive_name),然后在用户程序中,先open(),然后read(),实现无中断则睡眠,有中断则根据中断处理结果进行输出显示。


你可能感兴趣的:(linux驱动,中断驱动,irq_desc,request_irq)