用pcimem读写x64平台下的PCIE外设寄存器

背景

在之前的一篇文章用devmem2读写设备IO内存中,我介绍了devmem2这个通过读写/dev/mem文件实现从用户空间访问外设寄存器的工具,但是对于PCIE设备,特别是FPGA模拟出来的自定义PCIE设备,该工具在x64平台下可能会发出64位的内存读写请求,而FPGA模拟的外设寄存器一般都映射到32位地址空间,此时CPU就会因FPGA工作不正常而卡死。
此时驱动必须用ioread32接口来读写外设寄存器,而该接口无法被用户程序调用,不利于调试,最好有一种既能从用户空间访问,又能避免PCIE发出64位地址访问请求的方法。

sysfs和PCI的resource属性

现在较新的内核(4.15+)都支持sysfs,且每个PCIE设备都对应一个目录

/sys/bus/pci/[domain]:[bus]:[device].[function]/

该目录下有这些属性文件(有删减):

tree /sys/bus/pci/devices/0000\:01\:00.0/
/sys/bus/pci/devices/0000:01:00.0/
├── class
├── config
├── device
├── dma_mask_bits
├── driver -> ../../../../bus/pci/drivers/f260_mainfpga
├── enable
├── reset
├── resource
├── resource0   //对应BAR0寄存器空间
├── resource1   //对应BAR1寄存器空间
├── uevent
└── vendor

只要将resource0这样的属性文件/dev/mem文件一样mmap到用户进程的虚拟地址空间,就可以像devmem2工具那样通过解引用的方式访问寄存器,而不用ioread32/iowrite32等内核函数。

pcie寄存器查看工具:pcimem

有人已经提供了现成的工具pcimem,不过github时常抽风,我转载到了我的gitee以供下载

用法

该工具用法跟devmem2很像(因为代码是基于devmem2修改的)

Usage:  ./pcimem { sysfile } { offset } [ type*count [ data ] ]
        sys file: sysfs file for the pci resource to act on
        offset  : offset into pci memory region to act upon
        type    : access operation type : [b]yte, [h]alfword, [w]ord, [d]ouble-word
        *count  : number of items to read:  w*100 will dump 100 words
        data    : data to be written

用法举例

sudo ./pcimem /sys/bus/pci/devices/0001\:00\:07.0/resource0   0x100    w          0x00
                                                  BAR0      寄存器偏移 访问粒度word  写入0x00(读的话不填该参数)

总结

个人猜测是resource属性文件的驱动代码实现了普通内存地址到io内存地址的转换。

你可能感兴趣的:(驱动开发,linux软件)