RasPi Direct Hardware Access
Integrated peripheral access without operating system drivers.
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Groups Pages
Functions
SPI Slave (via IIS/PCM)

These functions allow the Raspberry Pi to act as SPI slave, even though it has some serious limitations. More...

Functions

static void spisl_init ()
 Configure PCM hardware to act as SPI slave.
 
static int spisl_poll (int num)
 Return true if at least num bytes are available in the receive FIFO. Only guaranteed to work correctly with num == 1. Larger values may return true even if less bytes (but at least one) are available.
 
static uint8_t spisl_read (void)
 Read a single byte received via SPI. Block if FIFO is currently empty.
 
static void spisl_write (uint8_t data)
 Send data via SPI. Block if FIFO is currently full. Note that an SPI slave only sends while receiving, so data is only sent while the master transmits a new byte, which may be much later (or never).
 
static void spisl_flush ()
 Block until transmit FIFO is empty.
 
static void spisl_synchronize (void)
 Synchronize to SPI master. More...
 

Detailed Description

These functions allow the Raspberry Pi to act as SPI slave, even though it has some serious limitations.

The natve SPI slave component is not connected to the board, so this is the only way to get some kind of SPI slave mode of operation. Note that you must unload the PCM kernel module, or these functions will not work correctly.

It (ab)uses the PCM interface for this, but there is no way to synchronize to byte boundaries. You must synchronize to the master clock in some way. spisl_synchronize() does so by expecting a continuous byte stream and glitching the clock until the bytes read correctly.

Declared in raspi/spisl.h.

Wiring

On the Raspberry Pi, this uses the unpopulated connector P5, which is only available on Rev. 2 boards. It looks like this:

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┏━━━━━━━━━┓ P1                      ┃
┃ ┗━━━━━━━━━┛ (GPIO pin header)       ┃
┃ P5 ┏━━━┓                       ┏━━━━━┓
┃    ┗━━━┛       ┏━━━━━┓         ┃ USB ┃
┃ (unpopulated)  ┃ CPU ┃         ┗━━━━━┛
┃                ┗━━━━━┛         ┏━━━━━┓
┃                                ┃ LAN ┃
┃      Raspberry Pi (top view)   ┗━━━━━┛
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

┏━━━━━━━━━━━━━━━━━━━━━━━┓
┃ +5V   SCLK  MOSI  GND ┃  P5 pin mapping
┃ +3.3V  CS   MISO  GND ┃  (top view)
┗━━━━━━━━━━━━━━━━━━━━━━━┛

Note that CS (Frame Sync) is not actually used. The Pi must be the only slave on the bus, and you should wire CS to GND.

Function Documentation

static void spisl_synchronize ( void  )
inlinestatic

Synchronize to SPI master.

Due to the way the Raspberry Pi PCM interface works, bytes are usually not aligned correctly. To establish correct transmission, the master should transmit a stream of marker bytes (0x81) until it reads the marker byte back. This function will adjust reception parameters until the marker bytes come through correctly, then send a marker byte as acknowledgement. Finally, the master sends (marker ^ 0xff) to finish synchronization.

You can use this function as template in case you require some other way of synchronization, e.g. when you don't have the option to modify the master's program code. In any case, there is no way to reliably synchronize master and slave without reading (and discarding) several hundreds of bytes. The Frame Sync input is not reliable enough for this purpose, unfortunately.