ioctl“无法发送 spi 消息:无效参数”Beaglebone Black

Posted

技术标签:

【中文标题】ioctl“无法发送 spi 消息:无效参数”Beaglebone Black【英文标题】:Ioctl "can't send spi message: Invalid argument" Beaglebone Black 【发布时间】:2019-06-03 19:11:56 【问题描述】:

我正在尝试从我的 spidev1.0(总线 1 设备 0)上的 beaglebone black 发送 16 位消息到 IC 芯片 TLV5618AC

在移位寄存器开始在时钟下降沿拾取位之前,片选线需要从高电平变为低电平。

我执行了 spidev_test.c 的修改版本(原始版本运行良好)。由于我需要芯片选择线在消息之间从高到低 - ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 行将不起作用,因为它将数据作为单个消息传输。即使我将 ioctl() 放在 for 循环中,它也不起作用,因为它是第一条也是最后一条消息。

以下代码有效

static void transfer(int fd)

    int ret;
  unsigned short buffer[1];
  int zero = 0;

    FILE *iFile = fopen("firsttest.bin", "r");
  if (iFile == NULL)
    
        printf("Cannot open file \n");
        exit(0);
    

  struct spi_ioc_transfer tr = 
      .tx_buf = (unsigned long)zero,
      .rx_buf = (unsigned long)zero,
      .len = 2,
      .delay_usecs = delay,
      .speed_hz = speed,
      .bits_per_word = bits,
    ;


  while(!feof(iFile))
      fread(buffer,2,1,iFile);
      unsigned short *tx = buffer;
      unsigned short rx[1] = 0, ;
      tr.tx_buf = (unsigned long)tx;
      tr.rx_buf = (unsigned long)rx;
      int size = ARRAY_SIZE(tx);


        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
        if (ret < 1)
            pabort("can't send spi message");

        for (ret = 0; ret < 1; ret++) 
            printf("0x%04x\n", tx[ret]);

        

  

第二个代码块没有

  
    int ret;
    unsigned short buffer[1];
    int zero = 0;

    FILE *iFile = fopen("firsttest.bin", "r");
    if (iFile == NULL)
      
          printf("Cannot open file \n");
          exit(0);
      

    struct spi_ioc_transfer tr[100];
        unsigned short *p = (unsigned short*) calloc(100, sizeof(unsigned short));
        unsigned short *p2 = (unsigned short*) calloc(100, sizeof(unsigned short));


  while(!feof(iFile))
    unsigned short *tx = p2;
    unsigned short *rx=p;
    for(int j = 0; j< 100; j++)
      fread(buffer,2,1,iFile);
      tx = (unsigned short*) &buffer+j;
      tr[j].tx_buf = (unsigned long)tx;
      tr[j].rx_buf = 0;
      tr[j].len = 2;/* Total length of message in bytes*/
      tr[j].delay_usecs = delay;
      tr[j].speed_hz = speed;
      tr[j].bits_per_word = bits;
      tr[j].cs_change = 1;

    


      ret = ioctl(fd, SPI_IOC_MESSAGE(100), &tr);
      if (ret < 1)
        pabort("can't send spi message");
    for(int v = 0; v<100; v++)
      printf("0x%04x\n", rx);
    
  
    free(p);

第二个代码块产生了这个错误

“无法发送 spi 消息:参数无效”

由于它是一个无效参数,我尝试传入 '&tr' 以及 'tr' 均无济于事。任何意见将不胜感激。

编辑:所以我决定使用第一个有效的代码。我想没有理由发送大额转账。我的系统足够快,电压足够快,可以有效地实时!!谢谢您的帮助。 (我还清理了很多代码以使其更易于阅读!)

【问题讨论】:

unsigned short buffer[1];,后来是tx = (unsigned short*) &amp;buffer+j;。好吧,除非 j==0,len==1,否则这将无法正常工作。您正在访问尚未分配的地址。 另外,请尽量减少强制转换(不幸的是 tx_buf 和 rx_buf 强制转换需要保留)。它隐藏了有效的编译器投诉。 【参考方案1】:

通过这个,我想到你可能没有正确定义你的 tr[j].rx_buf,这会导致无效的参数。需要有一个分配的存储空间,我假设它是 *p,但你没有将它与 tr 参数相关联。

【讨论】:

我尝试更改声明,但没有成功。 (无符号短*) rx = p; for 循环 rx = (unsigned short*) &rx+j; tr[j].rx_buf = (unsigned long) rx; 我认为你不需要声明 rx = (unsigned short*) &rx+j;如果您删除该行,它会起作用吗?如果不是,是否仍然是相同的“无效参数”错误? 所以,实际上,我又在看这个,想知道为什么你不能使用第一个代码块,而只是插入行 tr.cs_change = 1;在 while 循环的第六行附近的某个地方。这应该为您的设备提供所需的行为,即在每条消息之间重新声明芯片选择。 是的,但是 tr 是包含 100 个结构元素的结构数组。我对 C 不是很熟悉,但我认为这会导致编译器错误。 是的,它确实给出了编译器错误。我只是修改了这段代码以发送超过 1 条消息,但我认为缓冲区有问题。我尝试删除您建议的那条线,仍然没有。 corelis.com/education/tutorials/spi-tutorial【参考方案2】:

在struct spi_ioc_transfer tr之后添加memset(&amp;tr, 0, sizeof(tr));

https://community.nxp.com/thread/482375

【讨论】:

以上是关于ioctl“无法发送 spi 消息:无效参数”Beaglebone Black的主要内容,如果未能解决你的问题,请参考以下文章

kgsl_ioctl_gpu_command

如何转发/复用 ioctl 组?

unlocked_ioctl和compat_ioctl

kgsl_ioctl_gpumem_alloc

kgsl_ioctl_drawctxt_create

如何调用 compat_ioctl 或 unlocked_ioctl?