Linux Driver APIs - interrupt and irq
2016-11-27 15:44
941 查看
Linux Interrupt API
=============================
#include <linux/interrupt.h>
0.Index
=======
- 1.Request IRQ
- 2.enable/disable IRQ
- 3.使IRQ成为Wakeup Source
- 4.Sample Code
1.Request IRQ
=============
申请线程化的IRQ
-----------------------
irq - irq number
handler - hardware irq handler, 硬中断,在中断上下文执行
thread_fn - threaded irq handler,执行中断实际任务的线程函数,在线程
上下文执行
flags - 中断标志,触发方式,执行方式等
name - IRQ的名字
dev - 可以为任何参数,该参数将会传递到handler/thread_fn中,可用于保存
中断函数中需要使用的变量/结构体的指针。
Note:
- 调用这个函数将向中断子系统申请中断资源,同时使能该IRQ Line。
- handler/thread_fn允许同时存在,也允许只存在其中一个,但不允许两个都为NULL。
- handler函数(top half)在中断上下文执行,应保证快速执行完毕,中断上下文不允许
有sleep/task schedule等会导致主动放弃CPU操作,不能使用mutex/semaphore等有可能导致阻塞的API
- 中断上下文不允许访问用户空间内存
- 耗时的操作应该放到thread_fn中(bottom half)执行,如果handler存在,当handler
返回IRQ_WAKE_THREAD时,将唤醒thread_fn所在的线程。如果handler不存在,则默认当
中断触发后,唤醒thread_fn所在的线程。
- 中断bottom half可以通过workqueue或者自己创建kthread来实现,它们本质上都为
kernel thread,但通过request_threaded_irq创建的线程具有更高的优先级和实时性
较高的调度策略,因此如果你对bottom half的实时性有要求,应该优先使用request_threaded_irq.
使用threaded irq没有softirq、tasklet的限制,且拥有较高的执行优先级,推荐使用。
申请IRQ
-----------
释放IRQ
------------
------------------------------
相比不带资源管理的API,如下API多了一个参数struce device *dev,位于第一个参数位置,调用者不用关心irq的释放操作,当driver与device detach时,irq将被自动释放掉。devm_request_threaded_irq
devm_request_irq
devm_free_irq
2.enable/disable IRQ
================
Disable IRQ
----------------
因此不能在中断top half中执行disable_irq,否则将会导致死锁。
Enable IRQ
---------------
为NULL的时候,可以在中断上下文中调用enable_irq。
enable/disable irq必须成对使用,例如调用两次disable_irq后,irq将处于disabled状态直到
调用两次enable_irq。
全局中断开关
-----------------
3.使IRQ成为Wakeup Source
======================
被屏蔽掉,但此irq仍然可以被触发和处理(可以wake up 主控)
4.Sample Code
=============
=============================
#include <linux/interrupt.h>
0.Index
=======
- 1.Request IRQ
- 2.enable/disable IRQ
- 3.使IRQ成为Wakeup Source
- 4.Sample Code
1.Request IRQ
=============
申请线程化的IRQ
-----------------------
int __must_check request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags, const char *name, void *dev);参数依次为:
irq - irq number
handler - hardware irq handler, 硬中断,在中断上下文执行
thread_fn - threaded irq handler,执行中断实际任务的线程函数,在线程
上下文执行
flags - 中断标志,触发方式,执行方式等
name - IRQ的名字
dev - 可以为任何参数,该参数将会传递到handler/thread_fn中,可用于保存
中断函数中需要使用的变量/结构体的指针。
Note:
- 调用这个函数将向中断子系统申请中断资源,同时使能该IRQ Line。
- handler/thread_fn允许同时存在,也允许只存在其中一个,但不允许两个都为NULL。
- handler函数(top half)在中断上下文执行,应保证快速执行完毕,中断上下文不允许
有sleep/task schedule等会导致主动放弃CPU操作,不能使用mutex/semaphore等有可能导致阻塞的API
- 中断上下文不允许访问用户空间内存
- 耗时的操作应该放到thread_fn中(bottom half)执行,如果handler存在,当handler
返回IRQ_WAKE_THREAD时,将唤醒thread_fn所在的线程。如果handler不存在,则默认当
中断触发后,唤醒thread_fn所在的线程。
- 中断bottom half可以通过workqueue或者自己创建kthread来实现,它们本质上都为
kernel thread,但通过request_threaded_irq创建的线程具有更高的优先级和实时性
较高的调度策略,因此如果你对bottom half的实时性有要求,应该优先使用request_threaded_irq.
使用threaded irq没有softirq、tasklet的限制,且拥有较高的执行优先级,推荐使用。
申请IRQ
-----------
int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)参数意义同request_threaded_irq
释放IRQ
------------
void free_irq(unsigned int irq, void *dev_id);Resouce Managed API
------------------------------
相比不带资源管理的API,如下API多了一个参数struce device *dev,位于第一个参数位置,调用者不用关心irq的释放操作,当driver与device detach时,irq将被自动释放掉。devm_request_threaded_irq
devm_request_irq
devm_free_irq
2.enable/disable IRQ
================
Disable IRQ
----------------
void disable_irq_nosync(unsigned int irq);disable irq后立即返回,不等待中断执行完毕。
void disable_irq(unsigned int irq);disale irq并且同步等待中断执行完毕才返回。
因此不能在中断top half中执行disable_irq,否则将会导致死锁。
Enable IRQ
---------------
void enable_irq(unsigned int irq);enable_irq并没有同步与非同步的区分,当desc->irq_data.chip->bus_lock and desc->chip->bus_sync_unlock
为NULL的时候,可以在中断上下文中调用enable_irq。
enable/disable irq必须成对使用,例如调用两次disable_irq后,irq将处于disabled状态直到
调用两次enable_irq。
全局中断开关
-----------------
local_irq_disable() 禁止中断 local_irq_enable() 打开中断 local_irq_save(flag) 禁止中断并保存中断寄存器 local_irq_restore(flags) 打开中断,恢复寄存器 local_bh_disable() 仅禁止中断底半部中断 local_bh_enable() 打开注意:不要长时间屏蔽中断
3.使IRQ成为Wakeup Source
======================
int enable_irq_wake(unsigned int irq);
int disable_irq_wake(unsigned int 9017 irq);调用enable_irq_wake后该irq将一直处于wake状态,当系统进入deep sleep状态时,其他irq将会
被屏蔽掉,但此irq仍然可以被触发和处理(可以wake up 主控)
4.Sample Code
=============
#include <linux/interrupt.h> #define IRQ_NUM 13 static irqreturn_t hard_irq_handler(int irq, void *dev_id) { /* * irq context, limited operations. * do emergency work and quit as soon as possible */ return IRQ_WAKE_THREAD; } static irqreturn_t thread_irq_handler(int irq, void *dev_id) { /* * do the real work * you can use sleep api, mutex/semaphore api, * you can access user space memory here, */ return IRQ_HANDLED; } static int irq_sample(struct device *dev) { int irq = IRQ_NUM; int r; r = devm_request_threaded_irq(dev, irq, hard_irq_handler, thread_irq_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "samp", NULL); if (r < 0) return r; // at this point, irq is requested and is enabled. return 0; }
相关文章推荐
- Linux Platform Device and Driver
- Linux Platform Device and Driver
- 《Understanding the Linux kernel》学习笔记 Chapter 4: Interrupts and ExceptionsM
- MIPI DIsplay Panel And Linux Driver Model .
- Linux Platform Device and Driver
- Kinect sensor and Linux kernel driver
- SMP affinity and interrupt handling in Linux
- LINUX平台设备(linux platform_device and platform_driver)
- Linux那些事儿之我是EHCI(4) data structure of ehci driver and device
- Linux Platform Device and Driver [转]
- Linux Platform Device and Driver,platform_add_devices()->platform_driver_register()
- Linux Platform Device and Driver
- Understanding the linux kernel-ch4-Interrupt and exception
- linux平台设备驱动架构详解 Linux Platform Device and Driver
- Linux Platform Device and Driver : platform_add_devices()->platform_driver_register()
- Linux Platform Device and Driver
- Linux Platform Device and Driver
- Linux Driver APIs - kernel lock
- Linux Platform Device and Driver
- Linux Platform Device and Driver