linux如何读写pcie设备
linux如何读写pcie设备详细介绍
在 Linux 系统中读写 PCIe 设备通常涉及访问设备的配置空间或内存 / IO 区域,以下是具体步骤和示例:
一、准备工作
- 确认设备信息
通过lspci命令获取设备的厂商 ID、设备 ID 和总线位置:
bashlspci bus:device.function记录下设备的 Vendor ID、Device ID 和 BAR(基地址寄存器) 信息(尤其是内存映射的 BAR)。
- 加载驱动
确保设备未被内核驱动占用(可通过sudo lsof /dev/mem检查),或编写自定义驱动(若需用户空间访问,可使用uio或vfio框架)。
二、用户空间访问(通过
/dev/mem)
1. 打开
/dev/mem 设备
c
fd O_RDWR O_SYNC
fd
2. 映射 PCIe 设备内存空间(以 BAR0 为例)
假设从 lspci 获得 BAR0 的物理地址为 0x10000000,大小为 0x1000(4KB):
c
bar0_phys_addrbar0_size
page_offset bar0_phys_addr
bar0_virt_addr
bar0_size
PROT_READ PROT_WRITE
MAP_SHARED
fd
bar0_phys_addr page_offset
bar0_virt_addr MAP_FAILED
fd
bar0_access_addr bar0_virt_addr page_offset
3. 读写设备寄存器
c
offset
bar0_access_addr offset
offset value
bar0_access_addr offset value
reg_value
4. 释放资源
c
bar0_virt_addr bar0_sizefd
三、内核空间访问(驱动开发)
若需编写内核驱动,核心步骤如下:
- 探测设备
通过pci_register_driver注册驱动,在probe函数中获取 BAR 地址:
cpdev idpdev ENODEV
pdev EBUSY
__iomem bar0 pdev pdev
- 读写操作
使用内核提供的ioread32/iowrite32等函数:
cval bar0 offsetnew_val bar0 offset
四、注意事项
- 权限问题
用户空间访问/dev/mem需要root权限,且需确保设备未被内核驱动占用(可通过echo -n "user" > /sys/bus/pci/devices/<device>/driver/unbind解绑驱动)。 - BAR 类型
- 内存型 BAR:使用
mmap或pci_iomap映射。 - IO 型 BAR:使用
inb/outb等函数(x86 架构专用,现代 PCIe 设备较少使用)。
- 内存型 BAR:使用
- 错误处理
需处理地址无效、权限不足、设备未就绪等异常情况。
五、示例代码(用户空间完整示例)
c
fd O_RDWR O_SYNC
fd
page_offset BAR0_PHYS_ADDR
virt_addr
BAR0_SIZE page_offset
PROT_READ PROT_WRITE
MAP_SHARED
fd
BAR0_PHYS_ADDR page_offset
virt_addr MAP_FAILED
fd
access_addr virt_addr page_offset
reg access_addr
reg
virt_addr BAR0_SIZE page_offset
fd
994142#include <stdio.h>}
通过以上方法,可在 Linux 中实现对 PCIe 设备的读写操作。用户空间访问适合快速调试,内核驱动则适用于生产环境的稳定性和兼容性要求。