Hi Giovanni,
Thanks for responding. OK, it makes sense that perhaps a slave device would be more suited to a slave-specific driver interface. That way the master interface can stay focused on its purpose.
Preface -- some notes after writing the rest of this message
I apologize if I begin to ramble here, but I'm working through the thought process and the issues an SPI slave will have. In fact, I'm coming back to the top of the long message to write this preface and I'll say that I'm not convinced that an SPI slave is to best way to solve my multiprocessor communication problem. Now, SPI will certainly provide much higher transfer speeds that any of the alternatives, but it is so much messier to implement a high speed slave that I would prefer to avoid implementing an SPI slave if at all possible.Initial thoughtsFirst thing to consider in designing an SPI slave driver would probably be: how will it be used? What kind of usage is expected? The way in which the slave must behave might determine some things about the basic slave interface. In the simplest case, the slave might have pre-buffered an array of data bytes to send when the master initiates a transfer. However, most of the time the slave will need to take some action based on the first byte transmitted by the master.
This is where the issues arise. The speed of SPI is also the biggest issue. Well, potential speed, but at low speed there is little reason to use SPI. A fairly flexible but simple interface would be to have a single byte or probably a few bytes pre-buffered in the SPI hardware transmit buffer, and then have an interrupt handler that is invoked when the transfer has started -- the ISR can then take action and prepare to send the proper response. The problem is in the timing of how fast this interrupt can be executed and produce the response.
My intent was to implement an SPI slave device as a peripheral device to a main MCU -- the slave handling a specific task without burdening the main MCU, for instance to implement a wireless radio interface. The master would be able to send packets over the radio, and the radio slave would buffer received packets and make them available to the master. If it were implemented as an I2C slave rather than SPI, the clock stretching of I2C
really simplifies the protocol design and slave implementation. In an SPI protocol where the first byte from the master is a command, the slave must process this byte to produce the 2nd, 3rd, etc. bytes to send to the master. The slave must produce the response in less than one-half of a bit time, so the speed is severely limited. And, IMO
speed is the primary advantage of SPI over I2C.
Protocols that make the SPI slave's job easierSuppose that the SPI protocol can be dictated by us (we're not emulating an SPI EEPROM or some such thing). We could add some “busy†indication support to the protocol, so that the slave can take its time processing the first byte of the command. I think SPI EEPROMS do this. (BUSY, or conversely READY, flag could be provided as either in-band in the SPI protocol or out-of-band as a separate I/O pin, but let's avoid adding extra pins which would generally be an unnecessary complication.)
Suppose the first byte transmitted by the master is a command byte. The slave must respond with a 0x00 byte until it is ready to send the response, then it sends a 0x01 (“READYâ€) byte. The master sends the first command byte and continues clocking SPI transfers until it receives a 0x01 byte from the slave. Then the master knows that the next bytes transferred from the slave will are available. Continuing with the above example of a radio interface slave device, suppose the master sends a GET RECEIVED FRAME command to the slave. Furthermore, the first data byte sent by the slave after READY might be the frame length, after which the frame content follows. Whenever the SS# signal is de-asserted (SS# goes HIGH), the slave should reset its interface and prepare for a new transfer beginning with a command byte from the master.
SummaryNow the difficulty of implementing a robust SPI slave device is apparent. I think if we make some restrictions on the protocol such that the master can send a request, but the slave can indicate to the master when it's really ready, the SPI slave driver can be robust and not too complicated. A DMA channel configured to continually respond to SPI transfers with the “BUSY†flag (0x00 in the above example) until the application has a response ready, then the application can use DMA to transmit a 0x01 (“READYâ€) followed by the actual response data.
----
Alternatives to SPI for implementing a slave deviceThere are alternatives to SPI that do have drivers in ChibiOS already; they have their own advantages and disadvantages.
I²C:Advantages: + Slave implementation is robust with few protocol constraints thanks to clock-stretching.
+ Only two signal lines required to support many slave devices (or even multi-master).
Disadvantages:- Much slower than SPI. SPI can go easily to 12 MHz but I²C is limited to 400 kHz (1 MHz on NXP LPC1000 devices).
UART:Advantages:+ Slave implementation is straightforward. Slave transmits on its own time, not bound to a master clock.
+ Possible to take advantage of hardware flow control.
+ Multi-device bus support in STM32 (“Multiprocessor communication†in Reference Manual), supports 16 devices. Possible options: Address mark detection, idle line detection, or LIN.
Disadvantages:- Slower than SPI (but faster than I²C). SPI can go easily to 12 Mbit/s, but STM32 UART is limited to 3 Mbit/s, and also has 25% overhead due to start+stop bits.
- Requires stable CPU clock.
- Multi-device bus support may require extra hardware (AND gating all TX outputs from slave before passing to master RX input). Is this true?
---> Questions:
* Does ChibiOS/RT support STM32 multiprocessor communication mode?
* Is extra hardware needed to support multiple devices on the UART bus? I think the slave outputs must be ANDed before connection to master's RX pin. What about in LIN mode?----
I am wondering if perhaps SPI slave is too complicated to be worthwhile in most applications compared to using I²C or UART. The UART can achieve speeds that are sufficient for low-speed radio communication interfacing such as 802.15.4, particularly when the I/O is handled by DMA.
Thanks for taking the time to let me discuss this with you. Let me take the opportunity to say that I am really impressed by ChibiOS/RT's clean, orthogonal design and your attention to detail. Thanks to everyone else who has contributed too. I've been using only homebrewed code libraries with a simple scheduler of my own, though I've considered other RTOSes at length but have not found a suitable RTOS that satisfied me before. I'm tired of reinventing the wheel constantly, though, writing my own hardware drivers, concurrency primitives, software timers, etc. Now I am super excited about ChibiOS.

I feel more free to actually work on my
application itself, and just mess with low-level device-specific stuff in a few special cases.