RFC: extension of libi2c to support SPI aswell
Robert S. Grimes
rsg at alum.mit.edu
Wed Sep 5 13:39:37 UTC 2007
Hope you enjoyed your time off!
Thomas Doerfler wrote:
> Now I have the task to support an SPI bus as well and I think libi2c
> only needs few extensions to also support SPI devices. The differences
> are rather small, so I want to avoid copying the code into a separate
> libspi.c. Before I really start, I would like to get some feedback from
> the list.
Interesting approach... I can't really make any comments on your
specific suggestions as I am not at all familiar with libi2c, but you
have captured some of the important issues. IIRC I2C has a few
predefined clock frequencies and an addressing scheme, which is of
course in contrast to SPI. So it is important to keep the clock rate
and phasing info around on a per-device, as you've already mentioned.
However, there is another aspect that you haven't mentioned, and that is
how the chip select signals are used. Unlike I2c where the address
information is part of the transaction, the approach taken by SPI is
much simpler - a chip select is used for each device to specify which
should respond to the master. The painful aspect of this is that
devices use the CS in very different ways. Here are a few examples that
I'm currently using
1. The Analog Devices AD7490 (a nice little 16-channel, 12-bit A/D
converter) actually uses the CS both to frame a fixed-size 16-bit
transfer, but also initiate the A/D conversion. So for this device, the
CS must go active, then 16 clocks along with data, and then the CS must
2. The Ramtron ferro-electric non-volatile memories
uses the CS signal to frame a transaction, where a transaction consists
of a command by followed by a variable number of bytes. For example, a
read or write operation consists of a read opcode, followed by two bytes
of address, followed by one or more bytes of data; the number of bytes
is actually unlimited, as the device will wrap around if necessary. So,
the read or write operation is terminated not by a predefined (by the
chip) number of bits, but rather by the CS signal.
3. The Maxim MAX6957 is even crazier; while it is basically 16-bit
transfer oriented, multiple devices can be daisy-chained to appear as a
Nx16 bit wide device, hence requiring the CS to frame that sequence!
So the AD7490 uses a strict, constant 16-bit word transaction, while the
Ramtron devices use a variable number of bytes per transaction. So it
is important to allow flexible handling of the CS signals in order to be
able to communicate with these very different devices.
Another issue that will be important to those using various Freescale
CPUs that include the QSPI peripheral is the ability to either use the
supplied CS signals (typically 3 or 4) directly, or as a selector using
an external decoder to select one of 2^N-1 devices.
On another project, I did some investigation into how Linux does this,
and the newer model seems to address these issues, at least in theory.
I don't know if their approach is overkill or not; perhaps someone who
has used it can comment?
As for me, I need to use quite a few SPI devices in my current project,
specifically the AD7490, Ramtron FM25L256, a custom CPLD (probably will
use a fixed-size transaction as wide as 64-bits, and a SD flash card, so
I am quite interested in this effort. As you know, Thomas, I'm using
the Xilinx Virtex-4 devices, and I intend to use several of the opb_spi
peripherals per V-4, plus a custom adaptation that is essentially an
opb_spi16 - a 16-bit wide version. So I certainly could work on the
low-level, hardware-specific parts for the V4 chip.
Thanks for bringing this up, as I've found the SPI a very convenient
means of interfacing to a wide variety of peripherals, and a suitable
driver is a great addition to RTEMS!!!
More information about the users