The SPI slave driver topic

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
Post Reply
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

The SPI slave driver topic

Post by colin »

Is it possible to act as an SPI slave device? From a quick look at os/hal/platforms/STM32/spi_lld.c, it looks like

Code: Select all

 /* SPI setup and enable.*/
  spip->spi->CR1  = 0;
  spip->spi->CR1  = spip->config->cr1 | SPI_CR1_MSTR | SPI_CR1_SSM |
                    SPI_CR1_SSI;
  spip->spi->CR2  = SPI_CR2_SSOE | SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN;
  spip->spi->CR1 |= SPI_CR1_SPE;

forces the CR1.MSTR bit to be set. Also, I see no mention of SPI slave mode in the documentation, although it also doesn't mention the fact that only SPI master mode is supported.

Is slave mode supported? If not, I suggest that the documentation be updated to state that only SPI master mode is supported.

How much work would it be to add support for slave mode if it's not yet supported? Will it affect a lot of the SPI code and interface, or could it be a simple change? There are some interesting issues when acting as a slave, since the first byte to send must be pre-loaded into the SPI hardware buffer (unless there is special support for the Slave Select signal triggering an interrupt which would then load the SPI hardware transmit buffer, but that would require special slave-select timing from the master: not a huge deal in some cases, but certainly suboptimal).
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: STM32 SPI slave support?

Post by colin »

P.S. I really hope SPI slave support can make it into the 2.4 stable release! I would love to help contribute code for such a feature, but I'm brand new to ChibiOS/RT and just learning the basics of its structure and usage. I'll do what I can. :)
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32 SPI slave support?

Post by Giovanni »

Hi,

The current driver is designed as master-only, a slave SPI driver would be a separate driver model and currently it is not planned so inclusion in 2.4.0 is... unlikely.

However you may add a custom SPI-slave driver to 2.4.0, the two things are not incompatible. A common misconception is that you can only use the drivers included in the OS, that is not the case :-)

Let's discuss the hypothetical SPI-slave driver in this thread.

Giovanni
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: The SPI slave driver topic

Post by colin »

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 thoughts

First 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 easier

Suppose 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.

Summary

Now 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 device

There 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. :D 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.
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: The SPI slave driver topic

Post by colin »

Hi Giovanni,

In light of the potential complexity of an SPI slave, I concede perhaps there are more important things to get into release 2.4. Implementing a general-purpose and robust SPI slave driver might be a bigger task than I originally though.

Regards,
Colin

Open question: Does anyone else have a need or desire for an SPI slave driver?
In my case, I have the flexibility to use any STM32 communication interface, but SPI is just the fastest so it's best for graphics I/O and network communication.
kgysmits
Posts: 20
Joined: Tue May 03, 2011 10:16 am

Re: The SPI slave driver topic

Post by kgysmits »

I was just checking for a SPI slave driver, and found out there isn't one. I was planning to use a STM32F4-DISCOVERY to interface with an Arduino Uno (for education purposes). The STM32F4 would interface with 3 high resolution magnetic rotary encoders, 6 analog input (strain gauges) and PWM output to linear actuators.

Since the Arduino only has one serial port and it's used for interfacing over USB-CDC, that's not an option.
I have never used I2C before, so maybe that's an option too for this application.

So yes, I would use an SPI slave driver if available.
Since having the SPI slave process the data of the last transfer before the next command is sent is crucial, I will look into I2C first and see how that goes.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: The SPI slave driver topic

Post by Giovanni »

I am really embarrassed that I missed the mega-post above from Colin... sorry for that.

---> 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?


The UART driver should be able to do this, may be with small changes.

About the SPI slave driver.

I agree with the point Colin made, it is difficult to design a generic SPI-slave driver because time constraints. I think that making a driver that just expects to receive N bytes from the master would not be much useful.

Anyway, the important thing is to examine use cases and understand the requirements for such a driver.

I would start from understanding what is needed to implement an SD/MMC card with SPI protocol. Let's look at that problem from the slave point of view, there is command processing and data transfer within a single SPI transaction. The protocol seems to be designed in a way that the SPI slave driver continues to send FF automatically if the internal thread is not yet ready to send data.

Thoughts?

Giovanni
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: The SPI slave driver topic

Post by colin »

Giovanni wrote:I am really embarrassed that I missed the mega-post above from Colin... sorry for that.

No problem, this has turned into a brainstorming session as it's not so simple as it first seemed.

Giovanni wrote:About the SPI slave driver.

I agree with the point Colin made, it is difficult to design a generic SPI-slave driver because time constraints. I think that making a driver that just expects to receive N bytes from the master would not be much useful.

Anyway, the important thing is to examine use cases and understand the requirements for such a driver.

Yeah, it will be best to implement one or two specific applications first, and see if common patterns emerge, and enable distilling a useful driver design from it.

Giovanni wrote:I would start from understanding what is needed to implement an SD/MMC card with SPI protocol. Let's look at that problem from the slave point of view, there is command processing and data transfer within a single SPI transaction. The protocol seems to be designed in a way that the SPI slave driver continues to send FF automatically if the internal thread is not yet ready to send data.

That's a good idea: Look at a widely-implemented protocol and see how they solve the problems. And it's implemented using an ARM7 core in the flash interface controller in many SD cards, so possibly the SD card controller, being implemented on a standard processor architecture using firmware (rather than pure hardware) has to address many of the similar problems we are thinking about, compared to a simpler more hard-wired chip like an SPI EEPROM or ADC.

The SD/MMC SPI protocol slave keeps sending a byte with the BUSY bit set until it is finished working. That is the kind of simple idea I thought a driver could implement generically, but once again it might be too specific--but sometimes you are interfacing two microcontrollers and you do have control over the protocol, so you can design the protocol to make the jobs of the firmware easier and more robust.
Post Reply