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.c | C语言启动代码,完成内存布局准备(拷贝/解压/清BSS),最后调用usrInit | romStart(), 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()。找到这两处跳转即可确认启动路径的完整性。
验证方法
由于本案例是源码分析任务,验证方式为静态检查:
- 在
romInit.s中搜索romStart符号,确认存在跳转指令(b/blr/call等)。 - 在
romStart.c中搜索usrInit,确认存在函数调用。 - 确认
romInit.s中设置了栈指针(sp/r1),否则C代码无法运行。 - 若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再运行。