前言 #
在工业控制、数据采集、通信等场景中,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 驱动框架代码 #
- 头文件定义:
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
- 驱动实现文件:
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 控制器。希望本文的实战代码与思路,能为你的项目提供参考和启发。