微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux中断(interrupt)子系统之一:中断系统基本原理

Linux中断(interrupt)子系统之一:中断系统基本原理

时间:12-14 来源:互联网 点击:

的irq_desc结构的组织方式有两种:

基于数组方式 平台相关板级代码事先根据系统中的IRQ数量,定义常量:NR_IRQS,在kernel/irq/irqdesc.c中使用该常量定义irq_desc结构数组:

[cpp] view plain copystruct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {

[0 ... NR_IRQS-1] = {

.handle_irq = handle_bad_irq,

.depth = 1,

.lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),

}

};

基于基数树方式 当内核的配置项CONFIG_SPARSE_IRQ被选中时,内核使用基数树(radix tree)来管理irq_desc结构,这一方式可以动态地分配irq_desc结构,对于那些具备大量IRQ数量或者IRQ编号不连续的系统,使用该方式管理irq_desc对内存的节省有好处,而且对那些自带中断控制器管理设备自身多个中断源的外部设备,它们可以在驱动程序中动态地申请这些中断源所对应的irq_desc结构,而不必在系统的编译阶段保留irq_desc结构所需的内存。

下面我们看一看irq_desc的部分定义:

[cpp] view plain copystruct irq_data {

unsigned int irq;

unsigned long hwirq;

unsigned int node;

unsigned int state_use_accessors;

struct irq_chip *chip;

struct irq_domain *domain;

void *handler_data;

void *chip_data;

struct msi_desc *msi_desc;

#ifdef CONFIG_SMP

cpumask_var_t affinity;

#endif

};

[cpp] view plain copystruct irq_desc {

struct irq_data irq_data;

unsigned int __percpu *kstat_irqs;

irq_flow_handler_t handle_irq;

#ifdef CONFIG_IRQ_PREFLOW_FASTEOI

irq_preflow_handler_t preflow_handler;

#endif

struct irqaction *action; /* IRQ action list */

unsigned int status_use_accessors;

unsigned int depth; /* nested irq disables */

unsigned int wake_depth; /* nested wake enables */

unsigned int irq_count; /* For detecting broken IRQs */

raw_spinlock_t lock;

struct cpumask *percpu_enabled;

#ifdef CONFIG_SMP

const struct cpumask *affinity_hint;

struct irq_affinity_notify *affinity_notify;

#ifdef CONFIG_GENERIC_PENDING_IRQ

cpumask_var_t pending_mask;

#endif

#endif

wait_queue_head_t wait_for_threads;

const char *name;

} ____cacheline_internodealigned_in_smp;

对于irq_desc中的主要字段做一个解释:

irq_data 这个内嵌结构在2.6.37版本引入,之前的内核版本的做法是直接把这个结构中的字段直接放置在irq_desc结构体中,然后在调用硬件封装层的chip->xxx()回调中传入IRQ编号作为参数,但是底层的函数经常需要访问->handler_data,->chip_data,->msi_desc等字段,这需要利用irq_to_desc(irq)来获得irq_desc结构的指针,然后才能访问上述字段,者带来了性能的降低,尤其在配置为sparse irq的系统中更是如此,因为这意味着基数树的搜索操作。为了解决这一问题,内核开发者把几个低层函数需要使用的字段单独封装为一个结构,调用时的参数则改为传入该结构的指针。实现同样的目的,那为什么不直接传入irq_desc结构指针?因为这会破坏层次的封装性,我们不希望低层代码可以看到不应该看到的部分,仅此而已。

kstat_irqs 用于irq的一些统计信息,这些统计信息可以从proc文件系统中查询。

action 中断响应链表,当一个irq被触发时,内核会遍历该链表,调用action结构中的回调handler或者激活其中的中断线程,之所以实现为一个链表,是为了实现中断的共享,多个设备共享同一个irq,这在外围设备中是普遍存在的。

status_use_accessors 记录该irq的状态信息,内核提供了一系列irq_settings_xxx的辅助函数访问该字段,详细请查看kernel/irq/settings.h

depth 用于管理enable_irq()/disable_irq()这两个API的嵌套深度管理,每次enable_irq时该值减去1,每次disable_irq时该值加1,只有depth==0时

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top