跳转至

启动编译相关内容

ARM_Startup.s

File      : ARM_Startup.s
Purpose   : Generic startup and exception handlers for ARM devices.

Additional information:
  Preprocessor Definitions
    __FLASH_BUILD
      If defined,
        additional code can be executed in Reset_Handler,
        which might be needed to run from Flash but not to run from RAM.

    __SUPERVISOR_START
      If defined,
        application starts in supervisor mode instead of system mode.

    __HYPERVISOR_START
      If != 0 (default on ARMv8A and ARMv8R)
        Check if system is in Hypervisor mode and leave it.
        Might be necessary for at least ARMv8A/R,
        because stack setup requires mode change, which cannot be
        done in Hypervisor mode.
      If == 0 (default otherwise)
        Do not check mode before stack setup.

    __SOFTFP__
      Defined by the build system.
      If not defined, the FPU is enabled for floating point operations.

文件ARM_Startup.s
用途ARM 设备的通用启动与异常处理代码

预处理宏说明
    __FLASH_BUILD
    若定义 Reset_Handler 里会额外执行一段代码
    这段代码仅在 Flash 启动时才需要 RAM 启动则不需要

    __SUPERVISOR_START
    若定义应用程序启动后直接进入 Supervisor 模式而非默认的 System 模式

    __HYPERVISOR_START
     0ARMv8-A/R 默认
    先检查当前是否处于 Hypervisor 模式如果是就退出该模式
     ARMv8-A/R 上必须这样做因为后面要切模式来初始化栈 Hypervisor 模式下禁止切模式
    = 0其它架构默认
    初始化栈之前不做模式检查

    __SOFTFP__
    由编译系统自动定义
    若未定义则表示使用硬件 FPU 做浮点运算
*/

        .syntax unified  


#ifndef __HYPERVISOR_START
  #if defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)
    #define __HYPERVISOR_START 1
  #else
    #define __HYPERVISOR_START 0
  #endif
#endif

/*********************************************************************
*
*       Macros
*
**********************************************************************
*/
//
// Declare an interrupt handler
// 定义一个带默认参数的可调用宏
//
.macro ISR_HANDLER Name=
        //
        // Insert vector in vector table
        //
        // 切到向量表段,属性可分配(a)、可执行(x)。
        // 标志字符串,a = allocatable(将来要装进 ELF 段头,占用 Flash),x = executable(允许 CPU 取指)。
        .section .vectors, "ax"    
        ldr     PC, =\Name
        //
        // Insert dummy handler in init section
        //
        // 再切到以函数名命名的独立段,用来放“默认的哑处理函数”。
        .section .init.\Name, "ax"
        .code 32                   // 告诉汇编器后面的指令按 32-bit ARM 编码(和 Thumb 无关)。
        .type \Name, function      // 给符号打 STT_FUNC 类型,调试/链接更友好。
        .weak \Name                // 声明为“弱符号”。
        .balign 4                  // 4 字节对齐,保证指令地址合法。
\Name:                             // 标号,也就是默认处理函数入口。
        1: b 1b   // Endless loop  // 原地跳自己,无限循环——典型的“未实现中断/异常就卡死”的默认行为。
        END_FUNC \Name             // 一般是个宏,等价于 .size \Name, .-\Name 把函数大小写进符号表,方便调试。   
.endm                              // 宏定义结束。

//
// Place a reserved isr handler
//
.macro ISR_RESERVED
        .section .vectors, "ax"  // nop 指令的机器码是 0xE1A00000(ARM)或 0xBF00(Thumb-2 16-bit),占 4 字节,正好填满一个向量槽
        nop
.endm

//
// Mark the end of a function and calculate its size
// . - \name  就是“光标位置 - 入口位置” 
// .size \name   ,  . - my_func 只是把算出来的这个差值填进符号表,告诉工具链 \name 这段机器码一共这么长。
.macro END_FUNC name
        .size \name,.-\name
.endm

#if defined(__ARM_ARCH_4T__)
.macro blx reg
  mov lr, pc
  bx \reg
.endm
#endif 

/*********************************************************************
*
*       Global data
*
**********************************************************************
*/
/*********************************************************************
*
*  Setup of the exception table
*
*/
        .section .vectors, "ax"
        .code 32
        .balign 4
        .global _vectors
_vectors:
        ldr     PC, =Reset_Handler
        ISR_HANDLER undef_handler
        ISR_HANDLER swi_handler
        ISR_HANDLER pabort_handler
        ISR_HANDLER dabort_handler
        ISR_RESERVED
        //ISR_HANDLER irq_handler
        //增加新的
        ldr     PC, =IRQ_Handler   
        ISR_HANDLER fiq_handler

        .section .vectors, "ax"
        .size _vectors, .-_vectors
_vectors_end:

/*********************************************************************
*
*       Global functions
*
**********************************************************************
*/
/*********************************************************************
*
*       Reset_Handler
*
*  Function description
*    Exception handler for reset.
*    Generic bringup of a system.
*/
        .section .init.Reset_Handler, "ax"
        .code 32
        .balign 4
        .global reset_handler
        .global Reset_Handler
        .equ    reset_handler, Reset_Handler
        .type   Reset_Handler, function
Reset_Handler:
    cpsid i                     /* 关闭全局中断 */

    /* 关闭I,DCache和MMU 
     * 采取读-改-写的方式。
     */
    mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中                           */
    bic     r0,  r0, #(0x1 << 12)     /* 清除C1寄存器的bit12位(I位),关闭I Cache               */
    bic     r0,  r0, #(0x1 <<  2)     /* 清除C1寄存器的bit2(C位),关闭D Cache                 */
    bic     r0,  r0, #0x2             /* 清除C1寄存器的bit1(A位),关闭对齐                      */
    bic     r0,  r0, #(0x1 << 11)     /* 清除C1寄存器的bit11(Z位),关闭分支预测                   */
    bic     r0,  r0, #0x1             /* 清除C1寄存器的bit0(M位),关闭MMU                     */
    mcr     p15, 0, r0, c1, c0, 0     /* 将r0寄存器中的值写入到CP15的C1寄存器中                    */

#if 0
    /* 汇编版本设置中断向量表偏移 */
    ldr r0, =0X87800000

    dsb
    isb
    mcr p15, 0, r0, c12, c0, 0
    dsb
    isb
#endif

    /* 设置各个模式下的栈指针,
     * 注意:IMX6UL的堆栈是向下增长的!
     * 堆栈指针地址一定要是4字节地址对齐的!!!
     * DDR范围:0X80000000~0X9FFFFFFF
     */
    /* 进入IRQ模式 */
    mrs r0, cpsr
    bic r0, r0, #0x1f   /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4  */
    orr r0, r0, #0x12   /* r0或上0x13,表示使用IRQ模式                   */
    msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中                    */
    ldr sp, =0x80600000 /* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB */

    /* 进入SYS模式 */
    mrs r0, cpsr
    bic r0, r0, #0x1f   /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4  */
    orr r0, r0, #0x1f   /* r0或上0x13,表示使用SYS模式                   */
    msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中                    */
    ldr sp, =0x80400000 /* 设置SYS模式下的栈首地址为0X80400000,大小为2MB */

    /* 进入SVC模式 */
    mrs r0, cpsr
    bic r0, r0, #0x1f   /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4  */
    orr r0, r0, #0x13   /* r0或上0x13,表示使用SVC模式                   */
    msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中                    */
    ldr sp, =0X80200000 /* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */

    cpsie i             /* 打开全局中断 */
#if 0
    /* 使能IRQ中断 */
    mrs r0, cpsr        /* 读取cpsr寄存器值到r0中           */
    bic r0, r0, #0x80   /* 将r0寄存器中bit7清零,也就是CPSR中的I位清零,表示允许IRQ中断 */
    msr cpsr, r0        /* 将r0重新写入到cpsr中            */
#endif

    b _start                /* 跳转到main函数                */

/* IRQ中断!重点!!!!! */
IRQ_Handler:
    push {lr}                   /* 保存lr地址 */
    push {r0-r3, r12}           /* 保存r0-r3,r12寄存器 */

    mrs r0, spsr                /* 读取spsr寄存器 */
    push {r0}                   /* 保存spsr寄存器 */

    mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中
                                * 参考文档ARM Cortex-A(armV7)编程手册V4.0.pdf P49
                                * Cortex-A7 Technical ReferenceManua.pdf P68 P138
                                */                          
    add r1, r1, #0X2000         /* GIC基地址加0X2000,也就是GIC的CPU接口端基地址 */
    ldr r0, [r1, #0XC]          /* GIC的CPU接口端基地址加0X0C就是GICC_IAR寄存器,
                                 * GICC_IAR寄存器保存这当前发生中断的中断号,我们要根据
                                 * 这个中断号来绝对调用哪个中断服务函数
                                 */
    push {r0, r1}               /* 保存r0,r1 */

    cps #0x13                   /* 进入SVC模式,允许其他中断再次进去 */

    push {lr}                   /* 保存SVC模式的lr寄存器 */
    ldr r2, =SystemIrqHandler   /* 加载C语言中断处理函数到r2寄存器中*/
    blx r2                      /* 运行C语言中断处理函数,带有一个参数,保存在R0寄存器中 */

    pop {lr}                    /* 执行完C语言中断服务函数,lr出栈 */
    cps #0x12                   /* 进入IRQ模式 */
    pop {r0, r1}                
    str r0, [r1, #0X10]         /* 中断执行完成,写EOIR */

    pop {r0}                        
    msr spsr_cxsf, r0           /* 恢复spsr */

    pop {r0-r3, r12}            /* r0-r3,r12出栈 */
    pop {lr}                    /* lr出栈 */
    subs pc, lr, #4             /* 将lr-4赋给pc */  

/*************************** End of file ****************************/

SEGGER_ARM_Startup.s


FLASH1 RX 0x00910000 0x00010000;RAM1 RWX 0x00900000 0x00010000;FLASH2 RX 0x86800000 0x01000000;RAM2 RWX 0x80000000 0x01000000;

FLASH1 RX 0x00910000 0x00010000

RAM1 RWX 0x00900000 0x00010000

FLASH2 RX 0x86800000 0x01000000

RAM2 RWX 0x80000000 0x01000000