Linux对中断处理的框架及代码流程简述

一、异常向量入口: arch\arm\kernel\entry-armv.S

.L__vectors_start:
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)  pc, .L__vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq

二、中断向量: vector_irq

/*
 * Interrupt dispatcher
 */
    vector_stub irq, IRQ_MODE, 4   // 相当于 vector_irq: ..., 
                                   // 它会根据SPSR寄存器的值,
                                   // 判断被中断时CPU是处于USR状态还是SVC状态, 
                                   // 然后调用下面的__irq_usr或__irq_svc

    .long   __irq_usr               @  0  (USR_26 / USR_32)
    .long   __irq_invalid           @  1  (FIQ_26 / FIQ_32)
    .long   __irq_invalid           @  2  (IRQ_26 / IRQ_32)
    .long   __irq_svc               @  3  (SVC_26 / SVC_32)
    .long   __irq_invalid           @  4
    .long   __irq_invalid           @  5
    .long   __irq_invalid           @  6
    .long   __irq_invalid           @  7
    .long   __irq_invalid           @  8
    .long   __irq_invalid           @  9
    .long   __irq_invalid           @  a
    .long   __irq_invalid           @  b
    .long   __irq_invalid           @  c
    .long   __irq_invalid           @  d
    .long   __irq_invalid           @  e
    .long   __irq_invalid           @  f

三、 __irq_usr/__irq_svc

这2个函数的处理过程类似:
保存现场
调用 irq_handler
恢复现场

四、irq_handler: 将会调用C函数 handle_arch_irq

.macro  irq_handler

#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
ldr r1, =handle_arch_irq
mov r0, sp
badr lr, 9997f
ldr pc, [r1]
#else
arch_irq_handler_default
#endif
9997:
.endm

五、handle_arch_irq的处理过程

读取寄存器获得中断信息: hwirq
把hwirq转换为virq
调用 irq_desc[virq].handle_irq
对于S3C2440, s3c24xx_handle_irq 是用于处理中断的C语言入口函数

六、中断源介绍

在这里插入图片描述

七、中断描述结构体irq_desc介绍

在这里插入图片描述

八、虚拟中断号和硬件终端号介绍

虚拟中断时时irq_desc的下标
在这里插入图片描述

九、总结中断处理流程

假设中断结构如下:
sub int controller —> int controller —> cpu

发生中断时,
cpu跳到"vector_irq", 保存现场, 调用C函数handle_arch_irq

handle_arch_irq:
a. 读 int controller, 得到hwirq
b. 根据hwirq得到virq
c. 调用 irq_desc[virq].handle_irq

如果该中断没有子中断, irq_desc[virq].handle_irq的操作:
a. 取出irq_desc[virq].action链表中的每一个handler, 执行它
b. 使用irq_desc[virq].irq_data.chip的函数清中断

如果该中断是由子中断产生, irq_desc[virq].handle_irq的操作:
a. 读 sub int controller, 得到hwirq’
b. 根据hwirq’得到virq
c. 调用 irq_desc[virq].handle_irq

猜你喜欢

转载自blog.csdn.net/qq_18077275/article/details/108860113
今日推荐