Introduction

edit

Another popular bus that is used to connect chips on the same board or in a modular design with more than one board inside the same box, is the SPI bus, which stands for Serial Peripheral Interface, sometimes also referred to as a “four wire” interface.

SPI is a synchronous serial data link that transmits and receives data at the same time and can achieve much higher data rates than I2C. It is ideally suited to streaming data applications such as reading/writing SD cards or sending/receiving audio. Normal frequencies are in the order of tens of Megahertz, for example a common 8 pin 32Mbit Atmel dataflash connected to SPI bus can operate at 66MHz.

There is no formal SPI standard. The bus was introduced for the first time by Motorola in 1985 and well documented the first time with the M68HC11 micro-controller. Since then it has been adopted by many other silicon manufacturer and is widely used in the embedded industry for many different applications. For example, all SD memory cards can be used with a SPI interface.

Other examples of real world applications of the SPI bus are to connect with Analog to Digital Converters, Digital to Analog Converters, digital sensors, EEPROMs, Flash memories, touch screen controllers, digital potentiometers, Real Time Clocks, switches, serial port controllers and USB controllers or simply to establish point to point communication between different micro-controllers in the same board.

SPI is a very simple communication protocol with almost no high-level protocol, which means that there is very little overhead and data can be transmitted at high rates in both directions at once.

Like I2C, SPI devices also communicate using a Master-Slave relationship, but instead of selecting a slave device by sending its address in the data, it selects it with an extra wire that goes to each slave device, which is called the Chip Select signal.

Unlike I2C, there can only be one Master device on each SPI bus.

Like I2C, the Master is the one that sends the clock pulses, but at each pulse, 1 bit data is sent from Master to Slave and one bit is sent from Slave to Master.

SPI uses 4 wires to communicate between a master and a slave device:

  • The Clock (SCLK)
  • Master Output Slave Input (MOSI)
  • Master Input Slave Output (MISO)
  • Chip Select (CS)

The first three wires are common to all devices on the bus and there is a separate Chip Select wire for each Slave device on the bus.

For example, a Master device with a single Slave needs four wires: three for SCLK, MOSI, MISO and a one for the Chip Select.

Every additional Slave, in an Independent Slave configuration, requires another GPIO pin as Chip Select to select another Slave from the Master.

In addition to the clock frequency in MHz, which corresponds to the bit rate, you must also defined the Clock Polarity (CPOL) and the Clock Phase (CPHA) with respect to the data.

There are 4 modalities for SPI communication and the modality that is chosen must correspond between the Master and Slave devices that are communicating in any one moment.

  • Mode 0 with CPOL=0 and CPHA=0
  • Mode 1 with CPOL=0 and CPHA=1
  • Mode 2 with CPOL=1 and CPHA=0
  • Mode 3 with CPOL=1 and CPHA=1

Communication is initiated by the Master device. It configures its clock frequency to be equal or less than the maximum frequency supported by the slave that it wants to communicate with. Then the desired Slave is selected with Chip Select line, by pulling it to a low state, then the Master starts to issue clock pulses.

A full duplex data transmission on two shift registers occur during each clock cycle. That means the master sends a bit on the MOSI line; the slave reads it from that same line and the slave sends a bit on the MISO line and the Master reads it from that same line.

If more data needs to be exchanged, the shift registers are loaded with new data and the process is repeated. Then, when no more data needs to be transmitted, the master stops the clock.

This is basically all that is defined for the SPI protocol. SPI does not define any maximum data rate, nor any particular addressing scheme; it does not have an acknowledgement mechanism to confirm receipt of data and does not offer any flow control.

Hardware view

edit

The AT32UC3A system-on-chip on the main board includes two SPI interfaces, SPI0 and SPI1, with SPI0 on the left bus and SPI1 on the right. Each interface has four chip-select lines, allowing a maximum of eight SPI devices; one of these (SPI1 CS0) is used to talk to the SD/MMC card and three of them (SPI0 CS0 and SPI1 CS1 and CS2) are available on the bus connectors.

Bus pins
Signal GPIO Bus pin eLua name PicoLisp
SPI0_CS0 PA10 BUS1&3 pin 12 pio.PA_10 'PA_10
SPI0_MISO PA11 BUS1&3 pin 13 pio.PA_11 'PA_11
SPI0_MOSI PA12 BUS1&3 pin 14 pio.PA_12 'PA_12
SPI0_SCK PA13 BUS1&3 pin 15 pio.PA_13 'PA_13
SPI1_CS1 PA18 BUS3 pin 11 pio.PA_18 'PA_18
SPI1_CS2 PA19 BUS4 pin 12 pio.PA_19 'PA_19
SPI1_MISO PA17 BUS4 pin 11 pio.PA_17 'PA_17
SPI1_MOSI PA16 BUS4 pin 10 pio.PA_16 'PA_16
SPI1_SCK PA15 BUS4 pin 9 pio.PA_15 'PA_15

Software view

edit

SD card on SPI

edit

eLua reads and writes the SD card over SPI and provides access to the files on the card using Lua's io module using filenames that start with "/mmc/".

In PicoLisp, the load function can be used to load Lisp code from an SD card and execute it within the read-eval loop. Example: (load "/mmc/lib.l" "/mmc/pilog.l")

Function interface

edit

An SPI module is included in Alcor6L to talk low-level SPI protocol and is presumed to work but is untested.

eLua API

edit

List of available functions:

Function Return value(s) Description
spi.setup(id, type, clock, cpol, cpha, databits) clock Setup SPI interface
spi.sson(id) nil Select the SS line (Slave Select) of the SPI interface
spi.ssoff(id) nil Deselect the SS line (Slave Select) of the SPI interface
spi.write(id, data1, [data2], ..., [datan]) nil Write one or more strings/numbers to the SPI interface
spi.readwrite(id, data1, [data2], ..., [datan]) An array Do spi.write and return the data read from the same interface

PicoLisp API

edit

List of available functions:

Function Return value(s) Description
(spi-setup id type clock cpol cpha databits) clock Setup SPI interface
(spi-sson id) Nil Select the SS line (Slave Select) of the SPI interface
(spi-ssoff id) Nil Deselect the SS line (Slave Select) of the SPI interface
(spi-write id 'any) The last written value Write one or more strings/numbers to the SPI interface
(spi-readwrite id 'any) Not Applicable Not implemented yet: See issue #13

Further reading

edit