Timing problem on Sharc SPI in slave mode

I'm using one of the SPIs on a 21489 Sharc for communication with a microprocessor. On the Sharc the SPI runs in slave mode. On rare occasions, when the master asserts CS/ just as the Sharc is about to write a value into the TX register, the value is lost: the SPI transfers a zero word instead. I'm writing the value only if the TXS is 0, of course. But it seems there is a race condition under which TXS cannot be relied on. The HW Ref Manual 1.1 describes this (pg 16-22, under Transmit Collision Error), but not well. For instance, what does this mean? "In this case TXS is not set and attempts to send new data and it isn’t clear if this write to TXSPI takes place when the load to the shift register is occurring (in other words a TXCOL condition)"

In any case the documented workaround (if TUNF is set, don't rely on TXS, but rather wait until SPIF goes low before writing to the TX buffer) does not seem to work. TXCOL still gets set, and the data value is lost, replaced by a zero on the SPI bus.

Is there any more detailed info that would help me develop a workaround? For instanced, what is the timing of TXS, TUNF, TXCOL and SPIF? When is SPIF cleared? Is there any example code that illustrates how to use this workaround?

Of course I don't expect my data to go out on the bus if I don't put it in the TX register before the CS/ goes active. I expect the SPI to send zero in that case (because my SENDZ bit is high). And if the SPI hardware was working properly this would not be a problem - my software would check the TUNF bit, see that it's high (the TX underflowed) and then wait until TXS is low (TX buffer empty) and write the byte then. (The SPI bus would then transmit all my bytes, possibly with some zeroes interspersed, which is OK). The problem is that TUNF and TXS don't work as expected. The HW Ref Manual says as much on pg 16-22. But the suggested workaround does not work either. I'm hoping that there is a way to make SPI Slave mode work reliably without imposing artificial timing constraints on the SPI master. Any ideas?

As the document suggests, To avoid the TXCOL condition, programs should write to TXSPI well before the load to the shift register takes place. This can be done by writing to TXSPI whenever TXS is cleared and refrain from writing to TXSPI when TXS is set. For slave mode this means that data should be in TXSPI before the first SPI clock edge (or the negative edge of device select) occurs.

However, a potential case of TXCOL arises when there is a TUNF condition. To be absolutely safe, when a TUNF = 1, write to the TXSPI register as soon as SPIF goes from 1 to 0. This ensures that TXSPI is written into well before the next load to the shift register takes place.

There is an undefined behavior when the core or the DMA is writing to TXSPI at the moment that data needs to be loaded into the transmit shift register. From reading between the lines, it looks like the TX shifter sees no data in TXSPI when the transfer happens and therefore transfers either old data or zero depending on SENDZ. The data that is written might actually end up in TXSPI, but if TXS is not set it will never be sent. It seems like this is a bug in the hardware that could have been avoided with a bit of logic by the designer.

However, since that's the chip we have, you need to avoid the possibility of triggering the anomaly.

If you are OK with random zero bytes in your data stream then you could simply fill TXSPI whenever you receive a transmit buffer not full interrupt. This will assure that you are not writing to TXSPI when data is being moved to the TX shifter, since that's what's triggering your interrupt.

If you can only tolerate a zero byte at the beginning, but don't know when the host is pulling CS/ low then you could wait for the underflow error interrupt, which would get triggered if there is no data and the first transfer has started and then start pushing your data out.