3. BSP目录结构解析:BSP源码目录组织、关键文件说明
在VxWorks BSP开发中,理解BSP目录结构是第一步。一个规范的BSP目录不仅决定了编译系统能否正确找到源文件,还直接影响了ROM启动阶段的寄存器配置与链接脚本加载。本章将深入解析BSP源码的目录组织方式,并对config.h、makefile、romInit.s、sysLib.c四个关键文件进行详细说明。
核心观点: BSP目录结构是VxWorks启动流程的“骨架”,关键文件是“血肉”。掌握目录组织与文件职责,是定制ROM启动与寄存器配置的基础。
3.1 BSP目录结构总览
一个典型的VxWorks BSP目录通常包含以下子目录和文件。不同CPU架构(如ARM、PowerPC、x86)的BSP目录结构基本一致,但部分文件(如romInit.s)的汇编指令会因架构而异。
3.2 关键文件详解
3.2.1 config.h — 板级配置中心
config.h是BSP中最重要的头文件,它定义了板级硬件参数、内存布局、外设使能开关以及启动模式。VxWorks编译系统通过读取config.h中的宏定义来决定哪些功能被编译进内核。
| 宏定义 | 功能说明 | 典型值 |
|---|---|---|
LOCAL_MEM_LOCAL_ADRS |
本地内存起始物理地址 | 0x80000000 |
LOCAL_MEM_SIZE |
本地内存大小(字节) | 0x10000000 (256MB) |
ROM_BASE_ADRS |
ROM启动基地址 | 0xbfc00000 |
ROM_TEXT_ADRS |
ROM代码段起始地址 | 0xbfc00100 |
INCLUDE_MMU |
是否启用MMU | 1 或 0 |
INCLUDE_CACHE |
是否启用Cache | 1 或 0 |
实战提示: 在ROM启动场景中,
ROM_BASE_ADRS和ROM_TEXT_ADRS必须与硬件复位向量地址一致。例如,MIPS架构的复位向量通常为0xbfc00000,而ARM Cortex-A系列通常为0x00000000或0xffff0000。
3.2.2 makefile — 编译构建规则
BSP的makefile定义了编译目标、源文件路径、链接脚本以及编译器选项。它通常包含以下关键部分:
- 目标定义: 指定生成
vxWorks、vxWorks_rom、vxWorks_romCompress等镜像。 - 源文件列表: 通过
MACH_EXTRA或BOOT_EXTRA变量添加BSP特有的源文件。 - 链接脚本: 指定
ldscript或linker.cmd,控制代码段、数据段在ROM/RAM中的布局。 - 编译器标志: 如
-mcpu=cortex-a9、-mno-unaligned-access等。
# 典型的BSP makefile片段
TARGET_BASE = vxWorks
MACH_EXTRA = \
src/drv/timer/armGenericTimer.c \
src/drv/serial/pl011Uart.c
BOOT_EXTRA = \
rom/romInit.o \
rom/romStart.o
LDSCRIPT = ${BSP_DIR}/linker.ld
CFLAGS += -mcpu=cortex-a9 -mthumb -Os
3.2.3 romInit.s — ROM启动汇编入口
romInit.s是ROM启动的第一个执行文件,通常由汇编语言编写。它负责完成CPU最底层的初始化,包括:
- 设置CPU模式与堆栈指针(SP):确保CPU处于特权模式,并初始化临时堆栈。
- 关闭中断与MMU/Cache:在早期启动阶段,必须关闭所有中断和内存管理单元,避免异常。
- 配置关键寄存器:如时钟、看门狗、PLL等,确保CPU能稳定运行。
- 跳转到C语言入口:通常跳转到
romStart()或sysInit()。
/* romInit.s 典型代码结构(ARM Cortex-A9) */
.globl _romInit
_romInit:
/* 1. 设置CPU为SVC模式,关闭IRQ/FIQ */
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0xD3
msr cpsr, r0
/* 2. 关闭MMU、Cache、分支预测 */
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x0005 @ 关闭MMU和DCache
bic r0, r0, #0x1000 @ 关闭ICache
mcr p15, 0, r0, c1, c0, 0
/* 3. 初始化堆栈指针 */
ldr sp, =_stack_addr
/* 4. 跳转到C语言入口 */
bl romStart
常见错误: 在
romInit.s中忘记关闭看门狗定时器(WDT),导致在ROM启动过程中看门狗超时复位,系统陷入无限重启循环。务必在汇编阶段早期禁用WDT。
3.2.4 sysLib.c — 板级系统库
sysLib.c是BSP中C语言层面的板级初始化与驱动管理文件。它实现了VxWorks内核与硬件之间的抽象层,主要包含以下函数:
| 函数名 | 功能 | 调用时机 |
|---|---|---|
sysInit() |
板级早期初始化,设置时钟、中断控制器 | ROM启动早期 |
sysHwInit() |
硬件设备初始化,如UART、GPIO、定时器 | 内核启动阶段 |
sysMemInit() |
内存控制器初始化,配置SDRAM/DDR时序 | ROM启动中期 |
sysSerialHwInit() |
串口硬件初始化,用于调试输出 | 内核启动阶段 |
/* sysLib.c 中 sysMemInit 的典型实现 */
STATUS sysMemInit(void)
{
/* 配置DDR控制器寄存器 */
*(volatile UINT32 *)(DDR_CTRL_BASE + 0x00) = 0x01000001; // 时序参数
*(volatile UINT32 *)(DDR_CTRL_BASE + 0x04) = 0x00020002; // 刷新周期
*(volatile UINT32 *)(DDR_CTRL_BASE + 0x08) = 0x00000003; // 使能DDR
/* 等待DDR初始化完成 */
while (!(*(volatile UINT32 *)(DDR_CTRL_BASE + 0x0C) & 0x01));
return OK;
}
3.3 文件之间的调用关系
在ROM启动流程中,这四个关键文件按照严格的顺序被调用:
3.4 目录结构最佳实践
- 保持目录扁平化:避免过深的子目录嵌套,建议最多3层(如
src/drv/serial/)。 - 分离ROM与RAM代码:将ROM启动专用的汇编文件放在
rom/目录下,与普通驱动代码隔离。 - 使用版本控制:在BSP根目录添加
.gitignore,忽略target/编译输出目录。 - 统一头文件引用:所有寄存器地址宏定义集中在
include/h/下的一个头文件中,如regs.h。
总结: BSP目录结构是VxWorks移植的“地图”,
config.h是配置中心,makefile是构建引擎,romInit.s是启动入口,sysLib.c是硬件抽象层。掌握这四者的关系,就能在ROM启动与寄存器配置中游刃有余。