Mizar32/SPI
Introduction
editAnother 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
editThe 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.
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
editSD card on SPI
editeLua 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
editAn SPI
module is included in Alcor6L to talk low-level SPI protocol and is presumed to work but is untested.
eLua API
editList 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
editList 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- Introduction to Serial Peripheral Interface, David Kalinsky and Roee Kalinsky, in Embedded's electronics blog, 1 Feb 2002.
- EEHerald's Online course on Embedded Systems, Module 12: SPI Bus interface
- The Atmel AT32UC3A datasheet, section 23: "Serial Peripheral Interface"
- Wikipedia - Serial Peripheral Interface
- The eLua SPI module reference manual;