在上一节中,我们讲解了如何自动创建设备节点,实现一个查询方式的按键驱动。测试的时候,大家都看到了,使用查询式的方法,占用CPU的利用率高达99%,那么有没有好的办法来取代这惨不忍睹的方法呢?答案当然是有的。
上一节文章链接:http://blog.csdn.net/lwj103862095/article/details/17484041
这一节里,我们使用中断的方法来实现按键驱动。
问:内核的中断体系是怎么样的?
答:ARM架构linux内核中,有5种常见的异常,其中中断异常是其一,Linux内核将所有中断统一编号,使用一个irq_desc结构体来描述这些中断,里面记录了中断名称、中断状态、中断标记、并提供了中断的底层硬件访问函数(如:清除、屏蔽、使能中断),提供了这个中断的处理函数入口,通过它还可以调用用户注册的的中断处理函数。
问:irq_desc结构体有哪些重要的成员?
/**
* struct irq_desc - interrupt descriptor
* @irq: interrupt number for this descriptor
* @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()]
* @chip: low level interrupt hardware access
* @action: the irq action chain
* @status: status information
* @irq_count: stats field to detect stalled irqs
* @name: flow handler name for /proc/interrupts output
*/
struct irq_desc {
unsigned int irq;
......
irq_flow_handler_t handle_irq;
struct irq_chip *chip;
......
struct irqaction *action; /* IRQ action list */
unsigned int status; /* IRQ status */
......
unsigned int irq_count; /* For detecting broken IRQs */
......
const char *name;
} ____cacheline_internodealigned_in_smp;
关于irq_desc结构体的具体描述,请参考《嵌入式Linux应用完全开发手册》的第20章的20.2.1节,即416页开始的描述。关于linux中断体系的详细讲解,我就不多说了,大家参考韦老师的视频教程:
"第12课第4.1节.字符设备驱动程序之中断方式的按键驱动_Linux异常处理结构"
"第12课第4.2节.字符设备驱动程序之中断方式的按键驱动_Linux中断处理结构"
这二个视频,已经讲解的非常到位,如果还不理解的,大家可以参考韦老师的书的第20章内容。建议大家结合linux源码和书一起看,这样对你深入linux中断体系就不远了。
问:既然linux内核的中断体系已经 那么完善了,那么驱动工程师还需要做什么?
答:驱动工程师需要调用request_irq向内核注册中断,其原型为:
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char * devname, void * dev_id)
第一个参数irq:中断号,在irqs.h中定义,与架构相关;
第二个参数handler: 用户中断处理函数;
第三个参数flags:中断标记;
第四个参数devname:中断名字;可以通过cat proc/interrupts查看;
第五个参数dev_id: 在free_irq中有用,也用作区分中断处理函数;
问:request_irq函数有什么作用?
答:
1)、irq_desc[irq]结构体中的action链表中已经链入了用户注册的中断处理函数。
2)、中断触发方式已经被设置好。
3)、中断已经被使能。
问:如何卸载中断处理函数?
答:中断是一种很稀缺的资源,当不再使用一个设备时,应该释放它占据的中断。驱动工程师通过free_irq函数来实现,其原型为:
void free_irq(unsigned int irq, void *dev_id)
第一个参数irq:中断号,与request_irq中的irq一致,用于定位action链表;
第二个参数dev_id:用于在action链表中找到要卸载的表项;同一个中断的不同中断处理函数必须使