startup.S 简介

更新时间:
2024-01-10
下载文档

startup.S 简介

startup.S 是内核启动时执行的第一个文件。它主要用于实现系统启动时的复位操作。本节以上述创建的空 BSP 工程为例,简要介绍 IDE 中自动生成的 startup.S 文件里实现的相关操作。

堆栈设置

堆栈设置详情如下,startup.S 文件中包含的几个宏定义,用于配置 CPU 在各个处理器模式下的堆栈空间大小。CPU 总的堆栈大小是这几种模式下堆栈大小的总和,一般情况下,不需要对其做修改。

#define SVC_STACK_SIZE  0x00002000
#define SYS_STACK_SIZE  0x00001000
#define FIQ_STACK_SIZE  0x00001000
#define UND_STACK_SIZE  0x00001000
#define ABT_STACK_SIZE  0x00001000
#define IRQ_STACK_SIZE  0x00001000
#define CPU_STACKS_SIZE     (SVC_STACK_SIZE + \
                             SYS_STACK_SIZE + \
                             FIQ_STACK_SIZE + \
                             IRQ_STACK_SIZE + \
                             UND_STACK_SIZE + \
                             ABT_STACK_SIZE)

函数的声明与导出

汇编代码中如需使用外部函数,则要先对其进行声明。startup.S 中外部函数的声明详情如下,前面声明的几个函数用于处理异常向量。bspInit 函数作为从汇编代码跳入 C 代码执行的入口函数。

IMPORT_LABEL(archIntEntry)
IMPORT_LABEL(archAbtEntry)
IMPORT_LABEL(archPreEntry)
IMPORT_LABEL(archUndEntry)
IMPORT_LABEL(archSwiEntry)
IMPORT_LABEL(bspInit)

注:在创建的空的 BSP 工程里没有将 startup.S 里的函数作导出的操作。

异常向量表

异常向量表大多数情况下是通过汇编代码来实现,startup.S 中的 vector 段详情如下所示。vector 段内定义了一些标签,用伪指令将其指向对应的异常处理函数,而异常处理函数就是上文“函数的声明与导出”中声明的外部函数。异常向量表把这些标签赋值给 PC 指针,当发生对应异常时,程序就能通过异常向量表跳转到对应的异常处理函数中执行。

SECTION(.vector)
FUNC_DEF(vector)
    LDR     PC, resetEntry
    LDR     PC, undefineEntry
    LDR     PC, swiEntry
    LDR     PC, prefetchEntry
    LDR     PC, abortEntry
    LDR     PC, reserveEntry
    LDR     PC, irqEntry
    LDR     PC, fiqEntry
    FUNC_END()
FUNC_LABEL(resetEntry)
    .word   reset
FUNC_LABEL(undefineEntry)
    .word   archUndEntry
FUNC_LABEL(swiEntry)
    .word   archSwiEntry
FUNC_LABEL(prefetchEntry)
    .word   archPreEntry
FUNC_LABEL(abortEntry)
    .word   archAbtEntry
FUNC_LABEL(reserveEntry)
    .word   0
FUNC_LABEL(irqEntry)
    .word   archIntEntry
FUNC_LABEL(fiqEntry)
    .word   0

代码段

startup.S 的代码段主要定义了 reset 函数。它是系统复位及启动时第一个执行的函数。reset 函数主要进行以下操作:

  • 关看门狗

系统启动时,要将看门狗先关闭,防止不喂狗导致系统不断复位,不能正常启动。

  • 初始化堆栈

为了初始化不同工作模式下的堆栈,reset 函数会通过设置 CPSR 寄存器和关中断的操作,让 CPU 处于对应的工作模式,然后根据配置的堆栈宏,设置 CPU 各个模式下的堆栈指针。

  • 对核心硬件接口的操作

如 SDRAM、PLL 等,但一般这部分内容在 bootloader 中已经实现,因此这里可以不做操作。

  • 初始化 data 段

参看 SylixOSBSP.ld 链接脚本,在链接器进行链接时会将 data 段初始化的数据装载在 text 段,装载地址为 _etext,但 data 段真正的运行地址为 ORIGIN(DATA),因此 startup.S 初始化 data 段的主要工作就是将 _etext 的内容搬运到 ORIGIN(DATA)处,搬运的大小为 SIZEOF(.data)。

  • 清 bss 段

reset 函数初始化 data 段之后,需要将 bss 段清零。

  • 执行 C 程序

进入 bspInit 函数。根据 ATPCS 协议,reset 函数会设置 R0、R1、R2 和 FD,并把当前的地址保存到 LR 寄存器用于返回,然后跳转到 bspInit 函数中执行。

注意
当前工程 bspinit 函数没有接收参数,若需要,可以在汇编中对 R0 等寄存器做操作。

文档内容是否对您有所帮助?
有帮助
没帮助