Teensy 4.1 SPI as master + slave?

tjaekel

Well-known member
Teensy 4.1 SPI (as master) works fine (signals come out).
I have read: "only SPI master is supported".
But I would need also a second SPI as SPI slave.

Does anybody have a SPI slave implementation (at best with using DMA) for the Teensy 4.1?

Why do I need?
I want to connect a "Device Under Test" (DUT, external board) via SPI. But with a long cable,
the SCLK is "out of sync" on the MCU when receiving. I want to "compensate the round-trip delay" by using a DUAL-SPI approach:
- on device as SPI Tx (only), as master
- a second SPI Rx (only), as a slave
- the SCLK (clock) is fed back from far-end (external board) to the slave Rx, so that the delay caused
by the cable, the response delay on external chip... is "eliminated", the SLCK on Rx is delayed in a similar way as the cable and far-end chip would do
(so that SPI Rx is "in sync" with SCLK)

Therefore, I would need a second SPI peripheral, but running in slave mode.
How to do? How to modify the code...? Or: do you have it already?
 
How long a cable - SPI is meant for short distances only. You may need some signal conditioning to get it to work reliably long-distance.
 
Hi MarkT,
I know, SPI is synchronous and cable length matters.
The issue comes with "synchronous": it means: the SPI Rx uses the same MCU internal SPI clock to sample the MISO line.
So, any delay on external, e.g. due to cable length (propagation delay) plus the internal delay on external SPI device (chip needs a bit time to drive MISO),
results in: with fast SPI clock, the MISO signal is not in sync anymore with the (internal) SCLK clock (at the MCU side). It limits the maximum SPI clock you can use.

But this issue can be "fixed": if the SCLK signal is "sent back" from the far-end side (loopback the SCLK from external device), or you add a delay line in SCLK clock
going back to MCU SPI Rx...
it can compensate the cable length ("round trip delay") as well as the internal delay of external SPI chip (which delays the MISO due to internal logic there).
You just need separated SPI Tx and SPI Rx (where the clock comes back to the slave device).

It needs just to decouple Tx and Rx: if Rx is a slave device which gets the "SCLK reflected back" it stays much more in sync on MISO in relation to the SCLK (on MCU with a SPI Rx).
The problem with the "round trip delay" is this "synchronous nature" of SPI: SPI device uses the same MCU internal SCLK to sample MISO signal.
With two SPIs, one is Tx (as master), the other one an Rx (as slave) - it increases the maximum SPI speed and make the cable length pretty independent.

So, "how to use a SPI slave device" on Teensy 4.1?
(how to add code to run a second SPI in slave mode?)

Remarks:
It works fine on a STM MCU (called "DoubleSPIder").
See also this as the related "idea": https://www.ti.com/lit/ug/tidued8/tidued8.pdf
This approach is very helpful if you want to add line drivers (here, e.g. using LVDS signals) which contribute even more to the "round trip delay".

I need this "longer SPI cable" because the SPI chip (as Device Unter Test) is placed in an oven (climate chamber) but all the test vehicle hardware (MCU)
has to stay outside (not crashing due to test conditions).
 
A bit of progress:
1. I would need also a SPI Tx running in DMA mode (as asynchronous, not blocking the receiver. Rx complete is the criteria).
This works already (thanks to TsyDMASPI)" I can generate SPI in DMA mode.
2. But this SPI slave, only this SPISlave_T4 - https://forum.pjrc.com/threads/66389...ht=spislave_t4 - is available on Internet,
is so "strange" (and it does not work at the end):
- it loops inside ISR (it stays in ISR until "frame complete" flag comes)
- and very slow (2 MHz SPI fails completely, 1 MHz gives wrong order of bytes): obvious: it does a Serial.print() inside ISR:
this slows down to the UART speed and using USB VCP, it degrades the SPI Rx speed so much: so, the max. SPI Rx slave performance is
slower as the Serial speed. (who is doing such one?)

But OK, a good starting point to implement SPI Rx as slave (esp. how to configure MCU and handle INT).
 
You've still got to deal with signal conditioning, the Teensy can't easily drive ~100 ohm transmission lines (twisted pair, ribbon cable, etc) directly, and if the cables are not terminated with their characteristic impedance you'll get ringing and reflections, possibly double-clocking. Of course shorter cables can be treated as lumped capacitance if the delay is less than the rise/fall times.

You might want to try a destination matching network of 220 ohm to Gnd and 220 ohm to Vcc, giving 110 ohms biased to half Vcc - that's the easiest to drive from CMOS and is a good match to twisted pair like CAT5/CAT6 - it still wants to pull +/-15mA from the source of the logic signal, so decent buffers are needed really, but a simple 110 resistor to ground would want to pull 33mA, which is beyond most logic buffers.
 
I am familiar with serial and parallel line terminations, impedance issues, ringing, signal integrity etc.
Even for using LVDS (with line drivers, using a twisted pair CAT5 cable - I did on other setups - it results still in the issue to have SPI Tx and Rx separated (all the delays caused by line drivers must be compensated,
back to the main topic... LOL).

I made progress:
- I could fix issues in the SPISlave_T4 code - works fine now as expected (enabling and handling for "Frame Complete Flag" (FCF) was not correct, the ISR was not optimized for speed)

Just: it works just up to 22 MHz (now, after removing all these Serial.print() calls): a master driving faster starts to fail (wrong order or number of bytes received).
Still not fast enough for my purposes (DUT has 24 MHz, so I need 30 MHz working properly).
(it might be a clock config issue, e.g. SPI slave peripheral clock inside MCU is too slow (to large clock divider), or INTs come too fast...)

I found also in NXP RT1062 reference manual:
For a SPI master, you can select a "delayed SCK" for the Rx side (page 2969, "48.3.1.5 Clock loopback"). Even the amount of delay is not configurable, but it might help to deal a bit
with the "round trip delay" (because it adds a typical "gate delay" for the Rx FIFO). Cool! (never seen before on other MCUs, it will help for sure, a bit)

Clock_Loopback_RT1062.jpg

I have attached my (complete) code for SPI Slave (based on SPISlave_T4) here, as ZIP.

Thank you all for the hooks to let me keep going.
 

Attachments

  • SPISlave_T4.zip
    2.9 KB · Views: 28
Back
Top