We will now look at a significantly more complicated example. The cost of embedded systems is a sensitive function of the number of chips that are required to implement it. The chip count starts climbing rapidly when one accounts for the CPU, memory, the peripheral devices themselves, the chip select logic, and all the miscellaneous glue logic that is necessary. Even if cost is not a major concern, a design involving fewer chips is likely to be more reliable than one with many chips. This is one reason why highly integrated chips are so popular for such systems. Highly integrated chips are rather expensive, so one approach that is often used is to design the peripheral chips so that they can interface directly with the CPU, thus eliminating all the ``glue''. With this approach the number of pins required to implement the interface becomes a consideration, the fewer the pins the better.
As a consequence of this, devices that use bit synchronous serial communication with a controller have become common. Several microcontrollers provide support for a synchronous protocol as do EEPROMS, A/D and D/A chips. There are several synchronous protocols in common usage, IC and SPI are probably the most common. We will look at how to implement SPI here.
Devices using SPI are classified as either master or slave devices. They use three wires for communication: MOSI, master out and slave in, MISO, master in and slave iout, and a clock line. The MOSI line is the output line for the master device and is the line that the slave device reads data in from. The MISO line is the output line for the slave device and is the input line for the master. The transfer of data onto the two lines is bitwise and occurs at previously agreed upon phases of the clock signal. There can be multiple slaves, but there is only one master at a given time. The SPI master drives the clock and MOSI lines, these lines are used as inputs by the slave(s). The slave drives the MISO line. If there are multiple slaves, there must be some arrangement (hardware or software) to decide which slave is allowed to drive MISO. While the master is sending data out on MOSI, the selected slave is sending data out on MISO. So at the end of a transfer, the masters input buffer matches the slaves output buffer and the slaves input buffer is a copy of the masters output buffer. Depending upon the application the master can be a fixed device, or the roles of master and slave can shift among the devices.
Like RS-232, SPI is not really a standard but more of a conceptual approach. There are variations in the clock polarity, the clock phases at transfer time, the bit order of a transfer and the number of bits that constitute a single transfer. In our example we will choose one common set of choices:
It would be nice if we used the open collector lines for MOSI, MISO and clock. That way we could decide at runtime whether to be master or slave and use the lines as either input or output as appropriate. Unfortunately there is a problem with this idea. A pullup resistor must be put on the line in order to assure that the line really goes up to 5 volts when it is not being driven low. The need for this resistor introduces a minor mechanical inconvience: where do we physically locate these resistors for what otherwise would just be a simple cable ? One place is inside the hood for the DB-25 connector on one end of the cable, one just has to provide for a 5 volt source inside this hood too. A much more serious problem is that the pullup resistors limit the switching rate on the lines which will result in very slow transmission rates. As a consequence of these problems we will avoid using the open collector lines for SPI. Instead we will use the following: MOSI will be #DATA bit 0, MISO will be #STATUS bit 6, the clock line will be #DATA bit 1 for the master and be attached to #STATUS bit 5 on the slave side. If we make our cable have 5 wires (MOSI, MISO, two clock lines and ground) as shown in Figure 1, then we can still choose which side is master at runtime (one clock line will always be idle); if we use slave select control then we need to add two more wires (this is not really necessary for PC-PC communication and possibly not for some other devices either). Some simple devices can only be used as a master or only as a slave so its useful to be able to run in either mode.
Many devices have SPI implemented in hardware and can therefore run extremely fast; since we are implementing SPI in high level code our system might not be capable of running so quickly. Since the data transfer rate in both directions is controlled by the master, it is desirable to run in master mode from the slowest device.
Listing 2 is an implementation of SPI, for master or slave mode, that will run either under MSDOS or Linux. I put 1 microsecond pauses after each clock edge, this is something you can experiment with. With these pauses I can reliably transfer data between my 120Mhz Pentium and my 40Mhz '386 with either machine being the master. Without the pauses I can only transfer with the '386 as the master. I have also used this code, in master mode, to communicate with the SPI port on the Motorola 68332. This, and many other Motrola microprocessors, contains a Queued Serial Module (QSM) which is effectively a serial I/O coprocessor. SPI using the QSM consists of setting up the configuration registers, filling the transmit buffer, and then letting the QSM run in the background. The CPU is free to do other things during the transmission, it is notified that the transfer is complete via an interrupt or by polling a status register (depending upon the configuration settings). The QSM is very flexible in the range of configurations that it can be put into. For less flexible devices you may need to play with the timing, clock polarity and phase. Some devices have different timing requirements for interbit timing compared to interbyte timing. Some allow them to be selected for the entire duration of the transfer while others require that they be selected once for each byte (and deselected in between). A further variation to be aware of, is some devices have open collector SPI pins others do not.