补充中断处理接口.

Signed-off-by: lion.chan <cy187lion@sina.com>
This commit is contained in:
lion.chan 2022-04-22 00:19:40 +08:00
parent c18e1aa512
commit 173ab24350

View File

@ -69,13 +69,62 @@ Err: 0
## Linux 中断编程
获取中断信息:
```cpp
/**
* of_irq_get - Decode a node's IRQ and return it as a Linux irq number
* @file drivers/of/irq.c
* @dev: pointer to device tree node
* @index: zero-based index of the irq
*
* Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
* is not yet created.
*
*/
int of_irq_get(struct device_node *dev, int index);
/**
* platform_get_irq - get an IRQ for a device
* @file drivers/base/platform.c
* @dev: platform device
* @num: IRQ number index
* @brief 包含 of_irq_get()
*/
int platform_get_irq(struct platform_device *dev, unsigned int num);
```
注册中断处理程序:
```cpp
/**
* @file kernel/irq/manage.c
* @param irq 要申请的硬件中断号。
* @param handler 是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数。
* @param handler 是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数。为 NULL 时使用默认的处理,这个相当于中断的上半段。
* @param thread_fn 中断发生时,如果 handler 为 NULL就直接将 thread_fn 扔到内核线程中去执行。
* @param irqflags 是中断处理的属性
* SA_INTERRUPT则表示中断处理程序是快速处理程序快速处理程序被调用时屏蔽所有中断慢速处理程序不屏蔽
* SA_SHIRQ表示多个设备共享中断
* 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)
* IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
* Used by threaded interrupts which need to keep the
* irq line disabled until the threaded handler has been run.
* IRQF_NO_SUSPEND - Do not disable this IRQ during suspend. Does not guarantee
* that this interrupt will wake the system from a suspended
* state. See Documentation/power/suspend-and-interrupts.txt
* IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
* IRQF_NO_THREAD - Interrupt cannot be threaded
* IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
* resume time.
* IRQF_COND_SUSPEND - If the IRQ is shared with a NO_SUSPEND user, execute this
* interrupt handler after suspending interrupts. For system
* wakeup devices users need to implement wakeup detection in
* their interrupt handlers.
* @param devname An ascii name for the claiming device. 使用cat /proc/interrupt 可以查看中断程序名字。
* @param dev_id 在中断共享时会用到,一般设置为这个设备的设备结构体或者 NULL。
* 注册共享中断时不能为NULL因为卸载时需要这个做参数避免卸载其它中断服务函数。
@ -85,6 +134,10 @@ Err: 0
* -EBUSY表示中断已经被占用且不能共享。
* @brief 申请 IRQ
*/
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn, unsigned long irqflags,
const char *devname, void *dev_id);
int request_irq(unsigned int irq,
void (*handler)(int irq, void *dev_id, struct pt_regs *regs),
unsigned long irqflags,
@ -102,7 +155,68 @@ void free_irq(unsigned int irq, void *dev_id);
2. 如果采用共享中断方式,所有使用 request_irq 注册的中断时 flags 都要加上 IRQF_SHARED 这个共享参数,表明其实共享中断。
3. 对于共享中断,每一个申请共享的中断,申请和释放时都要给 request_irq 和 free_irq 的最后一个参数 dev 和 id_dev 传递一个指针,将来来中断的时候,将会传递这个指针到每个中断函数中,而中断函数就可以用来区分到底是不是它的中断,是则执行,不是则判断后直接退出中断处理函数即可。同时在 free_irq 时也会使用这个指针,查找这个贡献中断链表上了所有注册的 irq只有在这个指针能对的上的时候才会删除它所在的链表节点如果是最后一个节点还要释放该中断。所在在编写中断处理函数时该指针必须是唯一的通常传的这个指针是该设备结构体的地址这个每个设备不一样所以肯定是唯一的。
下列 3 个函数用于禁能/使能一个中断源。
对于资源管理 Linux 内核提供了一组 Devm API。Devm APIs 是一组便捷易用的接口通过该接口申请的内核资源是跟设备device有关的在设备device被 detached 或者驱动driver卸载unloaded会被自动释放。针对以上中断资源管理有以下 Devm 版本的 API
```cpp
/**
* @file kernel/irq/devres.c
* @param dev 设备结构体。
* @param irq 要申请的硬件中断号。
* @param handler 是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数(运行于中断上下文),
函数需要判断是否为自身中断,若是则关闭自身中断并返回 IRQ_WAKE_THREAD。
为 NULL 时使用默认的处理。
* @param thread_fn 中断发生时,如果 handler 为 NULLthread_fn 将在默认 handler 执行完毕后以内核线程形式运行。
* 否则待 handler 返回 IRQ_WAKE_THREAD 后以内核线程形式执行。
* @param irqflags 是中断处理的属性
* 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)
* IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
* Used by threaded interrupts which need to keep the
* irq line disabled until the threaded handler has been run.
* IRQF_NO_SUSPEND - Do not disable this IRQ during suspend. Does not guarantee
* that this interrupt will wake the system from a suspended
* state. See Documentation/power/suspend-and-interrupts.txt
* IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
* IRQF_NO_THREAD - Interrupt cannot be threaded
* IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
* resume time.
* IRQF_COND_SUSPEND - If the IRQ is shared with a NO_SUSPEND user, execute this
* interrupt handler after suspending interrupts. For system
* wakeup devices users need to implement wakeup detection in
* their interrupt handlers.
* @param devname An ascii name for the claiming device. 使用cat /proc/interrupt 可以查看中断程序名字。
* @param dev_id 在中断共享时会用到,一般设置为这个设备的设备结构体或者 NULL。
* 注册共享中断时不能为NULL因为卸载时需要这个做参数避免卸载其它中断服务函数。
* @return
* 0表示成功
* -INVAL表示中断号无效或处理函数指针为 NULL
* -EBUSY表示中断已经被占用且不能共享。
* @brief 申请 IRQ
*/
extern int __must_check
devm_request_threaded_irq(struct device *dev, unsigned int irq,
irq_handler_t handler, irq_handler_t thread_fn,
unsigned long irqflags, const char *devname,
void *dev_id);
static inline int __must_check
devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
return devm_request_threaded_irq(dev, irq, handler, NULL, irqflags,
devname, dev_id);
}
extern void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id);
```
禁能/使能中断源:
```cpp
// 禁能中断源