2. 理解VxWorks启动流程

任务目标

本案例要求基于VxWorks BSP源码中的romInit.s与romStart.c两个文件,梳理系统从上电复位到C语言入口usrInit之间的完整启动路径,明确各阶段职责与关键跳转关系。

前置环境

需要一份实际BSP源码(如target/config/xxxBSP/目录),其中包含romInit.s(汇编启动文件)与romStart.c(ROM启动C代码)。若无现成BSP,可使用VxWorks安装目录下任意参考BSP(如mv162、pcPentium)对照阅读。

启动路径总览

VxWorks的启动分为两个阶段:ROM启动(从复位到usrInit)和RAM启动(usrInit之后)。本案例聚焦ROM启动阶段,其核心路径如下:

复位入口(_romInit)
   ↓ 初始化CPU状态、关闭中断、设置栈指针
   ↓ 拷贝ROM/Flash中的代码到RAM(若配置为ROM_RESIDENT或ROM_COMPRESS)
   ↓ 跳转到C函数 romStart()
   ↓ 执行 romStart():拷贝数据段、清零BSS、解压缩(若压缩)
   ↓ 调用 usrInit()(C语言入口,后续进入VxWorks内核初始化)

关键文件职责

文件职责关键符号
romInit.s复位向量入口,CPU最低层初始化(关中断、设栈、初始化寄存器),最终跳转romStart_romInit, _romStart
romStart.cC语言启动代码,完成内存布局准备(拷贝/解压/清BSS),最后调用usrInitromStart(), usrInit()

核心代码定位与关键片段

以下为两个文件中必须理解的关键代码位置(以典型BSP为例,具体行号因BSP而异):

1. romInit.s 关键片段(汇编)


    .text
    .globl _romInit
_romInit:
    /* 1. 设置CPU为超级模式,关闭所有中断 */
    mfsr    r0, 0                    /* 示例:读状态寄存器 */
    /* 2. 初始化栈指针(临时栈,供romStart使用) */
    lis     sp, _stack_addr@ha
    addi    sp, sp, _stack_addr@l
    /* 3. 若配置了ROM_COMPRESS,此处调用解压函数 */
    /* 4. 跳转到C入口 */
    lis     r3, _romStart@ha
    addi    r3, r3, _romStart@l
    mtlr    r3
    blr

2. romStart.c 关键逻辑(C代码)


void romStart(void)
{
    /* 1. 将数据段从ROM拷贝到RAM(若为ROM_RESIDENT则跳过) */
    copyDataSegments();

    /* 2. 清零BSS段 */
    clearBss();

    /* 3. 若启用了压缩,解压内核到RAM */
#ifdef ROM_COMPRESS
    decompressKernel();
#endif

    /* 4. 跳转到usrInit,进入VxWorks内核初始化 */
    usrInit();
}
阅读方法:在真实BSP中,romInit.s的末尾必然存在跳转到romStart的指令(通常通过blr或b指令),而romStart.c的末尾必然调用usrInit()。找到这两处跳转即可确认启动路径的完整性。

验证方法

由于本案例是源码分析任务,验证方式为静态检查:

  1. 在romInit.s中搜索romStart符号,确认存在跳转指令(b/blr/call等)。
  2. 在romStart.c中搜索usrInit,确认存在函数调用。
  3. 确认romInit.s中设置了栈指针(sp/r1),否则C代码无法运行。
  4. 若BSP配置了ROM_COMPRESS,确认romStart.c中调用了解压函数。

通过条件:以上4项均能在源码中找到对应实现,且跳转顺序为_romInit → romStart → usrInit,即可判定启动路径梳理正确。

常见问题

  • 找不到usrInit调用? 某些BSP在romStart末尾通过函数指针间接调用,搜索usrInit字符串即可定位。
  • 栈指针初始化位置? 必须在跳转C代码之前完成,通常位于romInit.s的前半部分。
  • ROM_RESIDENT与ROM_COMPRESS的区别? ROM_RESIDENT表示代码直接在ROM中运行,无需拷贝;ROM_COMPRESS表示代码压缩存储,需先解压到RAM再运行。