我正在编写一个用于访问Python 3.5中的FPGA寄存器的用户空间驱动程序,该mmap
用于FPGA的PCI地址空间,获得memoryview
以提供对内存映射寄存器空间的直接访问,以及然后使用struct.pack_into("<I", ...)
将32位值写入所选的32位对齐地址。
def write_u32(address, data):
assert address % 4 == 0, "Address must be 32-bit aligned"
path = path.lib.Path("/dev/uio0")
file_size = path.stat().st_size
with path.open(mode='w+b') as f:
mv = memoryview(mmap.mmap(f.fileno(), file_size))
struct.pack_into("<I", mv, address, data)
不幸的是,appears struct.pack_into
所做的memset(buf, 0, ...)
会在写入实际值之前清除寄存器。通过检查FPGA内的写操作,我可以看到在设置真值之前将寄存器设置为0x00000000,因此PCI总线上至少有两次写操作(实际上,对于32位访问,有三个,两个为零)写入,然后是实际数据(64位涉及六次写入)。这会产生一些副作用,有些寄存器会计算写操作的次数,有些寄存器会在写操作时“清除写入”或触发某些事件。
我想使用另一种方法将寄存器数据一次写入存储器映射的寄存器空间。我研究了ctypes.memmove
,它看起来很有前途(尚未奏效),但我想知道是否还有其他方法可以做到这一点。
请注意,使用struct.unpack_from
进行寄存器 read 的工作非常正常。
请注意,我还通过使用记录所有访问的QEMU驱动程序从中删除了FPGA-在写入数据之前,我看到了相同的双零写入访问。
答案 0 :(得分:1)
也许这可以根据需要工作吗?
mv[address:address+4] = struct.pack("<I", data)
更新:
从注释中可以看出,上面的代码不能解决问题。但是,它有以下变化形式:
mv_as_int = mv.cast('I')
mv_as_int[address/4] = data
不幸的是,对引擎盖下发生的事情以及为什么精确的记忆视图如此行为的精确了解已经超出了现代技术的能力,因此将为将来的研究人员开放。
答案 1 :(得分:0)
你可以尝试这样的事情:
def __init__(self,offset,size=0x10000):
self.offset = offset
self.size = size
mmap_file = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
mem = mmap.mmap(mmap_file, self.size,
mmap.MAP_SHARED,
mmap.PROT_READ | mmap.PROT_WRITE,
offset=self.offset)
os.close(mmap_file)
self.array = np.frombuffer(mem, np.uint32, self.size >> 2)
def wread(self,address):
idx = address >> 2
return_val = int(self.array[idx])
return return_val
def wwrite(self,address,data):
idx = address >> 2
self.array[idx] = np.uint32(data)