RT-Thread 对 PCIe 的支持情况
一、PCIe 支持现状
1. 整体评估
支持程度:★★☆☆☆ (有限支持)
c
// 当前状态总结
- 基础框架: 有基本 PCIe 框架
- 驱动生态: 相对薄弱
- 应用场景: 主要在高性能应用
- 成熟度: 处于发展阶段
// 适用平台
✓ 64位 ARM (Cortex-A72/A53/A55)
✓ RISC-V 64位 (K210, D1)
✓ x86_64 (实验性支持)
✗ 32位 MCU (基本不支持)
二、PCIe 框架架构
1. PCIe 核心框架
c
// PCIe 主机控制器驱动框架
struct rt_pcie_host_controller
{
struct rt_device parent;
// 控制器信息
rt_uint32_t version; // PCIe 版本
rt_uint32_t max_speed; // 最大速度
rt_uint32_t max_width; // 最大宽度
rt_bool_t msi_support; // MSI 支持
rt_bool_t msi_x_support; // MSI-X 支持
// 操作接口
rt_err_t (*scan_bus)(struct rt_pcie_host_controller *host);
rt_err_t (*config_read)(struct rt_pcie_host_controller *host,
rt_uint8_t bus, rt_uint8_t dev,
rt_uint8_t func, rt_uint16_t offset,
rt_uint32_t *value, rt_uint8_t size);
rt_err_t (*config_write)(struct rt_pcie_host_controller *host,
rt_uint8_t bus, rt_uint8_t dev,
rt_uint8_t func, rt_uint16_t offset,
rt_uint32_t value, rt_uint8_t size);
// 中断处理
rt_err_t (*setup_msi)(struct rt_pcie_host_controller *host,
rt_uint8_t bus, rt_uint8_t dev,
rt_uint8_t func, rt_uint16_t vector);
// 私有数据
void *private_data;
};
2. PCIe 设备驱动模型
c
// PCIe 设备结构
struct rt_pcie_device
{
struct rt_device parent;
// PCIe 设备信息
rt_uint16_t vendor_id;
rt_uint16_t device_id;
rt_uint8_t class_code[3];
rt_uint8_t revision_id;
// PCIe 配置空间
struct {
rt_uint32_t bars[6]; // Base Address Registers
rt_uint32_t rom_bar; // Expansion ROM BAR
rt_uint16_t subsystem_vendor;
rt_uint16_t subsystem_id;
rt_uint32_t capabilities; // PCIe Capabilities
} config;
// PCIe 特性
rt_uint8_t current_speed; // 当前速度
rt_uint8_t current_width; // 当前宽度
rt_uint16_t max_payload; // 最大载荷
rt_bool_t sr_iov_support; // SR-IOV 支持
// 资源管理
struct rt_pcie_resource {
rt_uintptr_t start;
rt_uintptr_t end;
rt_size_t size;
rt_bool_t prefetchable;
} resources[PCI_MAX_RESOURCES];
// 驱动私有数据
void *driver_data;
};
三、支持的平台与芯片
1. ARM 平台支持
c
// Allwinner (全志) 系列
- D1 (RISC-V): ★★★☆☆
✓ PCIe 2.0 x1
✓ 支持 NVMe/SATA 控制器
✗ 驱动仍在完善
- H6/H616: ★★☆☆☆
✓ PCIe 2.0 x1
✗ 驱动支持有限
// Rockchip (瑞芯微) 系列
- RK3568: ★★★☆☆
✓ PCIe 3.0 x2
✓ 支持多种设备
✗ 需要定制驱动
- RK3588: ★★★★☆
✓ PCIe 3.0 x4
✓ 支持 SR-IOV
✓ 社区有初步支持
// NXP i.MX 系列
- i.MX8M Plus: ★★☆☆☆
✓ PCIe 2.0 x1
✗ 官方支持有限
2. RISC-V 平台支持
c
// 平头哥 (T-Head) 系列
- C906/C910: ★★☆☆☆
✓ PCIe 控制器
✗ 驱动不完善
// SiFive 系列
- FU740: ★★☆☆☆
✓ PCIe 3.0 x8
✗ 需要移植工作
3. x86 平台支持
c
// x86_64 架构
- 通用 x86 PC: ★★☆☆☆
✓ 基础 PCIe 扫描
✓ 可访问配置空间
✗ 高级功能支持有限
✗ 中断处理不完善
四、支持的 PCIe 设备类型
1. 存储设备
c
// NVMe SSD
- 支持程度: ★★☆☆☆
- 可用驱动: 基础 NVMe 驱动
- 限制:
✗ 仅支持基本读写
✗ 不支持高级 NVMe 特性
✗ 性能优化有限
// SATA 控制器
- 支持程度: ★★☆☆☆
- 示例: ASMedia ASM1061
- 限制:
✗ 需要额外 SATA 驱动
✗ AHCI 支持不完整
// SD/MMC 控制器
- 支持程度: ★☆☆☆☆
- 示例: Realtek RTS5227
2. 网络设备
c
// 以太网卡
- Realtek RTL8111/RTL8168: ★★☆☆☆
✓ 基础驱动可用
✗ 高级功能有限
- Intel 82574L/82599: ★☆☆☆☆
✗ 驱动不完整
// Wi-Fi 卡
- 支持程度: ★☆☆☆☆
- 限制:
✗ 需要复杂的固件加载
✗ 协议栈集成困难
3. GPU/显示设备
c
// 简单显示适配器
- 支持程度: ★☆☆☆☆
- 示例: SimpleFB 帧缓冲
- 限制:
✗ 无 3D 加速
✗ 无硬件加速
// 计算加速卡
- 支持程度: ★☆☆☆☆
- 限制:
✗ 需要专用驱动
✗ 生态不成熟
五、PCIe 驱动开发框架
1. 驱动注册与发现
c
// PCIe 驱动结构
struct rt_pcie_driver
{
struct rt_driver parent;
// 设备匹配表
const struct rt_pcie_device_id *id_table;
// 驱动操作
rt_err_t (*probe)(struct rt_pcie_device *dev);
rt_err_t (*remove)(struct rt_pcie_device *dev);
rt_err_t (*suspend)(struct rt_pcie_device *dev);
rt_err_t (*resume)(struct rt_pcie_device *dev);
// 电源管理
rt_err_t (*runtime_suspend)(struct rt_pcie_device *dev);
rt_err_t (*runtime_resume)(struct rt_pcie_device *dev);
};
// 驱动注册示例
static const struct rt_pcie_device_id nvme_ids[] = {
{ RT_PCI_DEVICE(0x144d, 0xa808) }, // Samsung NVMe
{ RT_PCI_DEVICE(0x1cc1, 0x8201) }, // ADATA NVMe
{ RT_PCI_DEVICE_END }
};
static struct rt_pcie_driver nvme_driver = {
.parent.name = "nvme",
.id_table = nvme_ids,
.probe = nvme_probe,
.remove = nvme_remove,
};
RT_PCIE_DRIVER_REGISTER(nvme_driver);
2. 资源配置与管理
c
// BAR 资源分配
static rt_err_t pcie_device_setup_bars(struct rt_pcie_device *dev)
{
rt_uint32_t bar_value;
rt_size_t bar_size;
for (int i = 0; i < PCI_MAX_BARS; i++) {
// 读取 BAR 寄存器
pcie_config_read(dev, PCI_BASE_ADDRESS_0 + i * 4,
&bar_value, 4);
if (bar_value == 0) continue;
// 确定 BAR 类型
if (bar_value & PCI_BASE_ADDRESS_SPACE_IO) {
// I/O 空间 BAR
dev->resources[i].flags = IORESOURCE_IO;
} else {
// 内存空间 BAR
dev->resources[i].flags = IORESOURCE_MEM;
if (bar_value & PCI_BASE_ADDRESS_MEM_PREFETCH) {
dev->resources[i].flags |= IORESOURCE_PREFETCH;
}
}
// 探测 BAR 大小
pcie_config_write(dev, PCI_BASE_ADDRESS_0 + i * 4,
0xFFFFFFFF, 4);
pcie_config_read(dev, PCI_BASE_ADDRESS_0 + i * 4,
&bar_size, 4);
pcie_config_write(dev, PCI_BASE_ADDRESS_0 + i * 4,
bar_value, 4);
bar_size = ~(bar_size & ~0xF) + 1;
dev->resources[i].size = bar_size;
}
return RT_EOK;
}
3. 中断处理
c
// MSI/MSI-X 中断设置
static rt_err_t pcie_setup_msi(struct rt_pcie_device *dev,
rt_uint16_t vector)
{
rt_uint32_t msi_cap;
rt_uint16_t msi_control;
// 查找 MSI Capability
if (pcie_find_capability(dev, PCI_CAP_ID_MSI, &msi_cap) != RT_EOK) {
return -RT_ENOSYS;
}
// 读取 MSI Control 寄存器
pcie_config_read(dev, msi_cap + PCI_MSI_FLAGS,
&msi_control, 2);
// 设置 MSI 地址和数据
rt_uint64_t msi_address = get_msi_address(dev);
rt_uint16_t msi_data = vector;
if (msi_control & PCI_MSI_FLAGS_64BIT) {
// 64位地址
pcie_config_write(dev, msi_cap + PCI_MSI_ADDRESS_LOW,
msi_address & 0xFFFFFFFF, 4);
pcie_config_write(dev, msi_cap + PCI_MSI_ADDRESS_HIGH,
msi_address >> 32, 4);
} else {
// 32位地址
pcie_config_write(dev, msi_cap + PCI_MSI_ADDRESS_LOW,
msi_address & 0xFFFFFFFF, 4);
}
pcie_config_write(dev, msi_cap + PCI_MSI_DATA_32,
msi_data, 2);
// 启用 MSI
msi_control |= PCI_MSI_FLAGS_ENABLE;
pcie_config_write(dev, msi_cap + PCI_MSI_FLAGS,
msi_control, 2);
return RT_EOK;
}
六、实际应用案例
1. NVMe SSD 驱动示例
c
// 简化的 NVMe 驱动实现
struct nvme_device {
struct rt_pcie_device *pcie_dev;
rt_uintptr_t reg_base;
rt_size_t reg_size;
// 队列
struct nvme_queue {
rt_uint32_t *sq_doorbell;
rt_uint32_t *cq_doorbell;
void *sq_base;
void *cq_base;
rt_uint16_t sq_head;
rt_uint16_t cq_tail;
} admin_q, io_q;
// 命名空间
struct nvme_namespace {
rt_uint64_t size;
rt_uint32_t block_size;
rt_uint32_t max_transfer;
} ns;
// 同步
struct rt_mutex lock;
struct rt_completion completion;
};
static rt_err_t nvme_probe(struct rt_pcie_device *pdev)
{
struct nvme_device *nvme;
rt_err_t ret;
// 1. 分配设备结构
nvme = rt_malloc(sizeof(struct nvme_device));
if (!nvme) return -RT_ENOMEM;
rt_memset(nvme, 0, sizeof(struct nvme_device));
nvme->pcie_dev = pdev;
pdev->driver_data = nvme;
// 2. 映射寄存器空间
nvme->reg_base = (rt_uintptr_t)pdev->resources[0].start;
nvme->reg_size = pdev->resources[0].size;
// 3. 初始化 NVMe 控制器
ret = nvme_init_ctrl(nvme);
if (ret != RT_EOK) {
rt_free(nvme);
return ret;
}
// 4. 创建设备
nvme->parent.type = RT_Device_Class_Block;
nvme->parent.ops = &nvme_ops;
ret = rt_device_register(&nvme->parent, "nvme0",
RT_DEVICE_FLAG_RDWR);
if (ret != RT_EOK) {
nvme_remove(pdev);
return ret;
}
rt_kprintf("NVMe device registered: %s\n", pdev->parent.name);
return RT_EOK;
}
2. 以太网卡驱动示例
c
// Realtek RTL8111 驱动框架
struct rtl8111_device {
struct rt_pcie_device *pcie_dev;
struct rt_eth_device eth_dev;
// 寄存器
rt_uintptr_t mmio_base;
// 描述符环
struct rtl8111_tx_desc *tx_ring;
struct rtl8111_rx_desc *rx_ring;
rt_uint8_t *tx_buffers;
rt_uint8_t *rx_buffers;
// 统计
rt_uint32_t tx_packets;
rt_uint32_t rx_packets;
// 同步
struct rt_mutex lock;
};
static rt_err_t rtl8111_transmit(struct rt_eth_device *eth_dev,
struct pbuf *p)
{
struct rtl8111_device *rtl = eth_dev->user_data;
rt_uint32_t tx_idx;
rt_mutex_take(&rtl->lock, RT_WAITING_FOREVER);
// 获取空闲 TX 描述符
tx_idx = rtl->tx_ring_tail % TX_RING_SIZE;
// 填充描述符
rtl->tx_ring[tx_idx].addr = (rt_uint64_t)rtl->tx_buffers[tx_idx];
rtl->tx_ring[tx_idx].flags = TX_DESC_FLAG_OWN |
TX_DESC_FLAG_FS |
TX_DESC_FLAG_LS;
rtl->tx_ring[tx_idx].len = p->tot_len;
// 复制数据
pbuf_copy_partial(p, (void*)rtl->tx_ring[tx_idx].addr,
p->tot_len, 0);
// 更新尾指针
rtl->tx_ring_tail++;
write_reg(rtl, TX_TAIL_REG, rtl->tx_ring_tail);
rt_mutex_release(&rtl->lock);
rtl->tx_packets++;
return RT_EOK;
}
七、限制与挑战
1. 技术限制
c
// 1. 中断处理复杂
- 传统 INTx 中断: 支持有限
- MSI/MSI-X: 部分支持
- 中断亲和性: 不支持
// 2. DMA 支持
- 简单 DMA: 支持
- IOMMU/SMMU: 不支持
- 64位 DMA: 部分支持
// 3. 电源管理
- D0-D3 状态: 基本支持
- ASPM: 不支持
- Runtime PM: 不支持
// 4. 高级特性
- SR-IOV: 不支持
- ATS: 不支持
- PASID: 不支持
2. 生态限制
c
// 1. 驱动数量有限
- 官方维护驱动少
- 社区贡献驱动稀缺
- 缺少商业驱动支持
// 2. 测试覆盖不足
- 硬件平台有限
- 测试用例不完整
- 稳定性验证不足
// 3. 文档缺乏
- API 文档不完整
- 移植指南缺失
- 调试工具有限
八、开发建议
1. 平台选择建议
c
// 推荐平台 (支持较好)
1. Allwinner D1 (RISC-V)
- 开源社区活跃
- 有基础 PCIe 驱动
- 适合学习开发
2