Xenomai RT SPI Driver for Blackfin
April 14th, 2007I am working on a Blackfin uClinux hardware project that requires a real-time SPI driver. I know that the RTDM community is looking to create profiles for various devices, but to my knowledge, nothing has been done for SPI controllers yet.
This driver is targeted at the Blackfin 537 running Xenomai 2.3.1. I have made some effort to separate the hardware specific bits from the main interface, but that was not my primary purpose. Also, the driver is targeted at custom embedded hardware where the definitions for each slave select are known at build time and is driven by actual board layout. The driver could be extended to allow configuration of each SPI slave via ioctls, but this was not a priority for me. The slave select configuration is in the device_config.inc file which defines an array of structures specifying the characteristics for each supported slave select. Slave selects are numbered from zero in the same order as listed in the device_config.inc file. Each slave select is exposed through RTDM as a device with a name of “rtspi%d”, where %d is the slave select number as listed in device_config.inc.
For the Blackfin, two types of slave selects are supported: “Native” and “GPIO”. Native slave selects map to bits in the SPI_FLG register and are listed on the spec sheets as SLAVE SELECTS. GPIO slave selects allow any available GPIO port to be controlled by the driver as a slave select. Since all native slave selects can also be GPIO pins, the entire driver could be configured solely with GPIO slave selects if desired.
SPI is a bidirectional protocol where sending and receiving is done simultaneously. The driver supports this by requiring that a call to “write” will initiate a SPI transaction and will also store the received results in a buffer which can subsequently be accessed through a call to “read”. On the Blackfin a single DMA channel is available for the SPI controller. The DMA can operate in either send or receive mode but not both. Because of this disparity, the driver does not use the DMA, which can be appropriate for typical, small SPI transactions. The driver could conceivably be extended with IOCTLS that could activate the DMA when a large one-way transfer is to take place.
This code is GPL’d and is freely available for anyone to use and extend. The current version at the time of this writing can be downloaded from http://www.rcode.net/blogattach/dist/rtspi-20070414.tgz. If there is any interest, I can post the code in a public SVN repository. Otherwise, recent versions can be obtained by emailing me.
In addition, I typically use the following program “rttran” to work with the SPI peripherals interactively:
/** rttran - Real-time copy.
* Provides a non-realtime -> realtime bridge to write data
* to real-time devices.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <native/task.h>
#include <rtdm/rtdm.h>
int process(int rt_fd, char** args) {
unsigned char *tx_buffer, *rx_buffer;
int buffer_size=0;
int loc, len;
int written;
char** cur;
// Count
cur=args;
while (*cur) {
buffer_size+