3. 系统启动与初始化过程监控

VxWorks 系统的启动不是一次“上电即运行”的瞬时动作,而是一条由多个阶段串联而成的链:从 CPU 复位向量进入 BootROM,到引导参数解析、VxWorks 映像搬运与解压,再到内核对象建立、驱动挂接、应用任务创建。任何一个阶段失败,最终表现往往都是“系统起不来”或“卡在某处”,但根因位置完全不同。因此,启动监控的核心思路是:把启动链拆成可观测的阶段,为每个阶段找到独立的观测点和判定依据,而不是只盯着最后的应用是否运行。

启动链的阶段划分与观测点

以常见的 ARM/PowerPC 目标板为例,一次典型启动可划分为五个阶段,每个阶段都有其“活着”的证据:

  • BootROM 阶段:CPU 复位后执行 ROM 中的引导代码,初始化内存控制器、串口、时钟,并进入引导命令行。观测点是串口输出的引导版本号与提示符(如 -> 或 BootROM>)。
  • 映像加载阶段:BootROM 根据引导参数(boot device、host IP、file name)通过 TFTP/Flash/磁盘读取 VxWorks 映像,校验后搬运到 RAM 入口地址。观测点是加载进度、映像长度、校验结果。
  • 内核初始化阶段:映像入口执行 usrInit,建立内核数据结构、中断向量表、系统时钟、内存池,随后启动 tUsrRoot 根任务。观测点是内核版本打印、内存池大小、时钟 tick 是否正常。
  • 驱动初始化阶段:根任务按 sysHwInit/sysClkInit/usrDrvInit 顺序挂接串口、网口、存储等驱动。观测点是各驱动注册日志、设备节点是否出现。
  • 应用启动阶段:usrAppInit 创建应用任务、打开设备、建立通信。观测点是应用任务名、优先级、首条业务日志。

下图给出这五个阶段的信号链关系,并标注每个阶段的关键观测点与典型异常表现,便于在排障时快速定位“卡在哪一段”。

VxWorks 启动链五阶段信号流与观测点 ① BootROM 复位向量 / 内存控制器 串口初始化 / 引导命令行 ② 映像加载 TFTP/Flash 读取 校验 / 搬运到 RAM ③ 内核初始化 usrInit / 中断向量 时钟 / 内存池 / tUsrRoot ④ 驱动初始化 sysHwInit / usrDrvInit 串口 / 网口 / 存储挂接 ⑤ 应用启动 usrAppInit 任务 / 设备 / 通信 关键观测点 串口打印 BootROM 版本 出现引导提示符 内存容量自检通过 加载字节数 / 进度 checksum 校验结果 入口地址跳转成功 内核版本 / 编译时间 内存池起始与大小 tUsrRoot 任务创建 驱动注册日志 设备节点 /dev/ 出现 中断号绑定成功 任务名/优先级 首条业务日志 通信链路建立 典型异常与定位方向 串口无任何输出:BootROM 未执行或串口未初始化 → 检查复位向量、时钟、串口引脚与波特率 有 BootROM 但加载失败:网络/Flash 读取错误 → 检查 boot device、IP、文件名、TFTP 服务与校验和 加载后无内核打印:入口地址错误或映像损坏 → 核对 load address 与 entry point,重新生成映像 内核启动后卡在驱动:某驱动初始化阻塞或中断冲突 → 逐项屏蔽驱动,观察最后成功注册的设备 驱动正常但应用不运行:usrAppInit 未挂接或任务创建失败 → 检查应用入口、任务优先级与栈大小

BootROM 阶段:先确认“最小系统”活着

BootROM 是启动链的第一环,它的职责是在没有任何操作系统支持的情况下,把 CPU 带到“能读内存、能输出串口”的状态。监控这一阶段最直接的手段就是串口。上电后应能看到类似下面的输出(示例为合理假设的引导信息):

VxWorks BootROM 2.2  (build 2024-05-10)
Copyright 1984-2024 Wind River Systems
CPU: ARM Cortex-A9  @ 800 MHz
Memory: 512 MB DDR3 @ 0x80000000
Boot Device: motetsec0
Boot File: vxWorks
Host IP: 192.168.1.100
Target IP: 192.168.1.200

如果串口完全无输出,问题通常不在 VxWorks 映像,而在更底层:复位向量是否正确、时钟是否起振、串口引脚复用是否配置、波特率是否匹配。此时应先用示波器或 JTAG 确认 CPU 是否在取指,再检查 BootROM 是否被正确烧写到启动介质。若能看到部分输出但中途停止,则重点看停止位置对应的初始化项——例如内存容量打印后卡住,往往是 DDR 训练或内存控制器参数问题。

映像加载阶段:校验与地址是两大关键

BootROM 进入命令行后,会根据引导参数从网络或 Flash 读取 VxWorks 映像。这一阶段最值得监控的是三个量:读取字节数、校验结果、入口地址。以 TFTP 加载为例,正常输出会显示类似:

Loading vxWorks ... 3145728 bytes read
Checksum: 0x8f3a21c7  OK
Entry point: 0x80010000
Starting at 0x80010000...

若校验失败,说明映像在传输或存储中损坏,应重新生成或重新下载;若校验通过但跳转后无反应,则要核对 Entry point 是否与映像实际链接地址一致。常见错误是把加载地址(load address)与入口地址(entry point)混为一谈:前者是映像被放到 RAM 的位置,后者是 CPU 开始执行的第一条指令地址,两者可以不同,但必须与链接脚本匹配。

内核初始化阶段:看内存池与根任务

映像入口执行后进入 usrInit,这是内核真正开始建立自身运行环境的阶段。此时应关注:内核版本与编译时间是否与预期一致、内存池(system memory pool)的起始地址和大小是否合理、系统时钟 tick 是否正常、根任务 tUsrRoot 是否被创建。一个健康的内核初始化输出通常包含:

VxWorks 6.9  (build 2024-05-10)
Kernel: WIND kernel version 3.0
Memory pool: 0x80100000 - 0x9fffffff (511 MB)
System clock rate: 100 Hz
tUsrRoot started, priority 0

如果内存池大小明显小于物理内存,可能是 sysMemTop 或内存描述表配置错误;如果时钟 tick 不推进,则依赖延时的驱动和应用都会异常。这一阶段还可以通过 memShow 或 ti 命令在后续 shell 中复查内存与任务状态。

驱动初始化阶段:逐项确认设备挂接

根任务随后调用 sysHwInit、sysClkInit、usrDrvInit 等,按顺序初始化硬件和驱动。监控要点是“每个驱动是否成功注册、设备节点是否出现、中断是否绑定”。例如串口驱动应打印设备名,网口驱动应显示 MAC 与链路状态,存储驱动应报告容量。若系统卡死,可用二分法:在 usrDrvInit 中逐项注释驱动初始化,观察最后一条成功日志,从而锁定问题驱动。常见异常包括中断号冲突、DMA 缓冲区地址越界、驱动与硬件版本不匹配。

应用启动阶段:从任务列表确认业务就绪

最后进入 usrAppInit,应用任务被创建。此时应通过 taskShow 或 i 命令查看任务名、优先级、状态和栈使用情况,确认应用任务处于 READY 或 PEND 而非 SUSPEND。若应用未运行,先检查 usrAppInit 是否被正确挂接(在 configAll.h 或 usrConfig.c 中),再检查任务栈是否溢出、优先级是否被高优先级任务长期抢占。首条业务日志的出现,通常可作为应用真正开始工作的标志。

启动监控的通用原则:每一阶段都要有独立的“活着”证据。串口输出是最基础的证据,但不应是唯一证据;结合内存池、任务列表、设备节点和中断统计,才能把“卡住”定位到具体阶段,而不是停留在“系统起不来”的模糊判断上。
注意:引导参数中的 IP 地址、文件名、加载地址和入口地址必须与目标板实际配置一致。修改后应重新上电验证,而不是仅依赖热复位,因为部分 BootROM 在热复位时不会重新读取全部引导参数。