1. 课程导入与BSP工程全景
在嵌入式系统开发中,VxWorks 以其高实时性、可裁剪性和稳定性,长期占据工业控制、通信设备、航空航天等关键领域。而 BSP(Board Support Package,板级支持包)正是 VxWorks 从“通用内核”落到“具体硬件”的桥梁。没有 BSP,VxWorks 内核只是一段无法在目标板上运行的代码;有了 BSP,内核才能完成上电初始化、驱动外设、挂载文件系统,最终把控制权交给应用。本课程围绕 BSP 移植与板级适配展开,本章先建立全局视角:VxWorks 如何启动、BSP 在系统中处于什么位置、移植到底要改什么、工程阶段如何划分。
一、VxWorks 启动流程:从复位向量到应用入口
理解 BSP,首先要理解 VxWorks 的启动链条。以常见的 ARM 架构为例,上电后 CPU 从复位向量取指,执行 BSP 中的 romInit.s。这段汇编代码运行在物理地址、MMU 关闭、Cache 未使能的环境中,主要完成:屏蔽中断、初始化时钟与内存控制器、设置栈指针、清零 BSS 段,然后跳转到 romStart()。
romStart() 通常由 C 语言实现,负责把 ROM 中的代码段和数据段搬运到 RAM 中的链接地址,并跳转到 sysInit()。进入 sysInit() 后,系统开始建立 C 运行环境,初始化异常向量表、串口、定时器等最基础资源,随后调用 usrInit()。在 usrInit() 中,VxWorks 完成内核初始化:创建根任务 tRootTask、初始化 Wind 内核、挂载系统时钟,最后进入 usrRoot()。此时用户可以在 usrRoot() 中挂载文件系统、初始化网络、创建设备节点,并启动第一个应用任务。
这条链路中,romInit.s、romStart()、sysInit()、usrInit() 的前半段几乎全部由 BSP 提供或深度参与。换句话说,BSP 决定了“内核能不能跑起来”,而应用决定了“跑起来之后做什么”。
二、BSP 在系统中的位置
从软件层次看,VxWorks 系统自下而上可分为:硬件层、BSP 层、内核层、系统服务层和应用层。BSP 层夹在硬件与内核之间,向上提供统一的 sysLib、intLib、timerLib、cacheLib 等接口,向下直接操作寄存器、中断控制器、定时器、串口、以太网 PHY 等硬件资源。
BSP 的组成通常包括:启动汇编 romInit.s、C 语言初始化 sysLib.c、中断处理 intLib.c、定时器 timerLib.c、串口驱动 ttyDrv 相关配置、网络驱动 endLib 相关配置、配置文件 config.h 与 Makefile,以及内存布局描述 sysPhysMemDesc[]。这些文件共同回答三个问题:硬件怎么初始化、内核怎么访问硬件、系统资源怎么分配。
三、移植与板级适配的核心任务
BSP 移植不是“从零写代码”,而是“以参考 BSP 为起点,针对目标板做差异化适配”。核心任务可以归纳为四条主线。
- 启动适配:修改
romInit.s中的时钟、内存控制器、栈指针、复位类型判断,确保 CPU 能正确进入 C 环境。 - 内存映射:在
sysPhysMemDesc[]中描述物理地址到虚拟地址的映射关系,配置 MMU 页表,区分可缓存与不可缓存区域。 - 驱动适配:根据目标板外设型号,调整串口、网口、Flash、I2C、SPI 等驱动中的基地址、中断号、时钟频率和引脚复用。
- 配置裁剪:在
config.h中使能或关闭组件,调整Makefile中的编译选项、链接地址和镜像格式。
以串口为例,参考 BSP 中 sysSerialHwInit() 通常使用 16550 兼容 UART,基地址为 0x10000000,中断号为 5,输入时钟 24MHz。若目标板改用 16C550 且基地址变为 0x20000000,则需要同步修改基地址、中断号,并重新计算波特率分频值。若忽略时钟差异,串口会输出乱码,这是移植初期最常见的现象之一。
四、典型工程阶段划分
一个完整的 BSP 移植项目通常经历五个阶段:准备与评估、最小系统启动、基础驱动打通、系统服务集成、稳定性验证。准备阶段需要收集目标板原理图、芯片手册、参考 BSP 和工具链;最小系统阶段以“串口能打印”为里程碑;基础驱动阶段打通网口、Flash 和中断;系统服务阶段挂载文件系统、配置网络协议栈;稳定性阶段进行长时间运行、异常注入和边界测试。
五、工程视角下的常见误区
初学者容易把 BSP 移植等同于“改几个地址”。实际上,BSP 的质量取决于对硬件时序、中断优先级、Cache 一致性和内存属性的理解。例如,DMA 缓冲区必须映射为不可缓存,否则会出现数据看似写入却未被外设读取的问题;中断嵌套需要正确配置优先级和屏蔽字,否则高优先级中断可能被低优先级中断阻塞。这些细节不会在“能启动”阶段暴露,却会在压力测试中集中出现。