All of my experience with SPI to date has been effectively half-duplex: the Master sends the known-size command (ignoring the data received from the Slave), then when it receives an interrupt from the Slave it re-starts the clock and sends known-sized garbage and receives the known-sized reply.
I am looking at embedding the XBee SX into a project, and since the MCU only has a spare SPI port I’d use that. So I read the docs and noted the diagram and description here:
https://www.digi.com/resources/documentation/Digidocs/90001477/Default.htm#reference/r_full_duplex.htm
SPI is inherently bit-synchronous; the byte boundaries are not explicit, but the start of transmission or reception implicitly defines them - when operating in half duplex. However, the above full-duplex description implies that the XBee can start transmitting on any bit boundary, not on a multiple of eight. It indicates that it has started by asserting nATTN, and finishes by de-asserting nATTN. Indeed, the above diagram asserts nATTN after the 5th clock. (At first I thought that nATTN was effectively an IRQ from the XBee to say that it had data, so please start clocking. But the above diagram explicitly shows this is not the case.)
This post https://forums.digi.com/50914/xbee-wifi-s6b-spi-bug seems to describe exactly this phenomenon. The poster gives an example of the 0x7E start byte being shifted as 0xFC, since byte boundaries were assumed.
That post also alludes to the other implication of the above: how many clocks should the Master send? It can’t send just the number sufficient to clock out its request: the XBee could have started to reply, so the Master needs to keep clocking until the Slave has finished. Again, the above diagram shows exactly this, with the Master still sending garbage after it has finished, and not de-asserting nSSel until the Slave is done.
Given that the API is not fixed-size (although each individual command’s response may well be, but that’s not explicitly stated), and that no other SPI implementation in my experience uses a signal like nATTN to “bracket” the Slave’s reply, it appears as though I cannot use the MCU’s SPI hardware. I’ll have to software bit-bang the interface, examining and tracking nATTN on every bit to determine if the XBee is replying or not, shifting each data bit manually since they’re not on byte boundaries, and keeping nSSel asserted and clocking until the Slave is finished.
I might be able to use the SPI hardware if I tell it to expect a huge receive. Either:
- The transmission finishes without nATTN, in which case I abort the receive;
- nATTN is asserted during the transmission, and I reset the Receive side mid-byte(!), then when nATTN is de-asserted I again abort the Receive.
Either way, no DMA is possible!
Or have I completely over-thought all of this, and of course the XBee’s SPI is byte-oriented, the above diagram notwithstanding?
With thanks for any information,
John