简体   繁体   English

使用 python mmap 强制 32 位访问?

[英]forcing 32 bit access using python mmap?

I run 64 bit python on a 64 bits arm processor.我在 64 位 arm 处理器上运行 64 位 python。 One on the AXI bus of this processor is connected to a FPGA (which does bus and clock domain changes down to a 32 bit wide bus).该处理器的 AXI 总线上的一个连接到 FPGA(将总线和时钟域更改为 32 位宽的总线)。 This piece of hardware does not like 64 bit accesses...这块硬件不喜欢 64 位访问...

I am trying to access this FPGA via python mmap like this (within a class):我正在尝试通过这样的 python mmap 访问这个 FPGA(在一个类中):

def __init__(self, base, len):
    self.base = base
    self.fd = open("/dev/mem", "r+")
    self.lw = mmap.mmap(self.fd.fileno(),
                        len,
                        mmap.MAP_SHARED,
                        mmap.PROT_READ | mmap.PROT_WRITE,
                        offset=base)

def get_U32(self, offset):
    s = self.lw[offset:offset+4]
    return struct.unpack("<I", s)[0]

The idea was to that get_U32() would read a 32 bit word from the bus (hence the offset to offset+4 reading).这个想法是让get_U32()从总线读取一个 32 位字(因此偏移量到偏移量+4 读取)。 Sadly, it seems that mmap performs a 64 bit access to the bus anyway (some kind of caching for performance optimization I assume) and then performs the 32 bit "casting".可悲的是,似乎 mmap 无论如何都会对总线执行 64 位访问(我假设是某种用于性能优化的缓存),然后执行 32 位“转换”。 The underlying FPGA is not happy...底层FPGA不开心...

In a C program, I simply write:在 C 程序中,我简单地写:

data = *((uint32_t *) address);

...and the CPU seems to gently perform a 32 bit access on its AXI bus, which the underlying hardware prefers.... (so right now, I have a (slow) workaround, where python requires a C program to interface the Hardware, via pipes) ...并且 CPU 似乎在其 AXI 总线上轻轻地执行 32 位访问,这是底层硬件更喜欢的......(所以现在,我有一个(缓慢的)解决方法,其中 python 需要一个 C 程序来连接硬件,通过管道)

Is there a way to force 64 bits python to perform a 32 bit access, as the previous C line obviously succeeds with?有没有办法强制 64 位 python 执行 32 位访问,因为前面的 C 行显然成功了?

The question is written about reading 32 bits here, but of course, writing 32 bits is needed as well...这里写的问题是关于读取 32 位,但是当然,也需要写入 32 位......

Based on the idea from @martineau, the double probe can be fixed using python ctypes, like:基于@martineau 的想法,可以使用 python ctypes 修复双探针,例如:

s = ctypes.c_uint32.from_buffer(self.lw, offset).value #read

or或者

types.c_uint32.from_buffer(self.lw, offset).value = s #write

This does indeed seem to force python into doing the same 32 bit access as in C, and remove the double read or write probe at the 32 bit bus.这确实似乎迫使 python 进行与 C 中相同的 32 位访问,并删除 32 位总线上的双读或写探测器。

However, sadly, python seems to do a read before each write.然而,遗憾的是,python 似乎在每次写入之前都会进行读取。 So the solution above works perfectly for reading, but when writing, I still get a read access before the write access.所以上面的解决方案非常适合读取,但是在写入时,我仍然在写入访问之前获得了读取访问权限。 In C, I can, of course just get a single write access when writing.在 C 中,我当然可以在编写时获得一次写访问权限。

I am posting this for others who may be interested.我把这个贴给可能感兴趣的其他人。 If you have a solution to this last issue (read before write), please post it.如果您对最后一个问题有解决方案(先读后写),请发布。

Solution on this thread线程上的解决方案

You could try something like this:你可以尝试这样的事情:

 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM