1

We are updating from an ARM embedded Ubuntu 14.04 to ARM embedded Ubuntu 16.04. On the first platform we are accessing a chip using SPIDEV without a problem. On the Ubuntu platform I am getting an EINVAL error following a ioctl SPI_IOC_MESSAGE.

I have seen the message SPI_IOC_MESSAGE(N) macro giving me fits and it does not solve the issue.

My code is as follows:

 SpiComm_t::Transfer(int i4Length) {   
   int ret = -1;

   m_tr.len = i4Length;

   ret = ioctl(m_fd, SPI_IOC_MESSAGE(1), &m_tr); 
   if (ret )   {
     printf("SPI IOCTL error %s\n", strerror(errno));   }

  return ret; 
}

The calling code looks like:

  // 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);

We are using Kernel 4.9.59 from TI SDK 4.0. I have traced the EINVAL to the spidev.c driver but cannot make sense of why I am getting the error.

spidev.c code is:

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;

/* copy into scratch area */

Any help would be greatly appreciated.

1 Answers1

4

The problem appears to have been that the spi_ioc_transfer had some garbage in it. Zeroing out the structure solved the issue. Either cs_change or pad was the cause of the error.

Also, the return code from ioctl(fd, SPI_IOC_MESSAGE(1), ...) does not indicate failure or success. Instead in this instance it returns a size of the message returned. To test for error had to check errno directly.

The updated code for the transfer function is now:

errno = 0;
ret = ioctl(m_fd, SPI_IOC_MESSAGE(1), &m_tr);
// NOTE this ioctl returns the lenght of the answer not an indication of  setting errno
// Check errno instead
if (errno != 0)
{
    printf("SPI IOCTL ret(%d)error(%d) %s\n", ret, errno, strerror(errno));
}
  • I'm not certain this part is quite right: "the return code from ioctl(fd, SPI_IOC_MESSAGE(1), ...) does not indicate failure or success." According to the ioctl man page (https://man7.org/linux/man-pages/man2/ioctl.2.html), "On error, -1 is returned, and errno is set to indicate the error." Non-negative values are used different ways depending on the request, but negative values mean an error occurred. – maldata Sep 22 '22 at 14:52