关于i.mx6ull中断向量表执行问题

i.mx6ull中断向量表部分代码如下:
疑问:在_start中,汇编代码具体是如何执行和跳转的(越具体越好,从下面的代码分析)?ldr pc, =label是否会被执行?
我的理解:
①程序必然执行第一行ldr pc, =Reset_Handler,随后跳转到Reset_Handler中,并最终通过b main跳转到main函数
②剩余的ldr pc,=label 不会被执行,但编译器会给到这些指令相应的程序地址(0x04、0x08、0x0C),用于发生中断时跳转到相应的程序地址去执行中断函数

.global _start

_start:
    ldr     pc, =Reset_Handler           /* Reset                  */     
    ldr     pc, =Undefined_Handler       /* Undefined instructions */
    ldr     pc, =SVC_Handler             /* Supervisor Call        */
    ldr     pc, =PrefAbort_Handler       /* Prefetch abort         */
    ldr     pc, =DataAbort_Handler       /* Data abort             */
    .word   0                                      /* RESERVED               */
    ldr     pc, =IRQ_Handler             /* IRQ interrupt          */
    ldr     pc, =FIQ_Handler             /* FIQ interrupt          */

Reset_Handler:

    cpsid   i                         /* 全局关闭中断 */

    mrc     p15, 0, r0, c1, c0, 0     /*读取CP15系统控制寄存器   */
    bic     r0,  r0, #(0x1 << 12)     /*  清除第12位(I位)禁用 I Cache  */
    bic     r0,  r0, #(0x1 <<  2)     /*  清除第 2位(C位)禁用 D Cache  */
    bic     r0,  r0, #0x2             /*  清除第 1位(A位)禁止严格对齐   */
    bic     r0,  r0, #(0x1 << 11)     /*  清除第11位(Z位)分支预测   */
    bic     r0,  r0, #0x1             /*  清除第 0位(M位)禁用 MMU   */
    mcr     p15, 0, r0, c1, c0, 0     /*  将修改后的值写回CP15寄存器   */

    /* 定义IRQ工作模式的栈起始地址 */
    cps     #0x12                
    ldr     sp, =IRQ_model_stack_start    

    /*定义User工作模式的栈起始地址,与Supervisor相同*/
    cps     #0x1F               
    ldr     sp, =SUP_model_stack_start    

    /*定义Supervisor工作模式的栈起始地址,与User相同 */
    cps     #0x13                
    ldr     sp, =SUP_model_stack_start   

    /*跳转到系统初始化函数,初始化GIC、CACHE-L1、mmu等等*/
    ldr     r2, =SystemInit      
    blx     r2  
   
    /*开启全局中断*/
    cpsie   i                   
  
    /*跳转到到 main 函数执行,*/
    b main                
    b .        /*死循环*/

在i.mx6ull中断向量表部分的代码中,_start标签表示程序的入口点。程序开始执行时,它会首先执行ldr pc, =Reset_Handler这一指令,该指令将Reset_Handler的地址加载到寄存器pc中,并通过跳转指令实现跳转到该地址处执行中断处理函数。然后,程序会进入中断向量表,寻找相应的处理函数,具体如下:

  • 如果发生未定义的指令,程序会跳转到Undefined_Handler处理函数。
  • 如果发生SVC类型的中断,程序会跳转到SVC_Handler处理函数。
  • 如果发生Prefetch Abort异常,程序会跳转到PrefAbort_Handler处理函数。
  • 如果发生Data Abort异常,程序会跳转到DataAbort_Handler处理函数。
  • 如果发生IRQ类型的中断,程序会跳转到IRQ_Handler处理函数。
  • 如果发生FIQ类型的中断,程序会跳转到FIQ_Handler处理函数。

Reset_Handler中,程序首先关闭全局中断,然后使用MRC指令读取CP15系统控制寄存器中的值。接下来的一系列BIC指令用于清除寄存器中的特定位,用于关闭I Cache、D Cache、严格对齐、分支预测、MMU等功能。之后,程序通过MCR指令将修改后的值写回CP15寄存器。此外,程序还会定义栈的起始地址,然后跳转到系统初始化函数(SystemInit)进行系统初始化。最后,开启全局中断并通过跳转指令跳转到main函数执行。

对于剩余的ldr pc, =label指令,它们不会被实际执行。这些指令只是用于为中断处理函数指定相应的程序地址,以便在发生中断时跳转到正确的处理函数。

你的理解是对的!

MX6UL 中断浅析一
可以参考下


https://gitee.com/holographic_light/notes_of_linux/blob/master/imx6ull%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.md