内核中断号必须要跟硬件中断号一致吗

首先说明,答案是否定的,内核中断号可以与硬件中断号不一致,但是这是个无聊的问题。。实用价值不大。但是却可以引起对内核软件中断号与硬件中断号关系的思考。两者的关系我觉得可以从中断的初始化和分发过程来一探究竟。这里就从ARM PPC MIPS 3款主流嵌入式处理器架构的内核代码框架中来分析下他们中断的初始化和分发过程。一 中断的初始化对于中断初始化,在系统启动过程中,这3款处理器架构的内核软件框架中都会有相应的中断初始化函数.内核启动函数start_kernel中会调用init_IRQ来进行中断初始化,该函数在不同处理器平台代码有不同实现。实现在arch/xxx/kernel/irq.c中。对于arm处理器,init_IRQ调用对应设备描述符machine_desc的init_irq。对于ppc处理器,init_IRQ调用对应设备描述符machdep_calls的init_IRQ。对于mips处理器,init_IRQ调用arch_init_irq。最终调用的中断初始化函数是在板级支持包中实现,因为中断控制器属于处理器核的外设。所以可以看出,中断初始化的调用关系:通用函数start_kernel —–> 处理器平台级函数init_IRQ —–> 板级中断初始化函数init_irq等板级中断初始化函数完成2件事情,其一,中断控制器初始化。其二,中断描述符irq_desc的初始化。中断控制器初始化就不细说了。这里我们主要关心软件上中断描述符的处理。

内核对于中断的管理,最关键的数据结构就是irq_desc,在kernel/irq/irqdesc.c中:

struct 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),}};

NR_IRQS由不同处理器平台的板级支持包来定义,irq_desc数组成员代表每一个中断号和相应的处理函数。所以irq_desc[NR_IRQS]就是硬件中断控制器中断号表在内核的表征。有个前提,这里是在不配置CONFIG_SPARSE_IRQ内核选项的情况下,irq_desc[NR_IRQS]用数组形式静态分配中断描述符表,编译时即确定irq_desc数组大小。如果配置CONFIG_SPARSE_IRQ则动态分配irq_desc以节省内存。这是另一套机制,这里就不细说了。板级中断初始化函数中完成其所使用所有中断号对应的irq_desc的初始化,主要是设置中断的一级处理函数。一般是handle_level_irq。函数实现在kernel/irq/chip.c中。handle_level_irq遍历该irq_desc的action链表,依次执行其action->handler。各个driver中调用request_irq注册的中断处理函数就是irq_desc各个action的handler成员。这里我们也就明白了内核下共享中断的实现机制了。内核中断的初始化就是这样。从这里可以看出,irq_desc[NR_IRQS]内核中断号表与硬件中断号表对应。那么问题来了,我不让他们一一对应,硬件中断号35的处理函数,我想放在irq_desc数组的30号可不可以?从中断的初始化来看这样的修改是没什么问题,就是数组成员内容换一下。但是我们要想到中断是来干什么的,中断的初始化以及注册,都是为了能够正确的响应中断进行处理。所以这个问题的关键在于,这样修改,当产生35号中断时,内核能不能正常找到在30号irq-desc上的处理函数呢。也就是在中断分发过程中内核如何确定软件中断号,由硬件35号中断找到30号irq_desc。

这个我们就需要来看下内核的中断分发过程了。二 中断的分发中断是处理器核异常的一种,所以处理器设计中,外设中断引起处理器异常,处理器跳转到异常向量表的相应异常入口取指执行。处理器的异常向量表也是软硬件结合很有意思的东西,有时间专门写一篇来记录,这里不详说了。我们主要来看产生中断后,处理器跳转到中断异常入口后的执行流程。

(1)对于arm处理器,执行流程如下:vector_irq —> irq_handler —> arch_irq_handler_default —> asm_do_IRQ —> handle_IRQ在arch_irq_handler_default中调用get_irqnr_and_base获取中断号,传给asm_do_IRQ作为参数。get_irqnr_and_base由板级支持包实现。

(2)对于ppc处理器,执行流程如下:do_IRQ —> ppc_md.get_irq —> handle_one_irqppc_md.get_irq是由板级支持包中实现的设备描述符的获取中断号函数。

(3)对于mips处理器,执行流程如下:handle_int —> plat_irq_dispatch —> do_IRQplat_irq_dispatch由班级支持包中实现。上述的流程表示由异常入口函数开始,到调用handle_level_irq结束。对于3款处理器平台,内核在中断分发上没有像中断初始化那样由通用函数到处理器平台函数最后到板级支持函数,而是每种处理器平台都不一样。上述函数的实现都在arch/xxx/kernel下,具体实现可以参考代码。根据上面的分析可以看出,,ARM MIPS PPC在中断分发中中断号的获取都是留给板级支持包来实现的。板级支持包中会读取中断控制器中相关寄存器来获取当前产生的中断情况,进而返回中断号。所以结合中断初始化部分提出的问题,不管哪款处理器平台,如果我们想将35号中断的中断处理函数在注册时放在30号irq_desc中(方法是request_irq时中断号写30)。

那么在中断分发时,获取中断号函数中我们也需要进行修改,查询到中断控制器寄存器状态是产生35号中断,我们返回的中断号应该是30号!但是,这样做并没有实际的应用意义,因为在实际开发中还是要尽量保证内核下irq_desc数组与硬件中断号表一一对应,这样驱动开发者在操作中断时就不需要关心内核中断号和硬件中断号的关系,而是直接使用硬件中断号来注册就可以了。如果内核中断号和硬件中断号不一一对应,驱动开发者在编写驱动时还需要查找硬件中断号和内核中断号的映射表,增大了开发难度。无论如何,借这个无聊的问题,还是搞清了内核中断的初始化和分发过程,也是很值得的但求好事,莫问前程!

版权声明:本文为博主原创文章,未经博主允许不得转载。

活在当下,别在怀念过去或者憧憬未来中浪费掉你现在的生活。

内核中断号必须要跟硬件中断号一致吗

相关文章:

你感兴趣的文章:

标签云: