Page 1 of 2

SPI synchronization between two devices

Posted: Tue Feb 02, 2021 4:15 pm
by nico314
I am trying to use an SPI bus to exchange data between two ESP32 boards. I connected both using cables, making sure MOSI/MISO are swapped, and can initialize both ends with spi=machine.SPI() and similar parameters for phase, polarity, and baud rate. What I cannot figure out is how to synchronize read/writes between the two hosts. Calling read() always returns data (only zeroes), and calling write() always succeeds. When I loop on a read() on the receiving end I can see it is constantly reporting zeroes and sometimes shows the actual transmitted bytes. What is the correct expected way to synchronize the two hosts? Did I forget something in initializing the bus?
Thanks for helping!

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 5:37 pm
by Roberthh
Did you configure one device as master and the other as slave? Because then the master controls the communication and runs the clock line. The slave would wait for the master sending a request, which may required the slave to submit teh amount of data defined by you in a protocol.

It may be easier for you to use UART, which is symmetric. And the data rates can also go into the Mbaud range.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 6:02 pm
by nico314
Ah, good point. That is probably what is missing here. All I do for init is:

Code: Select all

spi=machine.SPI(1,polarity=0,phase=0,baudrate=200000)
spi.init(baudrate=200000)
What should I do to switch to SPI master/slave? I probably oversaw something but could not find anything relevant in the micropython docs.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 6:18 pm
by Roberthh
The ESP32 does not support slave mode. That's the sentence I forgot, when suggesting to use UART.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 7:13 pm
by nico314
Ok. I followed your suggestion, tried a UART interface with baudrate set to 40*115200 and it seems to work fine. Thanks!
Note to self: you either need to swap the cables or swap the pins in the constructor, but not do both :-)

SPI should be faster though. Ultimately I would like to use an ESP32 board as a WiFi modem for other boards, so faster is better.
Do you know what would it take to add support for SPI slave in Micropython/ESP32?
Thanks again for your help!

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 7:38 pm
by kevinkk525
nico314 wrote:
Tue Feb 02, 2021 7:13 pm
Ultimately I would like to use an ESP32 board as a WiFi modem for other boards, so faster is better.
Do you know what would it take to add support for SPI slave in Micropython/ESP32?
Thanks again for your help!
You might want to take a look at this thread for the RPI Pico: viewtopic.php?f=21&t=9664#p54190

Seems like we have the same goal. But we can utilize the existing work for a WIfi modem on the esp32. It's in C++ but there might be no changes neccessary. Afaik this is the most advanced project for a WIFI modem.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 7:47 pm
by Roberthh
The espressif RTOS supports SPI slave mode, and using either the espressif SDK or Arduino you can use it. For Micropython, the respective module has to be adapted, which is quite some work. Whether using MicroPython you would gain much with respect to UART, is not clear.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 8:12 pm
by nico314
Robert: you do have a point. The ESP32 docs indicate a max speed of 5Mbit/s for UART. SPI can be controlled at 80MHz, which would suggest roughly only twice faster than UART. May not be worth the effort. I will anyway look into the SPI implementation on Micropython to estimate how much work would adding slave mode represent, keeping in mind that the UART version works out of the box. Thanks again for your help.

Kevin: you guessed right! Though I probably won't see a real Raspberry Pico before a long time.
Implementing full socket support on top of a bus interface is not going to be straightforward. Maybe we could skip the whole socket abstraction layer and head straight for an HTTP client instead? Maybe easier to implement such a thing on top of FIFO-like bus objects.
Since you have two cores running on an ESP32 it could make sense to dedicate one to WiFi and the other to adapting high-level protocols to sockets, only exposing the high-level parts to the UART/SPI bus. The main inconvenience is that you would have to split networked code into a socket-based part running on ESP32 and a high-level part (e.g. an NTP client, an HTTP client) running on Pico. Just my 2c, I obviously haven't looked into the details.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 8:16 pm
by kevinkk525
Adafruit already did all the work, it's just in CircuitPython. I have to test it to be sure it works as expected, but if it does, it's just porting from CircuitPython to Micropython. That should be rather easy even though it might still be some work.

And the esp32 part for the wifi modem is already finished in the nina-fw from Adafruit.

So an abstract socket implementation shouldn't be difficult and the basis is already there in CircuitPython.

Re: SPI synchronization between two devices

Posted: Tue Feb 02, 2021 8:25 pm
by nico314
Excellent! So the only missing part would seem to be SPI slave support in MicroPython then?