In this post we will see how to send and receive SPI messages to the device from userspace.
You can open the SPI device by using the below function call.
You can now set the configuration for the SPI using ioctl calls.
int fd = 0;
fd = open("/dev/spidev2.0", O_RDWR);
if (fd < 0)
{
printf("SPI : can't open device");
return -1;
}
To set the SPI mode
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);To get the SPI mode
if (ret == -1)
{
printf("SPI : can't set spi mode");
return 1;
}
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);Other SPI Bus properties can be manipulated in the same way.
if (ret == -1)
{
printf("SPI : can't get spi mode");
return 1;
}
Now the send a message over SPI Bus, You will need to fill up the message structure and pass it down.
struct spi_ioc_transfer mesg[1] = { 0, };To receive SPI message
mesg[0].tx_buf = (unsigned long)out_buffer;
mesg[0].len = num_out_bytes;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), mesg);
struct spi_ioc_transfer mesg[1] = { 0, };There may be requirements where a write has to be followed by a read without toggling the Chip Select signal. You can form 2 messages as below to handle such situations.
mesg[0].rx_buf = (unsigned long)out_buffer;
mesg[0].len = num_out_bytes;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), mesg);
int spidev_if_write_read(unsigned int num_out_bytes,The variable cs_change=0 disables the change in CS signal state between the two transactions.
unsigned char *out_buffer,
unsigned int num_in_bytes,
unsigned char *in_buffer)
{
struct spi_ioc_transfer mesg[2] = { 0, };
uint8_t num_tr = 0;
int ret;
if((out_buffer != NULL) && (num_out_bytes != 0))
{
mesg[0].tx_buf = (unsigned long)out_buffer;
mesg[0].rx_buf = (unsigned long)NULL;
mesg[0].len = num_out_bytes;
mesg[0].cs_change = 0;
num_tr++;
}
if((in_buffer != NULL) && (num_in_bytes != 0))
{
mesg[1].tx_buf = (unsigned long)NULL;
mesg[1].rx_buf = (unsigned long)in_buffer;
mesg[1].len = num_in_bytes;
num_tr++;
}
if(num_tr > 0)
{
ret = ioctl(fd, SPI_IOC_MESSAGE(num_tr), mesg);
if(ret == 1)
{
return 1;
}
}
return 0;
}