25
\$\begingroup\$

Is there a difference between the two, or is it just a matter of abstraction? My intuition says there's no difference but I'd love to be wrong.

\$\endgroup\$
33
\$\begingroup\$

An actual SPI controller peripheral in the MCU can often run much faster than bit-banging the interface. Of course, it depends on the MCU, but it would not surprise me to see a SPI controller running at 30+ MHz, while bit banging might be limited to around 1 MHz (if you're lucky).

But there is more to it than that. When bit-banging, the MCU is busy bit-banging it. It is shifting the data out and twiddling the GPIO lines. Meaning, it cannot be doing anything else. When using a SPI controller, the controller is busy doing all that stuff and the MCU is free to do other things.

So with an actual SPI controller, the actual SPI transfer is much faster and the MCU gains back some cycles that it can use to do other things.

\$\endgroup\$
11
\$\begingroup\$

There is no difference in terms that you can achieve the same result using both methods but there are a few reasons why you would choose one over the other.

Using a SPI peripheral will free the processor from having to care about generating the timing for bit banging the I/O pins, allowing it to perform other computational tasks and simplifying your programming of the CPU. Because the peripheral is implemented in hardware it will run faster and use less power than bit banging I/O. There may be cases where you would want to bit bang I/O to interface with SPI if your application demands that you choose a processor without a SPI peripheral. For sanity reasons I'd recommend avoiding that unless absolutely necessary.

\$\endgroup\$
  • \$\begingroup\$ The sanity reason is rubbish. Often setting up the SPI hardware to exactly the configuration you require takes more time reading the SPI peripheral datasheet than just writing the SPI master code, and thereby only having to read the slave device datasheet. \$\endgroup\$ – Olin Lathrop May 21 '13 at 13:57
  • \$\begingroup\$ I'll admit I was being a little bit sensationalist with my sanity remark but the (admittedly unwritten) intention was that as application complexity increases so does the burden of ensuring that the system as a whole continues to function within the intended timings. I've implemented it both ways and I know that I'd prefer to use the peripheral, even if it takes me an extra few minutes to read the data sheet. \$\endgroup\$ – Amoch May 21 '13 at 22:26
6
\$\begingroup\$

SPI is a synchronous interface, with the master controlling the clock. That means if you are the master, you get to pick the clock speed and timing. Slave devices will have some upper limit on the clock frequency they can handle, but typically don't care how slow the clock is below that. More specifically, there is usually a minimimum time each slave needs to see the clock in the high and low state before it can switch again, and there will be some minimum data setup and hold limits on the data line surrounding the clock edge on which the slave reads the data line.

Because of this, implmenting a SPI master in firmware is really quite easy. I have done this often as a convenience to use certain pins, when there was no built-in SPI hardware, or it wasn't available for that purpose for whatever reason. Doing a SPI master in firmware is about as easy as it gets.

Many SPI slave devices are quite fast, so often the minimum clock and setup times are met simply by making sure each is at least one instruction cycle wide. In that case, the code is very short and fast. In some cases a slave device might require two or three instruction cycles per clock phase, but that's really not hard to guarantee either. The low level SPI bit loop requires doing some shifting of the next output bit into position, grabbing the input bit, and checking the loop counter. You can usually meet two or three cycle minimum timing requirements just by arranging when you drive and sample the lines with some of the other overhead inserted at the right places. If speed is important, you can use the assembler preprocessor to write a unrolled loop. With techniques like this, you can often achieve pure firmware SPI at about the speed the slave device can handle anyway.

There are some advantages to doing the SPI master in firmware. SPI hardware is sometimes a bit ridgid in how it can be configured. There is always the issue of what exactly is supposed to happen immediately when slave select is asserted. Is the first bit written to the data lines then? What if the clock starts low and the data lines supposed to be latched on the falling edge? Sometimes this matters, sometimes it doesn't. With a firmware SPI master, you can be more forgiving and possibly use the same routine for communicating with different slaves. For example, you can make sure that the MOSI (Master Out Slave In) data line is stable on both edges of the clock. SPI hardware generally won't do that, so such hardware would need to be re-configured depending on which slave it is communicating with at the time.

Another advantage of a firmware SPI master is that you can chose a arbitrary number of bits per SPI sequence. Hardware is usually limited to multiples of 8 bits. Most devices are designed to allow for whole byte transfers, but often don't require them. For example, a 10 bit A/D will likely send the 10 data bits first, then send 0 or garbage after that if you keep clocking it. If using hardware SPI, you will be forced to transfer 16 bits and mask off the garbage. Everything will work fine, but a firmware SPI master could actually be faster than the hardware in this case due to it only tranferring the minimum required 10 bits.

The main advantages of hardware SPI masters is that the firmware can initiate a byte transfer, then go off and do something else. The clocking can also usually be faster than even a unrolled firmware loop can achieve. Note that while both of these advantages can be important in certain circumstances, they are often irrelevant. Most SPI code that uses hardware to transfer a byte then immediately goes into a wait loop for the hardware to finish the transfer. Also check the slave timing requirements carefully. SPI devices are generally fast as a whole, but there are cases where you need to slow down the hardware anyway to match the maximum speed the slave can handle.

That was all from the master point of view. In short, there is often little advantage to using SPI hardware as master, and even a few advantages in not using it sometimes. However, that is all different for slaves. Since the master controls the clock, the slaves have to be ready for whatever the master does whenever the master does it. The timing requirements are often quite short relative to instruction times, so having hardware implementing a SPI slave is usually what you want.

You can do SPI slaves in firmware, but it's tricky, you have to count cycles and latency carefully, and you usually end up implementing some subset of the protocol that you know your particular master uses. For example, one time I had to design a digital equivalent of a old analog controller board (they wanted extra features that couldn't be reasonably done in analog, and they wanted something smaller, cheaper to produce, and more stable). This board interfaced to the rest of the system over a SPI bus. The old analog board had a two-channel D/A to set the control values and a two channel A/D to read back measured values. Implementing both those in a single processor was tricky, and it included figuring out what subset of the hardware D/A and A/D SPI protocol the existing master actually used. It also envolved a processor that could run significantly faster than the SPI clock rate. In the end, I used three interrupts, one for each slave select and one for the rising edge of the clock line. That last one needed to be the highest priority interrupt in the system else the latency requirement couldn't be met.

Anyway, the overall point is that a firmware SPI master is easy, small, fast, and flexible, and there is little reason to shy away from doing one. On the other hand, for a slave you really want hardware, or you have to wake up and think very carefully about timing, latency, and the like.

\$\endgroup\$
  • \$\begingroup\$ Have you found any microcontroller slave implementations which can behave like typical hardware SPI devices (e.g. allowing the master to give an edge on CS and read status at any time, and using CS to mark command boundaries? Most implementations I've seen don't even report whether there was a CS edge between the current byte and the previous one. \$\endgroup\$ – supercat May 21 '13 at 15:32
  • \$\begingroup\$ @supe: Yes, that is a issue. Slave SPI hardware typically ignores clock and input data and keeps the output data line at high impedance when chip select is not asserted, but it doesn't usually tell you where the chip select boundaries are. At least with the PIC SPI hardware I remember using, you'd have to set up your own interrupt on chip select for that. \$\endgroup\$ – Olin Lathrop May 21 '13 at 16:05
  • \$\begingroup\$ I was wondering if you knew of any decent implementations. I guess not. The problem with using a hardware interrupt on the select wire is that if a transition happens on the select wire very soon after a byte is sent, the slave may have a hard time resolving whether it happened before or after the byte in question. I find it puzzling that almost every chip has an SPI slave implementation, but it seems none of them can actually be used like a typical SPI hardware slave device. The situation is somewhat like the processor slave port on the PIC compared to the 8048. \$\endgroup\$ – supercat May 21 '13 at 16:17
  • \$\begingroup\$ The 8048 processor slave port has an address pin; when data is externally written to the 8048, the 8048 latches the state of that pin and makes it available to its code (typically the first byte of a command will be written to one address, and parameters or data to the other). A read of one address will yield whatever the 8048 code puts there, but some bits that are read from the other address are generated by the 8048 hardware to indicate whether its' ready to have data read or written. \$\endgroup\$ – supercat May 21 '13 at 16:19
  • \$\begingroup\$ +1 for pointing out the difference being bit-banging a master (easy) and a slave (much more difficult). \$\endgroup\$ – tcrosley May 21 '13 at 16:23
1
\$\begingroup\$

It depends on what you're doing the SPI for. If your interest is getting the highest data rates out of it, hardware is always faster than bitbanging (e.g. the arm cortex chip in the teensy 3 I can push out data at 22Mbps using hardware SPI support, vs. ~4.5Mbps with bitbanging (it can also handle arbitrary numbers of bits per transfer from 3-16 - useful when sending data out in 12 bit chunks for certain led controllers!)). On 16Mhz avrs, the difference is a little less extreme, highest data rate with hardware seems to be high 4/low 5Mbps, while bitbanging is around 2.3Mbps).

In addition, if you use hardware support, again, depending on the microcontroller in question, you have options available to you for using DMA controllers to shift your data out, letting your code go back to other, potentially more interesting things than babysitting the data write.

All of the above depends on whether or not hardware SPI is even an option.

\$\endgroup\$
0
\$\begingroup\$

If you bit-bang SPI, you can't use the SSP interrupt to handle communications. This isn't that important for SPI for many uses

\$\endgroup\$
  • 1
    \$\begingroup\$ No specific processor was mentioned, so "SSP interrupt" is a meaningless term in this context. \$\endgroup\$ – Olin Lathrop May 21 '13 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.