简体   繁体   English

如何使用Python写入硬件中的寄存器?

[英]How do I write to registers in hardware using Python?

I have a C function which can read/write perfectly into the hardware register by opening the device descriptor (nf10). 我有一个C函数,可以通过打开设备描述符(nf10)完美地将其读/写到硬件寄存器中。 I am trying to do the same using Python. 我正在尝试使用Python进行同样的操作。 I am able to read the registers, but I am not able to write registers. 我能够读取寄存器,但无法写入寄存器。 Why am I unable to write? 为什么我不能写? Is there a better way to do read/write for registers in hardware? 有没有更好的方法可以对硬件中的寄存器进行读/写?

Relevant Python code: 相关的Python代码:

#! /usr/bin/env python
import os
from fcntl import *
from struct import *

SIOCDEVPRIVATE = 35312
NF10_IOCTL_CMD_READ_STAT = SIOCDEVPRIVATE + 0
NF10_IOCTL_CMD_WRITE_REG = SIOCDEVPRIVATE + 1
NF10_IOCTL_CMD_READ_REG = SIOCDEVPRIVATE + 2

def rdaxi(addr):

    f = open("/dev/nf10", "r+")
    arg = pack("q", int(addr, 16))
    value = ioctl(f, NF10_IOCTL_CMD_READ_REG, arg)
    value = unpack("q", value)
    value = value[0]
    value = hex(value & int("0xffffffff", 16))
    f.close()
    return value

def wraxi(addr, value):

    f = open("/dev/nf10", "r+")
    arg = (int(addr, 16) << 32) + int(value, 16)
    arg = pack("q", arg)
    ioctl(f, NF10_IOCTL_CMD_WRITE_REG, arg)
    f.close()

relevant C code 相关的C代码

#include <fcntl.h>
#include <sys/ioctl.h> 
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define NF10_IOCTL_CMD_READ_STAT (SIOCDEVPRIVATE+0)
#define NF10_IOCTL_CMD_WRITE_REG (SIOCDEVPRIVATE+1)
#define NF10_IOCTL_CMD_READ_REG (SIOCDEVPRIVATE+2)

int main(int argc, char* argv[]){
   int f;
   uint64_t v;
   uint64_t addr;
   uint64_t val;

   if(argc < 3){
       printf("usage: rdaxi reg_addr(in hex) reg_val(in_hex)\n\n");
       return 0;
   }
   else{
    sscanf(argv[1], "%llx", &addr);
    sscanf(argv[2], "%llx", &val);
  }

//----------------------------------------------------
//-- open nf10 file descriptor for all the fun stuff
//----------------------------------------------------
f = open("/dev/nf10", O_RDWR);
if(f < 0){
    perror("/dev/nf10");
    return 0;
}

printf("\n");

// High 32 bits are the AXI address,
// low 32 bits are the value written to that address
v = (addr << 32) + val;
if(ioctl(f, NF10_IOCTL_CMD_WRITE_REG, v) < 0){
    perror("nf10 ioctl failed");
    return 0;
}
printf("\n");

close(f);

return 0;

} }

I think it's best to implement lower-level operations on registers in C, and compile C to .so. 我认为最好在C中的寄存器上实现低级操作,并将C编译为.so。 Then load the .so in python. 然后在python中加载.so。

I suspect "endianness" may be your issue. 我怀疑“字节顺序”可能是您的问题。 It's hard to tell without knowing the hardware you're writing to, though. 但是,在不知道要写入的硬件的情况下很难分辨。 I noticed you've left off the byte order specifier from your pack function call. 我注意到您从包函数调用中删除了字节顺序说明符。 Most hardware registers are big-endian, meaning they expect bit 0 at the lowest memory address and the most significant bit at the highest address. 大多数硬件寄存器都是高位优先的,这意味着它们期望最低的内存地址为位0,最高的地址为最高有效位。

Without the byte order specifier, Python will pack with your native endianness, which is little-endian on an Intel system. 没有字节顺序说明符,Python将打包您的本地字节序,在英特尔系统上为little-endian。 Try packing it with the big-endian specifier so that everything stays in the same order as it started: 尝试使用big-endian说明符将其打包,以使一切保持与开始时相同的顺序:

arg = pack(">q", arg)

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

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