RTEMS SPI Implementations

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Jan 31 06:46:53 UTC 2019

Hello William,

On 31/01/2019 05:28, William Busacker wrote:
> Hi all,
> Told myself that in the new year I'd finally get around to working on 
> the Raspberry Pi's BSP some more, but before I start I have a couple 
> questions I'd like to have answered, particularly about SPI. Not sure 
> if this belongs in the devel list, figured users was a good place to 
> start.
> Its been talked about before how the RPi SPI driver should be 
> re-written at some point. Between the interrupt mis-handling, file 
> descriptor bugs, and performance issues, I think there is enough cause 
> to do a rewrite, but I'm not sure how exactly it should be done. 
> Section 10 of the BSP and Driver guide blanket statements that the SPI 
> bus drivers should use the SPI bus framework (dead link, likely lost 
> in the cpukit move) and specifies that the API needs to be Linux 
> user-space compatible. I understand the desire to be as linux-y as 
> possible to make developing in RTEMS much more natural for those not 
> used to real time systems, but in this case I'm not sure if it is the 
> best move. Doubly so for the Raspberry Pi. (As I'm interested in the 
> RPi in particular I'll be referencing that specific BSP forward)
> Since the RPi is marketed as an "entry" device for hobby electronics, 
> it is either a gateway device or is being upgraded to from an Arduino. 
> Brand new users trying to learn about SPI online (Sparkfun's blog post 
> being very popular) and people coming from Arduino will be used to the 
> model of 8/16 bits being traded with cs active end point. Put data in 
> buffer, send/receive, read back, or do it all at once with a single 
> function call. Arduino handles this flow quite nicely; configure an 
> SPISettings object, "begin" transactions, do as many .transfers() as 
> you want then when you're done "end" transaction. Granted Arduino 
> purposefully simplifies things, it still is very representative to 
> what actually occurs in hardware and is easy for a newcomer to grasp. 
> Linux's SPI user-space driver introduces ioctl which in and of itself 
> is complex and then makes all interaction through a file descriptor, 
> limiting the user to either read /or/ write ability, not both at the 
> same time.
> For the RPi, the vast majority of SPI examples are either in Python 
> (which does use spidev) or in C using either the wiringPi or BCM2835 
> libraries. Both the C libraries provide functionality more akin to 
> Arduino's solution than the Linux kernel solution.
> There are also issues in operational terms of spidev.
> - Full duplex is impossible without digging into ioctl
> - Everything must be synchronous (sitting in its own task can help 
> mimic interrupts but may not be the best solution)
> - spidev doesn't offer slave select polarity control
> What I was thinking as an alternative is something close to how the 
> BCM2835 
> <https://www.airspayce.com/mikem/bcm2835/group__spi.html#ga0127eab1b6c3f8bf127bdac474fdc0f9> 
> library controls SPI. The library can't be directly put into the RTEMS 
> project since it relies on Linux for other things, but its general 
> approach is something I feel is a much better solution than using 
> spidev. It grants far more insight into what the bus is doing as well 
> as much tighter control over the device. I realize this means more 
> documentation (something I also plan on attempting to tackle for RPi 
> at some point), but I think thats a worthy tradeoff. Especially since 
> it seems spidev was designed to fit Unix's 
> I'll-get-around-to-it-when-I-feel-like-it approach to device control, 
> compared to an rtos's Its my bus and I need it now!

Yes, ioctl() is a horrible interface, but the struct spi_ioc_transfer 
transfer mechanism is good from my point of view. It offers full-duplex 
transfers, per transfer settings and you can combine multiple transfers 
in one request. The driver ensures that the SPI bus is only used for one 
request at a time. If you like, then you can hide the ioctl() in a 
wrapper function to get a type-safe API. Maybe you can also add another 
IO control to accept asynchronous requests with a completion callback.

The APIs using multiple function calls to change settings and do a 
transfer have all potential locking issues. Using a request with 
multiple transfers has the benefit that you can issue the next transfer 
within the interrupt handler. This avoids task switches.

Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber at embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.

More information about the users mailing list