天天看点

【Linux中断子系统】疑问记录

IRQ Number 软件虚拟的 标识外设中断

HW interrupt ID 硬件上的标识外设中断

1、irq domain干什么用的,为什么要使用它?

irq domain就是指中断领域,任何超出这个范围的定义就没有意义了。

IRQ domain来描述一个中断控制器(IRQ Controller)所管理的中断源。换句话说,每个中断控制器都有自己的domain。我们可以将IRQ Domain看作是IRQ Controller的软件抽象。

这里所说的“中断控制器”,不仅指硬件上实际存在的中断控制器,也可以是一个“虚拟”的中断控制器。例如,假设我们有一块CPU,它有多个GPIO Pin可以作为外部中断源使用(事实上大多数嵌入式CPU都有这样的GPIO)。

我们还假定所有的GPIO中断都复用到该CPU的同一个中断向量。在这样的情况下,这多个GPIO中断就可以抽象成一个虚拟的中断控制器,它连接到CPU的某个中断向量上。

这样做的好处在于,可以将“对中断控制器的中断响应”和“对产生中断的外部设备的中断响应”分离开来。我们还是看一个例子,假定我们有若干个GPIO,分别接了不同外设(如按键、外部以太网控制器等),

当这些外设产生中断的时候,CPU内部的GPIO控制器会置位相应的中断标志位,并向CPU提交中断请求。这样,对每一个外设中断,我们实际上要进行两级中断服务:第一级中断服务判断是哪个GPIO产生了中断,

并需要清除GPIO控制器内部某个寄存器中的某个标志位;第二级中断服务才是服务产生中断的那个外设的。显然,第一级中断服务代码对每个产生GPIO中断的外设是类似的。有了IRQ Domain的帮助,

第一级中断服务代码就可以统一,设备驱动程序只需要关心第二级中断服务就可以了。

2、如何注册一个irq domain,注册irq domain的动作到底是做什么了操作?

三种方法:

1、irq_domain_add_linear (线性映射)

2、irq_domain_add_tree (Radix Tree map)

3、irq_domain_add_nomap (no map)

根据自己的映射类型,初始化struct irq_domain中的各个成员,

调用__irq_domain_add将该irq domain挂入irq_domain_list的全局列表

3、为什么IRQ Number需要HW interrupt ID映射过来?

1、驱动工程师而言,我们和CPU视角是一样的,我们只希望得到一个IRQ number,而不关系具体是那个interrupt controller上的那个HW interrupt ID。

这样一个好处是在中断相关的硬件发生变化的时候,驱动软件不需要修改

2、interrupt controller级联的情况下,仅仅使用HW interrupt ID已经不能唯一标识一个外设中断,还需要知道HW interrupt ID所属的interrupt controller

因为HW interrupt ID在不同的interrupt controller上是会重复编码。

4、如何知道系统irq domain的当前采用哪种映射关系?

映射有三种:

1、线性映射

2、Radix Tree map (powerPC和MIPS硬件平台用到)

3、no map 即:hw interrupt id就是 irq number,寄存器配置HW interrupt ID而不是物理连接特性决定

因此arm架构使用 线性映射

5、如何获取HW interrupt ID?

interrupt controller会对连接其上的interrupt source(根据其在Interrupt controller中物理特性)进行编号(也就是HW interrupt ID了

int (*xlate)(struct irq_domain *d, struct device_node *node,
         const u32 *intspec, unsigned int intsize,
         unsigned long *out_hwirq, unsigned int *out_type); 
           

软件上通过调用 irq domain的irq_domain_ops结构的xlate回调函数成员 将指定的设备(node参数)上若干个(intsize参数)中断属性(intspec参数)翻译成HW interrupt ID(out_hwirq参数)和trigger类型(out_type)。

6、HW interrput ID如何转换成IRQ number?

由IRQ domain负责,通过irq_create_mapping

7、什么是interrupt flow control?

中断流控制

软件上设定一些标志位和硬件上 mask或者unmask interrupt controller等,具体表现为调用中断描述符的irq chip driver进行mask,ack等callback函数。

8、每一个IRQ都有中断描述符吗?

系统中每一个连接外设的中断线(irq request line)用一个中断描述符来描述,每一个外设的interrupt request line分配一个中断号(irq number),

系统中有多少个中断线(或者叫做中断源)就有多少个中断描述符struct irq_desc

NR_IRQS定义了该硬件平台IRQ的最大数目

linux内核中有一个数据结构保存了所有中断描述符的信息,具体表现为以下两种:

(1)即一个静态定义的数组,irq number作为index, 有空洞,存在空间浪费

(2)打开CONFIG_SPARSE_IRQ 使用Radix tree保存,这时候,每一个中断描述符都是动态分配,然后插入到radix tree中

描述一个具体的中断 struct irq_desc,简称中断描述符

描述一个具体中断的底层相关数据结构 struct irq_data

描述一个具体中端底层若干和具体interrupt controller相关的callback函数 strcut irq_chip

【Linux中断子系统】疑问记录

9、GIC支持多少个中断号?

linux-4.9/drivers/irqchip/irq-gic.c
    /*
     * Find out how many interrupts are supported.
    * The GIC only supports up to 1020 interrupt sources.
    */
    gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
   gic_irqs = (gic_irqs + 1) * 32;
   if (gic_irqs > 1020)
       gic_irqs = 1020;
           

继续阅读