3、linux中断中(异常向量详解)

中断程序完成了从asm代码到C代码的传递,并且获得了引起中断的IRQ编号

中断向量表在arch/arm/kernel/entry_armv.S中定义

这里写图片描述

代码被分为两部分:
第一部分是真正的向量跳转表,位于__vectors_start__vectors_end之间;
第二部分是处理跳转的部分,位于__stubs_start__stubs_end之间;

  .globl  __stubs_start  
__stubs_start:  

    vector_stub irq, IRQ_MODE, 4  

    .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)  

    vector_stub dabt, ABT_MODE, 8  

    .long   __dabt_usr          @  0  (USR_26 / USR_32)  
    .long   __dabt_invalid          @  1  (FIQ_26 / FIQ_32)  
    .long   __dabt_invalid          @  2  (IRQ_26 / IRQ_32)  
    .long   __dabt_svc          @  3  (SVC_26 / SVC_32)  

vector_fiq:  
    disable_fiq  
    subs    pc, lr, #4  
    ......  
    .globl  __stubs_end  
__stubs_end:  



    .equ    stubs_offset, __vectors_start + 0x200 - __stubs_start  
    .globl  __vectors_start  
__vectors_start:  
 ARM(   swi SYS_ERROR0  )  
 THUMB( svc #0      )  
 THUMB( nop         )  
    W(b)    vector_und + stubs_offset  
    W(ldr)  pc, .LCvswi + stubs_offset  
    W(b)    vector_pabt + stubs_offset  
    W(b)    vector_dabt + stubs_offset  
    W(b)    vector_addrexcptn + stubs_offset  
    W(b)    vector_irq + stubs_offset  
    W(b)    vector_fiq + stubs_offset  

    .globl  __vectors_end  
__vectors_end:  

中断向量表的使用:

这里写图片描述
1. 首先,在setup_arch函数中,early_trap_init被调用,其中完成了中断向量的拷贝和重定位工作。

void __init early_trap_init(void)  
{  
    ......  
    /* 
     * Copy the vectors, stubs and kuser helpers (in entry-armv.S) 
     * into the vector page, mapped at 0xffff0000, and ensure these 
     * are visible to the instruction stream. 
     */  
    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);  
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);  
    ......  
}  

两个memcpy会把__vectors_start开始的代码拷贝到0xffff0000处,把__stubs_start开始的代码拷贝到0xFFFF0000+0x200处,这样,异常中断到来时,CPU就可以正确地跳转到相应中断向量入口并执行他们。
这里写图片描述


  1. 然后,start_kernel发出early_irq_init调用,early_irq_init属于与硬件和平台无关的通用逻辑层,它完成irq_desc结构的内存申请,为它们其中某些字段填充默认值,完成后调用体系相关的arch_early_irq_init函数完成进一步的初始化工作,不过ARM体系没有实现arch_early_irq_init

  2. 接着,start_kernel发出init_IRQ调用,它会直接调用所属板子machine_desc结构体中的init_irq回调。machine_desc通常在板子的特定代码中,使用MACHINE_START和MACHINE_END宏进行定义。
    machine_desc->init_irq()完成对中断控制器的初始化,为每个irq_desc结构安装合适的流控handler,为每个irq_desc结构安装irq_chip指针,使他指向正确的中断控制器所对应的irq_chip结构的实例,同时,如果该平台中的中断线有多路复用(多个中断公用一个irq中断线)的情况,还应该初始化irq_desc中相应的字段和标志,以便实现中断控制器的级联。

猜你喜欢

转载自blog.csdn.net/qq_33487044/article/details/81411891