Electronic – How to organize robust communication between a PC and a microcontroller

communicationraspberry pistm32

I have a Raspberry Pi and STM32F072. What I want to do is very simple: Generate lots of data on the Raspberry Pi and transfer it to the STM32.

There are several things that are important:

  • The STM32 needs time to process data, so the Raspberry Pi should send data only when the STM32 is ready to process it.
  • The communication needs to be robust. By that I mean guaranteed delivery and no errors (some kind of error correction must be present). Also I want to be confident that connection can stay alive indefinitely.
  • Preferable at least 1 Mbit/s speed.

I considered using SPI, I²C, UART and USB, but they all share a common problem: They are all too low-level (level 1-2 of the OSI model) and lack any flow control (therefore aren't robust).

  1. Are there any implementations of some preferably lightweight transport protocol on top these which can be is used?

  2. If I have to implement such a transport protocol myself, which underlying protocol will be the simplest to use? Here are my thoughts; please correct me if I am wrong on any of these:

    • UART is simple, but slow on Raspberry Pi. I think can use a USB-to-UART converter (e.g. ch340) to make it faster, but is it a good idea?
    • SPI is fast and simple. There is a snag though: Raspberry Pi supports SPI only in master mode, which makes protocol slightly more complicated.
    • I²C is probably fine, but it's not clear why it could be better than SPI in my case.
    • USB is fast, has error correction and guaranteed delivery built-in, but it is very complex.

Best Answer

I think SPI would be my first choice. I2C and UART are way slower, USB is overkill. 1 MHz is not slow, but certainly doable for a short distance. You might need matched impedances on your lines, and a scope will be very handy for troubleshooting.

I'd assume that errors are rare. On top of SPI, you could implement a go-back protocol: send data as a big block with an ID and a checksum. With each SPI exchange, the ST returns the ID of the last succesfully received block. When that doesn't match what the RaPi hoped for, it must go back to transmitting the last not-yet-succesfully-received block.

When a block is not received OK, the RaPi will notice this with the transmission of the next block, so two blocks are lost. If this is deemed too much the TS could buffer one extra block, or the acknowledge could be piggybacked on a tail part (dummy bytes) of the block itself.