Python: запись в память за одну операцию - PullRequest
0 голосов
/ 27 ноября 2018

Я пишу драйвер пользовательского пространства для доступа к регистрам FPGA в Python 3.5, который mmap определяет адресное пространство PCI FPGA, получает 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-битного доступа есть три, два нуляпишет, а затем фактические данные. 64-битные включает в себя шесть записей).Это вызывает побочные эффекты для некоторых регистров, которые подсчитывают количество операций записи, или для некоторых, которые «очищают при записи» или инициируют какое-либо событие при записи.

Я хотел бы использовать альтернативный метод для записи регистраданные за одну запись в отображаемое в память регистровое пространство.Я посмотрел на ctypes.memmove, и это выглядит многообещающе (пока не работает), но мне интересно, есть ли другие способы сделать это.

Обратите внимание, что регистр читает , используяstruct.unpack_from отлично работает.

Обратите внимание, что я также исключил FPGA из этого с помощью драйвера QEMU, который регистрирует все обращения - я вижу такой же двойной доступ с нулевой записью до записи данных.

1 Ответ

0 голосов
/ 27 ноября 2018

Возможно, это будет работать при необходимости?

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

Обновление :

Как видно из комментариев, приведенный выше код не решает проблему.Однако есть следующие варианты:

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

К сожалению, точное понимание того, что происходит под капотом и почему именно так выглядит память, выходит за пределы возможностей современных технологий и, таким образом, останется открытым для исследователей.будущего для решения.

...