ESP32 <---> P2 SPI Code (runs at 2.4MBytes/sec)
RJSM
Posts: 68
A number of posts on the forums have expressed interest in connecting the P2 to an ESP32, thereby giving the P2 access to the outside world. I’ve developed some code to do this as part of a larger project and thought I’d share it for others to use and improve upon. The 2 programs here will allow you to connect a P2-EVALB and an ESP32 module via an SPI link (here the ESP32 is the master running a 20 MHz SPI clock - and the P2 is the slave). The actual data transfer rate you'll achieve (measured for a 32k data transfer in either direction) is ~ 2.4 Mbytes/sec. An Adafruit (or similar) NeoPixel (8 x WS2812) strip connected to the P2 provides lots of visual feedback as the code runs.
My ESP32 code was developed using the Arduino IDE. I found and made use of an ESP32 DMA SPI library that was essential in getting this working without too much complexity on the P2 end – the relevant link to that is mentioned in the code comments.
To do this work I made a small PCB that has an ESP32 module riding piggyback on my P2-EVALB (the DipTrace schematic pdf shows the connections). The photo here is rather old – in current testing I’ve got the breakout PCB plugged into the P31..P16 headers on a P2-EVALB board, but just P19..16 are used for the 4 wire SPI bus and P20 for the LED string.
You’ll find lots of comments to explain what’s going on at either end of this SPI link. Once data is moved over to the ESP32 then you can send it off to the cloud or whatever else you so desire. The world literally is your oyster then !
I’ve been talking to this P2/ESP32 combo by sending messages from another ESP chip (an 8266) located over 1 km away – all just using the Espressif radios - but that’s another story….
n.b. The forum software did not allow the usual .ino file extension for the ESP32 Arduino IDE code so I've just changed it to .txt !
My ESP32 code was developed using the Arduino IDE. I found and made use of an ESP32 DMA SPI library that was essential in getting this working without too much complexity on the P2 end – the relevant link to that is mentioned in the code comments.
To do this work I made a small PCB that has an ESP32 module riding piggyback on my P2-EVALB (the DipTrace schematic pdf shows the connections). The photo here is rather old – in current testing I’ve got the breakout PCB plugged into the P31..P16 headers on a P2-EVALB board, but just P19..16 are used for the 4 wire SPI bus and P20 for the LED string.
You’ll find lots of comments to explain what’s going on at either end of this SPI link. Once data is moved over to the ESP32 then you can send it off to the cloud or whatever else you so desire. The world literally is your oyster then !
I’ve been talking to this P2/ESP32 combo by sending messages from another ESP chip (an 8266) located over 1 km away – all just using the Espressif radios - but that’s another story….
n.b. The forum software did not allow the usual .ino file extension for the ESP32 Arduino IDE code so I've just changed it to .txt !
pdf
36K
Comments
He's used VSPI pins for the connection to the P2 while the HSPI pins are physically probably more convenient to wire to port B of the P2D2 but I read both these two ESP32 SPI ports are interchangeable and general purpose and can operate as master or slave so this wiring difference shouldn't matter (in theory).
Another use of these extra pin connections if SPI is not used, could be for SW controlled flow control between ESP32 and P2. This could become important at higher speeds over serial. I'm trying to figure out how fast the ESP32 serial port can be vs the 20MHz SPI RJSM achieved. UPDATE: UART might just be 5Mbps, so SPI looks quite a bit faster. I also read that SPI can clock up to 80MHz; the board signal integrity might start to become a factor then, maybe some series resistors are required for that performance.
https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf
By the way, I was reading about the internal pin muxing capabilities of the ESP32 and it looks useful. You can apparently remap GPIO pins so your might be able to run a second serial port over those same HSPI pins for example, if I read it right.
Hi Peter,
Could these be ordered with the ESP-WROOM-32U? Everything I do involves metal enclosures and so I need the external antenna.
@Mickster - Yes, absolutely as the modules are the same except for the antenna so I am just testing with this type for general dev work but some end use will call for an antenna.
Key will be to wire in the standard serial comm pins, the enable, GPIO0 and an optional SPI bus of which HSPI is likely the easiest, and that extra reset out GPIO pin to reset the P2D2 module. My suggestion in the P2D2 thread should hopefully help.
Most of the built modules do not expose all of the GPIO's that are available on the ESP-WROOM-32 module from Espressif that I believe you are using for P2D2.
I used the 4 VSPI pins - but if you'd rather access HSPI then you will use the GPIO's with the SPI labels in this diagram.
Looks like you share the SPI bus CLK and CS for the PSRAM with the ESP32 HSPI bus and have found a way to maintain QuadSPI capabilities to the PSRAM while giving the ESP32 its own data line. Neat. An alternative would be its own chip select and a shared IO pin but that relies on tri-state stuff working nicely. A side effect is the SPI slave in the ESP32 would always see the same data sent to it as the PSRAM, but it would respond if required on its own MISO line back to the P2.
Not sure why you included GPIO2 connection to the P2 and not just let the internal pulldown remain at logic 0, but there's probably a possibility of mapping ESP GPIO2 to U2RTS internally to this extra pin (assuming the IOMux can do this) which could then hopefully provide an option for the secondary serial interface to support full HW flow control.
Note : for U2CTS there is a small risk that if a P2D2 user is also using pin 9 of the P2 on their system board then it can prevent the ESP32 from booting via its flash which shares this signal.
Suggestion for a remote wifi reset control:
Add a reset output pin from the a free ESP32 GPIO on the ESP32 to the reset pin of the P2D2 via a diode (cathode to ESP). I'd pick one that is a RTC_GPIO as well, in case the board is in a low power mode and the internal ESP state machine controller might want to drive reset to reboot when the system is in a deep sleep state. You obviously shouldn't choose an input only pin from pin 4-7 on the module for this purpose and also not select one that pulls down by default or outputs PWM at startup. Something that either floats or pulls up during ESP reset would be good and the series diode is there to save us.
I found these links which are handy as they talk about pins you shouldn't use during boot etc.
https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
http://acoptex.com/project/9521/basics-project-076f-esp32-development-board-how-to-use-gpio-pins-at-acoptexcom/#sthash.SUQ3TEGK.4rQanDpo.dpbs
Both GPIO0 and GPIO2 can get used later after ESP32 boot for general status/interrupt signalling use (and probably even HW flow control if remapped in the IOMUX to RTS/CTS lines). So you could wire like this for example...
P6 - U2TXD
P7 - U2RXD
P8 - GPIO0
P9 - GPIO2
I disconnected P8 from GPIO2 although I just left an untented via right next to the header pad.
I gather your 18-bit LCD would be using P2..P7 then P10..P15 etc. I had left P0..P4 free for VGA but I could wire RXD2/TXD2 to P8,P9 and find another P2 pin for GPIO0 I guess. (Just noticed I hadn't disconnected P9, now that I know it's the internal boot Flash)
BTW - I forgot to attach the schematic but here it is. I also changed the CS to SRD3 which is normally the hold pin so that the PSRAM won't be affected.
You are right about the 18 bit LCD panel wiring, I skip the 2 LSBs of the first three bytes of port A, which can then be used for other purposes outside of video. So it would be useful for people who have parallel LCDs like this to keep these bits free, and put your optional second serial channel on P8 and P9 as you mentioned. GPIO0 is important to keep connected for programming, but if you've just remapped your HSS/MISO for the slave ESP32 SPI you could use that now freed pin P54 which would probably make things ideal and in most cases will keep all ESP connections contained on port B unless you choose to make use of an optional second serial channel. With a slave ESP32 SPI capability that channel is less likely to be needed, but people can still use it if desired.
EDIT: actually this wiring method only works if QSPI is never used with PSRAM when the SPI slave is used. Still okay though for dual/single SPI on PSRAM with an ESP32 SPI slave if it tri-states. It's a good compromise.
The no-diode reset approach is probably fine as long as we always code the ESP32 to never drive active high but only open drain low (so the reset switch doesn't short the ESP32 output). It just puts a slight software burden on all the future ESP32 developers, that's all. They'll all need to know to never drive it high with their P2D2s. GPIO33 looks okay.
Update: Actually going without the diode has an advantage in that the ESP32 can also sense the pushbutton switch and could take an action.
https://esp32.com/viewtopic.php?t=6269
I probably will need to think about all these signals in the morning but here is what I have at present. BOOT0 is connected to P10 as I'm not sure where else I could connect it yet.
So if it is not possible to send BOOT0 (GPIO0) back to port B, could the GPIO0 at least be mapped one of the two lower pins of the 8 bit group, that way I can still reprogram the ESP32 if the 18 bit LCD is fitted/operational. Personally I'd give up default secondary serial pins in my own application, which can always be custom remapped in ESP32 code to use GPIO0 for the missing serial pin anyway via the GPIO MUX if I ever need it. So this pin mapping would be far better for me:
P8 - GPIO0
P9 - U2TXD
P10 - U2RXD
Hopefully your P2PAL bottom layer has a little room for this slight signal order reversal by using a another via or so.
ps. Speaking of the bottom layer I guess you'll need to shuffle a few power traces/pads outside that diamond heat sink spreading pattern so it can bond to the P2D2 better without a shorting risk. Your gerber looks like it will all be exposed copper there (which will be good for heat spreading with solder paste or thermal compound).
I'm still looking at boot0 (re)mapping and perhaps a diode for the reset.
I wonder if the HyperRAM footprint pad size is ok? That reminds me, I still have to account for HyperFlash.
To @RJSM, I'm sorry we have essentially hijacked your ESP32 software thread here discussing all this P2D2 ESP32 stuff, and I do kind of feel bad about that, but if we manage to get a P2D2 with an ESP32 capable of a SPI link etc out of this it is probably a good thing for everyone. You've already proven how useful this will be for us too with what you are doing.
To keep everything safe it might be nicer to run all these PWM transient signals through a series resnet first before hitting the P2 if you had the space on your board but I can see that could be really tight on your P2PAL unless you fit one just under that PSRAM label somewhere. This might help HSPI operating speeds perhaps too given the ESP32 can have a SPI clock up to 80MHz. So maybe some small series resistors could allow faster bus operation like you already found with the SD cards?
Actually, I might hard-wire one of these modules to a P2D2 to make sure it all works. I just solder short lengths of wire-wrap directly to the pads.
If you can fit a resnet to stop any boot up PWM on HSPICS and HPSICLK and GPIO0 from messing up the PSRAM SPI bus signals or other shared Prop pin use whenever ESP32 is rebooted that will be nice, but P2 software can possibly try to workaround this if the ESP32 gets restarted while the P2 is already up just by not using PSRAM at this time, or delay using it from boot up until it would know the ESP32 is up.
If you can pass the two HSPIQ and HSPID signals through another dual resnet too that may allow tuning of performance for higher speed SPI one day like you did with the SPI bus for SD (to reduce reflections etc). I can see it is getting tricker to do this as track placement is tighter now but if it can be done that could be a good thing.
On the bottom layer, if the power tracks were spread further away from the diamond maybe it will help more heat transfer into your bulk copper plane. Even some extra via stitching up into the top layer bulk ground regions like below the SD card may help heat flow there faster as there appears a fair bit of free copper there (in relative terms anyway) and that MicroSD card shell might be metallic too. Hopefully you might get a little bit of room to play with that bottom layer once all components are positioned. It would be cool :-) if this P2PAL behaves very well as the P2 heatsink.