I'd like to hear some suggestions how you have implemented a SPI slave with a microcontroller.

I need to replace a current slave chip with a MCU and be mostly compatible with it so the master does not really see any difference to the original slave.

Basically the SPI hardware in microcontrollers can use blazing-fast SPI clocks to transfer a byte, but most microcontrollers don't have any DMA capability so each byte must be received in the SPI data interrupt.
Sometimes, the slave MCU must serve other interrupts and so it has a varying response time to SPI data interrupt. So the host cannot send bytes back to back or the slave will miss them if there is not enough time between each byte transferred.

Fortunately I can use one extra GPIO pin for syncronization, in the interrupt I first set a pin to indicate "slave busy do not send any more" and when the byte is fetched from SPI hardware and stored into buffer, I set the pin to indicate "slave ready for more stuff" at the end of the interrupt. I know some DSPs have this kind of extra wire for busy indication as well.

Then there is also the problem of SS or CS. The SPI hardware will handle the SS so that I get bytes when it is low and everything is ignored when SS is high. But how should I detect where SPI frames/packets start/end? Mostly the slave must execute commands sent to it after the SS goes high so it knows the transmission was complete and it can be executed and the next received byte will be the first byte of the next packet. So have you also connected the SS pin to external interrupt pin to generate interrupts when SS pin goes high (or low, whatever), or does some microcontroller have SPI hardware to handle the SS in some kind of interrupt too?

Then there is the problem of the slave sending responses back to master. If the first byte of packet signals whether the command is a read or write command, then the response byte must be loaded before it is transferred back. Now, the host could read any amount of bytes as a response so how will SPI hardware usually handle such a case if a byte is loaded to SPDR in SPI interrupt, but never transferred, and then as there is SS going high interrupt to signal end of transmission, I have to reload SPDR again so that the first byte in the next packet going back to host is not garbage from previous read. Will the SPDR write update the shift register if it is loaded two times or does it ignore the second write, setting some overrun status bit?

You will have a finite time to respond to /CS on a GPIO pin. e.g. a PCINT interrupt.

You should preload SPDR with the reply value before the Master starts the next SCK sequence.

If you respond to /CS with an interrupt, you can transfer the data efficiently by polling. If you use a SPI/USI interrupt, this will limit your effective speed.

So you will never be able to do a drop-in replacement for a hardware chip. You will have to specify the /CS timing. This is fine if you have control of the Master. No good if the Master has been programmed for the hardware chip timing.

In all honesty it's not THAT hard to emulate a SPI slave, and it's probably easier to do by bitbanging on interrupts. Connect CS to two external interrupt lines, to detect high level and low level. Connect the CLK line to a timer input, and MISO and MOSI to two GPIOs. When you detect CS low, start sampling bits on timer interrupts, either on rising or falling edge depending on clock polarity. If you want full duplex operation, you also clock out bits on MISO on the same interrupt. Use two buffers, one for input one for output. All you need to do for operation is fill in your buffers and the interrupts do the rest.

In concept, that is true. BUT - to emulate a hardware device with NO changes in the master is really hard. That is because a hardware SPI slave can load registers much faster than an MCU can do in software. The master likely does not even pause enough between bytes to service an ISR!

In concept, that is true. BUT - to emulate a hardware device with NO changes in the master is really hard. That is because a hardware SPI slave can load registers much faster than an MCU can do in software. The master likely does not even pause enough between bytes to service an ISR!

Jim

I guess it depends at what speed you operate the link, but let's say 1MHz. The port registers themselves are 1-byte DMA's. I doubt you would have any problems as long as you keep the delay smaller than a half-bit. You could always just use the internal SPI port's shifter for MISO and MOSI and operate it manually.

I agree with Hugoboss.
So the main question is what is the SPI speed of your master?
And then take it from there.
Perhaps the low level has to pull for data from the other interrupt (I don't know what it is but I guess read adc , change channel and start new convertion).

As the chip would not be running the analog section, or the eeprom, I would expect that at least within a temperature range around room temperature, (i.e. no temperature extremes), one could easily over clock the XmegaE5 a bit, if needed.

Obviously if it is a commercial product, mission critical, or needs to function reliably at temperature extremes, then picking a faster micro, if needed, would be the solution.

Thanks everyone for ideas, I had other issues keeping me busy and away, I apologize.

Indeed the replaceable chip is an MCU which has SPI but it is suboptimal and has all kind of issues, so I am seeking how to do it better/easier if possible. Otherwise I will just clone it to another MCU (faster, larger).

DMA is certainly one way to do it better, however the SPI "packets" are of variable length so it is not known which is the last byte until CS rises and it generates an interrupt. Maybe DMA could work with just large enough buffer size. But with DMA it is not possible to wiggle the BUSY pin to host as handshake as it is with SPI receive interrupts.

SPI clock speed to this slave would be about 1 MHz, but this is not only slave so there will be up to 8 MHz clocks while this device is unselected. This should not be a problem, as it is unselected.

The MCU has to manage about a dozen other slave chips as well so it can't sit and poll SPI traffic when it sees CS goes low. Hmm this does deserves a second thought and I might try that.

And there is a BUSY signal defined so this SPI slave MCU can request delays between bytes and packets if necessary (the previous slave was also MCU).

The extra CPLD/FPGA as an interface is a nice idea as well. Maybe in the next design I will route everything through one so it can do tricks between MCU and The Real World like handling the BUSY handshake pin.

The MCU has to manage about a dozen other slave chips as well so it can't sit and poll SPI traffic when it sees CS goes low.

Why not in that case it's the master, (As long the routine is fast). The main thing is that you can have the SPI receive data by it's self so you under the transfer only look at byte level, (and the CS line).