跳过正文

VxBus 驱动开发:VxWorks 开发人员的完整指南

VxWorks VxBus 设备驱动 嵌入式系统 RTOS 驱动程序开发
目录

简介

设备驱动程序开发是嵌入式系统的核心。在业界领先的实时操作系统(RTOS)VxWorks 中,硬件驱动程序是使用 VxBus 框架实现的。

本指南将全面介绍 VxBus 驱动开发,涵盖从架构到实际实现的方方面面。无论您是 VxWorks 7 的新手,还是从旧版 BSP 风格迁移而来,本文都将帮助您掌握 VxBus,并构建高效、可维护的驱动程序。


为什么 VxBus 在 VxWorks 中如此重要
#

在早期版本的 VxWorks 中,驱动程序通常被硬编码到 BSP(板级支持包)中。这种方法使得维护困难,并且在硬件发生变化时可移植性有限

为了解决这个问题,Wind River 公司引入了 VxBus——一个标准化、可扩展和模块化的驱动程序框架。

VxBus 的优势:

  • 🔌 模块化 – 驱动程序与 BSP 解耦。
  • 高效 – 设备发现和初始化是自动化的。
  • 🔄 可重用 – 同一个驱动程序可以支持多个平台。
  • 🛠️ 可维护 – 代码更清晰,降低了 BSP 的复杂性。
  • 🌍 标准化 – 支持设备树(Device Tree),确保与行业标准对齐。

VxBus 架构概览
#

VxBus 驱动模型借鉴了 Linux 等现代操作系统框架。它围绕着总线-驱动-设备的层次结构展开:

  1. 总线(Bus) – 代表一种互连方式(例如,PCI、I²C、SPI、USB)。
  2. 设备(Device) – 连接到总线的硬件实例,在**设备树(DTS)**中定义。
  3. 驱动(Driver) – 管理设备的软件逻辑。

在启动时,VxBus 会执行以下步骤:

  1. 读取设备树
  2. 枚举设备。
  3. 将每个设备的 compatible 字符串与已注册的驱动程序进行匹配。
  4. 调用驱动程序的 probeattach 函数。

VxBus 驱动开发分步指南
#

1. 在设备树中定义您的设备
#

**设备树源文件(DTS)**是硬件描述的基石。例如,要定义一个 I²C GPIO 扩展器,可以这样做:

i2c@0x10000000 {
    compatible = "nxp,pca9535";
    reg = <0x10000000 0x1000>;
    interrupts = <10 0>;  // 适用的中断线
};

📌 提示: 尽可能使用供应商标准的 compatible 字符串。这可确保您的驱动程序具有可移植性,并与上游约定保持一致。


2. 实现驱动程序骨架
#

一个 VxBus 驱动程序通常包含 probeattachdetach 方法。

LOCAL STATUS myDriverProbe(VXB_DEV_ID pDev) {
    // 检查此驱动程序是否支持该设备
    return OK;
}

LOCAL STATUS myDriverAttach(VXB_DEV_ID pDev) {
    // 初始化寄存器、内存、中断等
    return OK;
}

LOCAL STATUS myDriverDetach(VXB_DEV_ID pDev) {
    // 释放资源,禁用中断
    return OK;
}

LOCAL VXB_DRV_METHOD myDriverMethods[] = {
    { VXB_DEVMETHOD_CALL(vxbDevProbe), myDriverProbe },
    { VXB_DEVMETHOD_CALL(vxbDevAttach), myDriverAttach },
    { VXB_DEVMETHOD_CALL(vxbDevDetach), myDriverDetach },
    VXB_DEVMETHOD_END
};

VXB_DRV myDriver = {
    { NULL },
    "myDriver",
    "示例 VxBus 驱动程序",
    VXB_BUSID_PLB,   // 总线类型
    0,
    sizeof(VXB_DEV_ID),
    myDriverMethods,
    NULL,
    NULL,
    NULL
};

VXB_DRV_DEF(myDriver);

3. 向 VxBus 注册驱动程序
#

在系统初始化期间添加驱动程序:

IMPORT VXB_DRV myDriver;

void sysHwInit(void) {
    vxbDevRegister(&myDriver);
}

4. 处理中断
#

许多设备都依赖中断来实现高效操作。在 VxBus 中,您可以像这样请求一条 IRQ 中断线:

LOCAL void myIsr(void * arg) {
    VXB_DEV_ID pDev = (VXB_DEV_ID) arg;
    // 处理中断
}

LOCAL STATUS myDriverAttach(VXB_DEV_ID pDev) {
    int irq = vxbIntConnect(pDev, 0, myIsr, pDev);
    if (irq != OK) {
        return ERROR;
    }
    vxbIntEnable(pDev, 0, myIsr, pDev);
    return OK;
}

5. DMA 和缓冲区管理
#

对于网卡存储控制器等高性能设备,直接内存访问(DMA)至关重要。

VxBus 提供了用于 DMA 安全内存分配的 API:

void * dmaBuf;
dmaBuf = cacheDmaMalloc(1024);
if (dmaBuf == NULL) {
    return ERROR;
}

📌 始终使用 cacheDmaMalloc() 或类似的 API 来确保缓存一致性。


6. 测试与调试
#

用于驱动程序测试的常用 VxWorks 命令:

  • -> devs – 列出所有已注册的设备。
  • -> i2cShow / -> spiShow – 显示总线设备。
  • -> d (0xADDRESS, 16) – 内存/寄存器值转储。

调试方法:

  • 在早期开发阶段使用 printf
  • 启用 Wind River Workbench 或 WDB 调试器来设置断点。
  • 添加 errnoGet() 检查以诊断错误。

实际案例:VxBus UART 驱动程序
#

为了使 VxBus 驱动开发更具体,我们来创建一个简化的 UART 驱动程序。此示例假设有一个内存映射的 UART 设备,具有基本的发送(TX)和接收(RX)寄存器。

1. 设备树入口
#

首先,在设备树中定义 UART:

uart0: serial@0x101f1000 {
    compatible = "simple,uart";
    reg = <0x101f1000 0x1000>;
    interrupts = <5 0>;
    clock-frequency = <48000000>;
};

这里:

  • reg 定义了 UART 的基地址和大小。
  • interrupts 指定了 IRQ 中断线。
  • clock-frequency 提供了用于波特率计算的输入时钟频率。

2. 寄存器映射
#

此示例假设 UART 具有以下寄存器:

偏移量 寄存器 描述
0x00 UART_DR 数据寄存器(读/写)
0x04 UART_SR 状态寄存器
0x08 UART_CR 控制寄存器
0x0C UART_BAUD 波特率分频寄存器

3. 驱动程序实现
#

#define UART_DR      0x00
#define UART_SR      0x04
#define UART_CR      0x08
#define UART_BAUD    0x0C

#define UART_SR_TX_READY  (1 << 0)
#define UART_SR_RX_READY  (1 << 1)
#define UART_CR_TX_EN     (1 << 0)
#define UART_CR_RX_EN     (1 << 1)

typedef struct {
    VXB_DEV_ID  dev;
    void * base;   // 映射的寄存器基地址
    int         irq;
} UART_DEV;

LOCAL void uartIsr(void * arg) {
    UART_DEV * pDrv = (UART_DEV *) arg;
    UINT32 sr = vxbRead32(pDrv->dev, (UINT32 *) (pDrv->base + UART_SR));

    if (sr & UART_SR_RX_READY) {
        char c = vxbRead8(pDrv->dev, (UINT8 *) (pDrv->base + UART_DR));
        printf("UART RX: %c\n", c);
    }
}

LOCAL STATUS uartProbe(VXB_DEV_ID pDev) {
    return OK; // 在此演示中始终声称支持
}

LOCAL STATUS uartAttach(VXB_DEV_ID pDev) {
    UART_DEV * pDrv = (UART_DEV *) vxbMemAlloc(sizeof(UART_DEV));
    if (!pDrv) return ERROR;

    pDrv->dev  = pDev;
    pDrv->base = (void *) vxbRegMap(pDev, 0, 0);
    pDrv->irq  = vxbIntConnect(pDev, 0, uartIsr, pDrv);

    // 启用 TX/RX
    vxbWrite32(pDev, (UINT32 *)(pDrv->base + UART_CR), UART_CR_TX_EN | UART_CR_RX_EN);

    // 配置波特率
    vxbWrite32(pDev, (UINT32 *)(pDrv->base + UART_BAUD), 48000000 / 115200);

    vxbDevSoftcSet(pDev, pDrv);
    return OK;
}

LOCAL STATUS uartDetach(VXB_DEV_ID pDev) {
    UART_DEV * pDrv = (UART_DEV *) vxbDevSoftcGet(pDev);
    if (!pDrv) return ERROR;

    vxbIntDisconnect(pDev, pDrv->irq, uartIsr, pDrv);
    vxbMemFree(pDrv);
    return OK;
}

LOCAL VXB_DRV_METHOD uartMethods[] = {
    { VXB_DEVMETHOD_CALL(vxbDevProbe),  uartProbe },
    { VXB_DEVMETHOD_CALL(vxbDevAttach), uartAttach },
    { VXB_DEVMETHOD_CALL(vxbDevDetach), uartDetach },
    VXB_DEVMETHOD_END
};

VXB_DRV uartDriver = {
    { NULL },
    "uartDriver",
    "简单 UART VxBus 驱动程序",
    VXB_BUSID_PLB,
    0,
    sizeof(UART_DEV),
    uartMethods,
    NULL,
    NULL,
    NULL
};

VXB_DRV_DEF(uartDriver);

4. 驱动程序注册
#

将驱动程序添加到 BSP 初始化中:

IMPORT VXB_DRV uartDriver;

void sysHwInit(void) {
    vxbDevRegister(&uartDriver);
}

5. 测试 UART 驱动程序
#

  1. 启动系统并运行:
-> devs

您应该能看到 UART 设备被列出。

  1. 通过写入 TX 寄存器发送数据:
UART_DEV * pDrv = (UART_DEV *) vxbDevSoftcGet(<device>);
vxbWrite8(pDrv->dev, (UINT8 *)(pDrv->base + UART_DR), 'A');
  1. 当字符到达时,ISR 会将其打印到控制台。

VxBus 驱动开发的高级主题
#

设备树叠加(Device Tree Overlays)
#

无需重新构建 BSP,您可以通过应用 DTS 叠加来添加新的硬件支持——这非常适合原型设计。

电源管理
#

现代 VxBus 驱动程序应支持挂起/恢复(suspend/resume)钩子,以应对对功耗敏感的设备。

多实例设备
#

确保您的驱动程序能优雅地处理多个实例(例如,多个 I²C 控制器)。

错误恢复
#

为瞬时故障(例如,总线错误、超时)实现重试逻辑。


VxBus 驱动程序的最佳实践
#

保持驱动程序通用 – 避免硬编码特定于开发板的细节。 ✅ 使用标准 API – 遵循 VxBus 和 VxWorks 内核 API。 ✅ 记录接口 – 帮助未来的开发人员集成您的驱动程序。 ✅ 遵循模块化 – 分离硬件初始化、ISR 和数据处理。 ✅ 基准测试性能 – 在负载下测试延迟和吞吐量。


结论
#

对于 VxWorks 工程师来说,使用 VxBus 开发驱动程序是一项必备技能。通过理解其架构、利用设备树并遵循最佳实践,您可以构建可移植、高效且面向未来的驱动程序。

基本的驱动程序骨架支持 DMA 的高级实现,掌握 VxBus 将为您构建稳定、高性能的嵌入式系统打开大门。

相关文章

VxWorks 编程终极指南
VxWorks RTOS 嵌入式系统 RTP 设备驱动
VxWorks 与 Linux 的 BSP 开发对比分析
VxWorks Linux BSP 嵌入式系统 设备驱动 RTOS
VxWorks BSP 开发:移植自定义 ARM 开发板
VxWorks BSP ARM 开发板 板级支持包 嵌入式系统 VxWorks 7 设备树 MMU 驱动程序开发