SPI will not work from c++ program

Started by wapel, February 14, 2015, 12:42:32 PM

Previous topic - Next topic

wapel

Hello.
On my A20 Mirco with the default debian Image: A20-OLinuXino-MICRO Debian with kernel 3.4.90+ release 10

I don't get the SPI /dev/spidev2.0 working.
On the Linux shell i can execute following command: echo "test" > /dev/spidev2.0
With my Oscilloscope i can see the clock and mosi pulses --> OK.

Now i want to use this device from my c++ code and will not work. Here some lines of code i used to get some output/input.

********************* Variables *****************************
int spiDev;
static uint8_t spiMode = 3;
static uint8_t spiBPW = 8;
static uint32_t spiSpeed = 1000000;
static uint16_t spiDelay = 0;
int ret = 0;
********************* Init SPI*******************************

    spiDev = open("/dev/spidev2.0", O_RDWR);
    if (spiDev < 0)
{
perror("can't open device");
exit(1);
}
ret = ioctl(spiDev, SPI_IOC_WR_MODE, &spiMode);
if (ret == -1)
{
perror("can't set spi mode");
exit(1);
}
ret = ioctl(spiDev, SPI_IOC_RD_MODE, &spiMode);
if (ret == -1)
{
perror("can't get spi mode");
exit(1);
}
ret = ioctl(spiDev, SPI_IOC_WR_BITS_PER_WORD, &spiBPW);
if (ret == -1)
{
perror("can't set bits per word");
exit(1);
}
ret = ioctl(spiDev, SPI_IOC_RD_BITS_PER_WORD, &spiBPW);
if (ret == -1)
{
perror("can't get bits per word");
exit(1);
}
ret = ioctl(spiDev, SPI_IOC_WR_MAX_SPEED_HZ, &spiSpeed);
if (ret == -1)
{
perror("can't set max speed hz");
exit(1);
}
ret = ioctl(spiDev, SPI_IOC_RD_MAX_SPEED_HZ, &spiSpeed);
if (ret == -1)
{
perror("can't get max speed hz");
exit(1);
}
printf("spi mode: %d\n", spiMode);
printf("bits per word: %d\n", spiBPW);
printf("max speed: %d Hz (%d KHz)\n", spiSpeed, spiSpeed/1000);


*********************** Loop / send 7 Bytes************************************
      struct spi_ioc_transfer xfer;
      memset(&xfer, 0, sizeof (xfer));
      u_int8_t dataBuffer[] = {0x01,0x03,0x00,0x00,0x00,0x7D,0xB1};
      char rxBuffer[20];
      xfer.tx_buf = (unsigned long)dataBuffer;
      xfer.rx_buf = (unsigned long)rxBuffer;
      xfer.len = 7;
      xfer.delay_usecs = spiDelay;
      xfer.speed_hz = spiSpeed;
      xfer.cs_change = 1;
      xfer.bits_per_word = spiBPW;
      res = ioctl(spiDev, SPI_IOC_MESSAGE(1), &xfer);
      printf("SPI result: %d\n", res);


The Init part of the code works without error or bad return value.
In the loop the "ioctl" returns a -1 and i dont see a clock or mosi pulses like on the linux shell.

The c++ Code runs as root.
Somebody an idea why it will not work out of the c++ code ?


jmyreen

It would have helped if you had told us what the error was, i.e. what perror printed or what the value of errno was after the failed ioctl.

muellerMachine

I have the same problem, I wan't to access the MOD-SMB380 over SPI. I copied the code which i found in the driver folder /opt/spidev/MOD-SMB380/MOD-SMB380.c one to one into another location on the user space.

When I run the code form the user space it fails at the line:

status = ioctl(spi_fd, SPI_IOC_MESSAGE(2), spi);
if (status < 0) {
            perror("SPI_IOC_MESSAGE");
            return -1;
        }


perror prints: SPI_IOC_MESSAGE: Invalid Argument

I'have no clue why exactly the same code is working from within the driver folder, and not working from another folder.

Do you have any Idea?
I'm using the OlinuXino A20 Micro with debian 8.3

muellerMachine

I compiled the /opt/spidev/MOD-SMB380/MOD-SMB380.c in the same folder.

gcc -o smb380Test MOD-SMB380.c

But even there in the same folder as a.out is located the smb380Test throws the invalid argument error.

I tried as well runnig the spidev_test.c code (https://github.com/rm-hull/spidev-test/blob/master/spidev_test.c) but it throws the same invalid argument error. Is there something wrong with the compilation I'm using?

LubOlimex

It is a compilation issue related to differences in spidev.h between Linux releases.

Use these two files: https://drive.google.com/open?id=1ksDS4QEnCXaWQCjvcsW5Fb6TUso2jNDt
Technical support and documentation manager at Olimex

muellerMachine

Great thanks no it works perfectly with these two files in the same folder.

I compiled it with:
gcc -o smb380Test MOD-SMB380.c

and the invalid argument error is gone.
Thanks a lot