Practical Development of Device Drivers Based on PLX PCIe Controllers in VxWorks 7

Introduction

In industrial control, data acquisition, and communication scenarios, PLX (acquired by Broadcom) PCIe controller chips are widely used. VxWorks 7, as the latest generation of real-time operating systems from Wind River, offers a more modern driver framework – VxBus 2.0. This article will share the complete process of developing PCIe device drivers in the VxWorks 7 environment using PLX series PCIe chips, along with framework code.

Driver Model Overview: VxBus 2.0

VxBus is the driver bus framework of VxWorks, which has been fully upgraded to VxBus 2.0 in VxWorks 7, featuring the following characteristics:

  • • Object-oriented, layered architecture
  • • Supports dynamic device hot-plugging
  • • More user-friendly multi-core (SMP) support
  • • Can be combined with the device tree (FDT) for hardware description

The driver development mainly includes the following structures:

  • • Probe function: matches the device
  • • Attach function: resource mapping, interrupt registration
  • • Detach function (optional): resource release
  • • API implementation: interface for application layer access to the driver

Introduction to PLX PCIe Controllers (Taking PLX 8725 as an Example)

The PCIe switch chips provided by PLX (such as PLX 8725, 8749, etc.) have rich BAR space and interrupt support, with common features including:

  • • Multi-channel BAR register mapping
  • • Supports MSI/MSI-X interrupts
  • • DMA engine
  • • Hot-plugging and reporting mechanisms

In VxWorks, we can identify and initialize these chips through the general configuration space access method of PCIe.

Device Tree Configuration (Optional)

If using the FDT (Flattened Device Tree) method to describe devices, the following node can be added to the BSP’s device tree:

pcie@0x80000000 {
    compatible = "plx,pcie8725";
    reg = <0x80000000 0x1000>; // Register mapping
    interrupts = <32>;         // Interrupt number (GIC or others)
};

In the driver, resources will be obtained through APIs such as <span>vxbFdtDevGet()</span> and <span>vxbResourceAlloc()</span>.

VxBus Driver Framework Code

  1. 1. Header file definition: <span>plxPcieDrv.h</span>
#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. 2. Driver implementation file: <span>plxPcieDrv.c</span>
#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, &amp;vendorId);
    vxbPciConfigRead16(dev, PCI_CFG_DEVICE_ID, &amp;deviceId);

    if (vendorId == PLX_VENDOR_ID &amp;&amp; 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 mapping
    pCtrl->pResBar = vxbResourceAlloc(dev, VXB_RES_MEMORY, 0);
    pCtrl->barBase = (void *)vxbResourceVirtAdrsGet(pCtrl->pResBar);

    // Interrupt resource
    pCtrl->pResIrq = vxbResourceAlloc(dev, VXB_RES_IRQ, 0);
    pCtrl->irq = (int)(long)vxbResourceAdrsGet(dev, VXB_RES_IRQ, 0);

    vxbDevSoftcSet(dev, pCtrl);

    // Register interrupt
    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;

    // Read interrupt status register and clear
    UINT32 status = *(volatile UINT32 *)(pCtrl->barBase + 0x04);
    *(volatile UINT32 *)(pCtrl->barBase + 0x04) = status;

    // Custom processing logic...
}

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)

Debugging Tips

  • • View PCI configuration space:
-> vxbPciShow()
  • • View device registration information:
-> vxbDevShow()
  • • Print BAR and interrupt information:
printf("BAR0 base: 0x%x, IRQ: %d\n", pCtrl->barBase, pCtrl->irq);
  • <span>WindView</span> tracks interrupt response times for optimization of <span>ISR</span> execution.

Suggestions for Expandable Features

  • • Support PLX DMA engine transfers (using vxbDma* series interfaces)
  • • Support user-space access interfaces (via ioctl or shared memory)
  • • Support multi-channel, multi-BAR mapped device structures

Conclusion

The combination of VxWorks 7 and modern PCIe device driver development makes real-time and high-performance communication possible. By leveraging the VxBus framework and device tree, modular drivers can be implemented quickly and efficiently, especially for complex PCIe controllers like PLX. I hope the practical code and ideas presented in this article can provide reference and inspiration for your projects.

Click “Read the original text” to access more free resources for VxWorks!

Leave a Comment