2. 理解VxWorks启动流程

任务目标

分析VxWorks的bootrom与VxWorks镜像的启动顺序,明确各阶段入口函数与职责,最终能够通过串口日志或调试器定位当前执行到启动流程的哪个阶段。

启动流程概览

VxWorks启动分为两个阶段:bootrom(引导程序)与VxWorks镜像(操作系统内核)。bootrom负责硬件最小初始化、加载VxWorks镜像到内存并跳转;VxWorks镜像随后完成完整系统初始化并启动应用任务。

BootROM 阶段 romInit() romStart() bootConfig() 跳转 VxWorks 阶段 sysInit() usrInit() usrRoot() 启动 应用阶段 usrAppInit() 启动任务 入口: romInit.s 入口: sysInit.s 用户代码

关键入口函数定位

阶段入口文件关键函数职责
BootROMromInit.sromInit()关闭中断、初始化栈指针、拷贝自身到RAM、跳转romStart
BootROMbootrom中的bootConfig.cromStart() → bootConfig()解压/加载VxWorks镜像到RAM,设置启动参数,跳转sysInit
VxWorkssysInit.ssysInit()最低级CPU初始化(关中断、清TLB、设栈),跳转usrInit
VxWorksusrConfig.cusrInit()C环境初始化(cache、内存池、中断向量),调用usrKernelInit
VxWorksusrConfig.cusrRoot()创建根任务,初始化驱动、文件系统、网络,调用usrAppInit

定位启动入口的调试方法

  1. 串口日志观察:bootrom启动时打印BSP版本与启动参数;VxWorks启动时打印内核版本与“Attaching network interface”等标志性信息。观察日志出现顺序即可判断当前阶段。
  2. 调试器断点:在romInit、romStart、sysInit、usrInit、usrRoot处设断点,通过调用栈确认当前执行位置。
  3. LED/GPIO指示:在BSP的sysHwInit中翻转GPIO电平,通过示波器观察电平变化定位启动进度。

最小验证代码

以下代码在usrRoot入口处打印启动标志,用于确认VxWorks内核已完成初始化并进入根任务:

/* 在 usrConfig.c 的 usrRoot() 函数开头添加 */
void usrRoot(char *pMemPool, unsigned long memSize)
    {
    /* 启动标志:串口输出,确认已进入VxWorks根任务 */
    printf("\r\n[BOOT] usrRoot entered. memSize=0x%x\r\n", (unsigned int)memSize);

    /* 原有初始化代码继续执行 */
    ...
    }

运行与验证

  1. 编译bootrom与VxWorks镜像:make bootrom 和 make vxWorks(在BSP目录下)。
  2. 通过JTAG或串口加载bootrom到Flash,复位目标板。
  3. 观察串口输出:若先出现bootrom版本信息,随后出现[BOOT] usrRoot entered,说明启动顺序正确,且已定位到VxWorks根任务入口。
  4. 通过条件:串口完整打印上述两阶段标志信息,且系统最终进入shell提示符(如->),即可判定启动流程正常。

常见问题

  • 启动卡在bootrom不跳转:检查镜像加载地址是否与链接脚本中RAM_HIGH_ADRS一致。
  • 进入usrInit后崩溃:检查sysMemTop返回值是否正确,栈指针是否越界。
  • 无法定位入口:在编译时加-g选项保留符号表,使用nm vxWorks | grep usrRoot确认符号存在。