跳过正文

VxWorks 7 下基于 PLX PCIe 控制器的设备驱动开发实战

VxWorks 7 PCIe Device Driver
目录

前言
#

在工业控制、数据采集、通信等场景中,PLX(Broadcom 收购)出品的 PCIe 控制器芯片被广泛应用。而 VxWorks 7,作为 Wind River 最新一代实时操作系统,提供了更现代化的驱动框架 —— VxBus 2.0。本文将结合 PLX 系列 PCIe 芯片,分享在 VxWorks 7 环境下开发 PCIe 设备驱动的完整流程,并给出框架代码。

驱动模型概览:VxBus 2.0
#

VxBus 是 VxWorks 的驱动总线框架,VxWorks 7 中已全面升级为 VxBus 2.0,具有以下特点:

  • 面向对象、分层架构
  • 支持动态设备插拔
  • 更友好的多核(SMP)支持
  • 可结合设备树(FDT)进行硬件描述

驱动开发主要包括以下结构:

  • Probe 函数:匹配设备
  • Attach 函数:资源映射、中断注册
  • Detach 函数(可选):资源释放
  • API 实现:应用层访问驱动的接口

PLX PCIe 控制器介绍(以 PLX 8725 为例)
#

PLX 提供的 PCIe 交换芯片(如 PLX 8725、8749 等)拥有丰富的 BAR 空间和中断支持,常见特性包括:

  • 多通道 BAR 寄存器映射
  • 支持 MSI/MSI-X 中断
  • DMA 引擎
  • 热插拔和上报机制

在 VxWorks 中,我们可通过 PCIe 的通用配置空间访问方式来识别、初始化这些芯片。

设备树配置(可选)
#

如果使用 FDT(Flattened Device Tree)方式描述设备,可在 BSP 的设备树中添加如下节点:

pcie@0x80000000 {
    compatible = "plx,pcie8725";
    reg = <0x80000000 0x1000>; // 寄存器映射
    interrupts = <32>;         // 中断号(GIC 或其他)
};

驱动中将通过 vxbFdtDevGet()vxbResourceAlloc() 等 API 获取这些资源。

VxBus 驱动框架代码
#

  1. 头文件定义: plxPcieDrv.h
#ifndef __PLX_PCIE_DRV_H__
#define __PLX_PCIE_DRV_H__

#define PLX_VENDOR_ID   0x10B5
#define PLX_DEVICE_ID   0x8725

typedef struct {
    VXB_DEV_ID dev;
    void * barBase;
    int irq;
    VXB_RESOURCE * pResBar;
    VXB_RESOURCE * pResIrq;
} PLX_PCIE_DRV_CTRL;

#endif
  1. 驱动实现文件: plxPcieDrv.c
#include <vxWorks.h>
#include <subsys/pci/vxbPciLib.h>
#include <subsys/int/vxbIntLib.h>
#include <subsys/dma/vxbDmaLib.h>
#include "plxPcieDrv.h"

LOCAL STATUS plxPcieProbe(VXB_DEV_ID dev) {
    UINT16 vendorId, deviceId;
    vxbPciConfigRead16(dev, PCI_CFG_VENDOR_ID, &vendorId);
    vxbPciConfigRead16(dev, PCI_CFG_DEVICE_ID, &deviceId);

    if (vendorId == PLX_VENDOR_ID && deviceId == PLX_DEVICE_ID)
        return OK;

    return ERROR;
}

LOCAL STATUS plxPcieAttach(VXB_DEV_ID dev) {
    PLX_PCIE_DRV_CTRL *pCtrl = vxbMemAlloc(sizeof(*pCtrl));
    if (!pCtrl) return ERROR;

    pCtrl->dev = dev;

    // BAR0 映射
    pCtrl->pResBar = vxbResourceAlloc(dev, VXB_RES_MEMORY, 0);
    pCtrl->barBase = (void *)vxbResourceVirtAdrsGet(pCtrl->pResBar);

    // 中断资源
    pCtrl->pResIrq = vxbResourceAlloc(dev, VXB_RES_IRQ, 0);
    pCtrl->irq = (int)(long)vxbResourceAdrsGet(dev, VXB_RES_IRQ, 0);

    vxbDevSoftcSet(dev, pCtrl);

    // 注册中断
    vxbIntConnect(dev, pCtrl->pResIrq, plxPcieIsr, pCtrl);
    vxbIntEnable(dev, pCtrl->pResIrq);

    return OK;
}

LOCAL void plxPcieIsr(void *param) {
    PLX_PCIE_DRV_CTRL *pCtrl = (PLX_PCIE_DRV_CTRL *)param;

    // 读取中断状态寄存器并清除
    UINT32 status = *(volatile UINT32 *)(pCtrl->barBase + 0x04);
    *(volatile UINT32 *)(pCtrl->barBase + 0x04) = status;

    // 自定义处理逻辑...
}

LOCAL VXB_DRV plxPcieDrv = {
    {NULL},
    "plxPcie", "PLX PCIe Driver",
    VXB_BUSID_PCI, 0, 0,
    plxPcieProbe, plxPcieAttach, NULL
};

VXB_DRV_DEF(plxPcieDrv)
VXB_DRV_MOD_INSTALL(plxPcieDrv)

调试技巧
#

  • 查看 PCI 配置空间:
-> vxbPciShow()
  • 查看设备注册信息:
-> vxbDevShow()
  • 打印 BAR 和中断信息:
printf("BAR0 base: 0x%x, IRQ: %d\n", pCtrl->barBase, pCtrl->irq);
  • WindView 跟踪中断响应时间,便于优化 ISR 执行。

可扩展功能建议
#

  • 支持 PLX DMA 引擎传输(使用 vxbDma* 系列接口)
  • 支持用户空间访问接口(通过 ioctl 或共享内存)
  • 支持多通道、多 BAR 映射设备结构

结语
#

VxWorks 7 与现代 PCIe 设备驱动开发的结合使得实时性与高性能通信成为可能。通过 VxBus 框架与设备树的配合,可以快速、高效地实现模块化驱动,尤其适用于像 PLX 这样的复杂 PCIe 控制器。希望本文的实战代码与思路,能为你的项目提供参考和启发。

相关文章

VxWorks 7系统下的TCP网络编程
VxWorks 7 Socket TCP
VxWorks 7 BSP开发详解
VxWorks 7 BSP
VxWorks 7信号量简介
VxWorks 7