Python:在一次操作中向内存写入[英] Python: writing to memory in a single operation

本文是小编为大家收集整理的关于Python:在一次操作中向内存写入的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在编写一个用户空间驱动程序,用于在 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)

不幸的是,出现 struct.pack_into 执行 memset(buf, 0, ...) 在写入实际值之前清除寄存器.通过检查 FPGA 中的写操作,我可以看到寄存器在设置真值之前设置为 0x00000000,因此 PCI 总线上至少有两次写入(实际上对于 32 位访问,有 3 个,两个 0写入,然后是实际数据.64 位涉及六次写入).这会导致一些对写入操作计数的寄存器产生副作用,或者对一些"写入时清除"或在写入时触发某些事件的寄存器产生副作用.

我想使用另一种方法将寄存器数据一次性写入内存映射寄存器空间.我研究了 ctypes.memmove ,它看起来很有希望(还没有工作),但我想知道是否还有其他方法可以做到这一点.

请注意,使用 struct.unpack_from 的寄存器 read 可以完美运行.

请注意,我还通过使用记录所有访问的 QEMU 驱动程序消除了 FPGA - 在写入数据之前,我看到了相同的双零写入访问.

推荐答案

也许这会根据需要工作?

mv[address:address+4] = struct.pack("<I", data)

更新:

从评论中可以看出,上面的代码并没有解决问题.但是,它的以下变体可以:

mv_as_int = mv.cast('I')
mv_as_int[address/4] = data

不幸的是,精确理解幕后发生的事情以及 memoryview 究竟为何如此行为超出了现代技术的能力范围,因此将继续为未来的研究人员解决问题.

本文地址:https://www.itbaoku.cn/post/2090952.html

问题描述

I'm writing a userspace driver for accessing FPGA registers in Python 3.5 that mmaps the FPGA's PCI address space, obtains a memoryview to provide direct access to the memory-mapped register space, and then uses struct.pack_into("<I", ...) to write a 32-bit value into the selected 32-bit aligned address.

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)

Unfortunately, it appears that struct.pack_into does a memset(buf, 0, ...) that clears the register before the actual value is written. By examining write operations within the FPGA, I can see that the register is set to 0x00000000 before the true value is set, so there are at least two writes across the PCI bus (in fact for 32-bit access there are three, two zero writes, then the actual data. 64-bit involves six writes). This causes side-effects with some registers that count the number of write operations, or some that "clear on write" or trigger some event when written.

I'd like to use an alternative method to write the register data in a single write to the memory-mapped register space. I've looked into ctypes.memmove and it looks promising (not yet working), but I'm wondering if there are other ways to do this.

Note that a register read using struct.unpack_from works perfectly.

Note that I've also eliminated the FPGA from this by using a QEMU driver that logs all accesses - I see the same double zero-write access before data is written.

推荐答案

Perhaps this would work as needed?

mv[address:address+4] = struct.pack("<I", data)

Update:

As seen from the comments, the code above does not solve the problem. The following variation of it does, however:

mv_as_int = mv.cast('I')
mv_as_int[address/4] = data

Unfortunately, precise understanding of what happens under the hood and why exactly memoryview behaves this way is beyond the capabilities of modern technology and will thus stay open for the researchers of the future to tackle.