This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/processor-SDK-AM335X:ioctl 消息错误

Guru**** 2979400 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/677791/linux-processor-sdk-am335x-ioctl-message-error

器件型号:PROCESSOR-SDK-AM335X

工具/软件:Linux

我们将从 ARM 嵌入式 Ubuntu 14.04 (内核3.14)更新到 ARM 嵌入式 Ubuntu 16.04。 在第一个平台上、我们使用 SPIDEV 访问芯片、没有任何问题。 在 Ubuntu 16.04 (Kernel 4.9.59)平台上、在 ioctl SPI_IOC_MESSAGE 之后出现 EINVAL 错误。 内核来自 TI 的 SDK 4.02.00.09。

调用 ioctl 的代码如下所示:
SpiComm_t::传输(int i4Length){
int ret =-1;

m_tr.len = i4Length;

ret = ioctl (m_FD、SPI_IOC_MESSAGE (1)、&m_tr);
if (ret){
printf ("SPI IOCTL 错误%s\n"、strerror (errno));}

return;
}

SpiComm_t::SpiComm_t( uint32_t w4Bus,
                      uint32_t w4ChipSelect ) :
    m_fd(-1),
    m_b0IsInitialized(false),
    m_w4Bus(w4Bus),
    m_w4ChipSelect(w4ChipSelect)
{

  m_tr.tx_buf = (unsigned long)m_c1BufTx;
  m_tr.rx_buf = (unsigned long)m_c1BufRx;

  m_tr.delay_usecs   = SX_1276_SPI_DELAY;
  m_tr.speed_hz      = SX_1276_SPI_SPEED;
  m_tr.bits_per_word = SX_1276_SPI_BITS;
}

m_tr and m_c1BufTx are defined as:
  spi_ioc_transfer m_tr;

  uint8_t m_c1BufTx[0xff+1];
  uint8_t m_c1BufRx[0xff+1];



调用传递函数的代码为:

  // Reset memory (Optional...  Helps diagnose failures to read.)
  memset(m_c1BufTx, 0xFF, sizeof(m_c1BufTx));

  // Put address
  m_c1BufTx[0] =  address;

  // Reset memory (optional...)
  memset(m_c1BufRx, 0xFF, sizeof(m_c1BufRx));

  // Invoke ioctl transaction
  int result = Transfer(size+1);

我们使用的是 TI SDK 4.0中的内核4.9.59。 我已将 EINVAL 跟踪到 spidev.c 驱动程序、但无法理解我为什么会遇到错误。

spidev.c 代码为:

tmp = _IOC_SIZE(cmd);
if ((tmp % sizeof(struct spi_ioc_transfer)) != 0)
    return ERR_PTR(-EINVAL);
*n_ioc = tmp / sizeof(struct spi_ioc_transfer);
if (*n_ioc == 0)
    return NULL;

如果有任何帮助,将不胜感激。 
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在上述问题上取得了一些进展。 将零不再spi_ioc_transfer产生 EINVAL 错误、而是得到 EBUSY 错误。 我猜结构中的 cs_change 或 pad 会导致 EINVAL 错误。

    由于我不应该在每个 SPI_IOC_MESSAGE 上看到 EBUSY 错误、因此仍需要进行更多调查。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    EBUSY 不是来自调用的错误。  SPI_IOC_MESSAGE ioctl 调用返回所返回消息的长度。 因此、在这种情况下、它不是错误的指示。 我看到的 EBUSY 来自之前的调用。 更正后的代码现在为:

    errno = 0;
    ret = ioctl (m_FD、SPI_IOC_MESSAGE (1)、&m_tr);
    //请注意,如果
    
    (errno!= 0)
    {,则该 ioctl 返回应答长度,而不是设置 errno 的指示//检查 errno
    printf ("SPI IOCTL ret (%d) error (%d)%s\n"、ret、errno、strerror (errno));
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您分享该解决方案。