Using SPI on Raspberry

NOTE!! It seems the code example and buffer size changing below does not work on the newer kernals. I will let you know when I find the problem.

 

SPI?
SPI, Serial Peripheral Interface is a serial protocol. It uses a clock, data in, data out and a chip select from the main controller (often called CLK,MISO, MOSI and CS).

When you give the order to send, let’s say, 4 bytes, CS will go low, and the data is then clocked out on MOSI using the clock, one bit at each clock cycle. At the same time a bit is clocked into the master using MISO. Either you like it or not, your input buffer will contain the number of bytes you also sent.

I have tested to send data with up to 60MHz clock which, in real life, gives something like 45Mbit. Not that bad for a small serial port.

Using the SPI interface (from user space, ie a “normal” program) on your Pi is easy!

Installing
First, if not already done, you have to make sure the SPI kernel module is loaded at startup. The easiest way to have it load the module at startup is to enable it in raspi-config. So,

sudo raspi-config

will get you into the configuration menu. Here you can select “Advanced Options” and you will then find SPI in the list. Enable it and exit the configuration tool. Now reboot.

A very simple example, sending 4 bytes on the SPI bus:

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <stdint.h>

void main(void)
{
int retVal;
int SPIDescriptor;

uint8_t spiBufTx [4]; //We want to send and receive 4 bytes
uint8_t spiBufRx [4];
struct spi_ioc_transfer spi;

spiBufTx [0] = 0x23; //Just put some example data in the send buffer
spiBufTx [1] = 0x34;
spiBufTx [2] = 0x45;
spiBufTx [3] = 0x56;

spi.tx_buf = (unsigned long)spiBufTx;
spi.rx_buf = (unsigned long)spiBufRx;
spi.len = 4; //4 bytes to send
spi.delay_usecs = 0; //Delay between each byte
spi.speed_hz = 1000000; //1MHz transfer speed
spi.bits_per_word = 8; //8 bits/word

retVal = ioctl (SPIDescriptor, SPI_IOC_MESSAGE(1), &spi); //Send!

if(retVal < 0)//Check for success or failure
printf(“Write to SPI Device failed”);
//Now spiBufRx contains the received data.
}

Maximum transfer size
If you feel 4096 bytes is not enough for sending data on the SPI you can change it. The size of the buffer is determined by the file /sys/module/spidev/parameters/bufsiz which holds the buffer size in normal text. The file is read-only, but using chmod (sudo chmod 777 bufsiz, for example) makes it writeable. This change is not permanent, you will be back to 4096 bytes when you reboot. I tried setting it to 131072 bytes (128k) and it seems to happily send 70kbytes after that. You just need to use a clock frequency high enough. There is a 150ms timeout for each transmission. (I haven’t actually tested this with a real data transfer yet. I will let you know when that happens.)

I found the SPI transfer size info here, but I did not get their permanent solution to work. Let me know if you have more info!

Leave a Reply