MATLAB Answers

SPI does not activate Raspberry Pi when run from Simulink while attempting to send more than 4 bytes in a message

5 views (last 30 days)
mprice
mprice on 28 Oct 2016
Edited: mprice on 31 Oct 2016
I have implemented an s-function block with the s-function builder in Simulink that uses WiringPi to use SPI on the Raspberry Pi 2 Model B. This works when I load 4 bytes or fewer into the buffer to be sent. However, when I try to send 6 bytes, the SPI pins on the Raspberry Pi do not activate at all.
My s-function block takes bytes to be written as an input vector, and outputs bytes read from the peripheral as a vector. Also, this problem only occurs when the input bytes are written to the SPI buffer. The transmission sends perfectly fine if I write test bytes to the buffer inside the block, ignoring the input. It's also perfectly fine if I send 4 bytes that are provided by the input to the block. The "outputs" section of the code looks like this:
uint8_t spiData[6];
int n;
spiData[0] = write[0];
spiData[1] = write[1];
spiData[2] = write[2];
spiData[3] = write[3];
spiData[4] = write[4];
spiData[5] = write[5];
// If the above block is commented out and this is used instead, the transmission succeeds
// spiData[0] = 0x01;
// spiData[1] = 0x00;
// spiData[2] = 0x02;
// spiData[3] = 0x03;
// spiData[4] = 0x04;
// spiData[5] = 0x05;
spi_test[0] = wiringPiSPIDataRW(0,spiData,6) ;
for (n = 0; n < 6; n++){
read[n] = spiData[n];
}
I know that the Raspberry Pi SPI buffer is much larger than 4 bytes, and I'm unsure why writing the input to the SPI buffer should cause it to fail. This input I'm testing with is just a uint8 vector of length 6. Changing the SPI baud rate and the sample time of the simulink model has no effect. Any insights would be appreciated.

Accepted Answer

mprice
mprice on 31 Oct 2016
Edited: mprice on 31 Oct 2016
A few things I changed to make this work.
Rewrote the wiringPiSPIDataRW function to look like this:
int wiringPiSPIDataRW (int channel, unsigned char *data, int length)
{
struct spi_ioc_transfer spi[length] ;
int i = 0;
channel &= 1 ;
for (i = 0; i < length; i++){
memset(&spi[i], 0, sizeof (spi[i]));
spi[i].tx_buf = (unsigned long)(data + i) ;
spi[i].rx_buf = (unsigned long)(data + i) ;
spi[i].len = sizeof(*(data + i)) ;
spi[i].delay_usecs = spiDelay ;
spi[i].speed_hz = spiSpeeds [channel] ;
spi[i].bits_per_word = spiBPW ;
}
return ioctl (spiFds [channel], SPI_IOC_MESSAGE(length), &spi) ;
}
Apparently the memset is to null is necessary due to changes in the internal RasPi library. The for loop was added to create a separate transfer for each byte.
The data type for the data buffer in the s-function was changed to unsigned char.
The block sample mode was changed to discrete and set to the sample time of the full system.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!