Implementing SPI on an OMAP-based board design

Dmitry Pervushin, Texas Instruments

May 22, 2012

Dmitry Pervushin, Texas Instruments

What are the necessary kernel changes?
The SPI bus and USB, for example, are different. USB devices provide information about themselves and can be queried by the bus controller driver. SPI devices, on the other hand, cannot do this. The SPI master driver never has a chance to know what is connected to some specific CS# (and even know if there is something connected) unless it is provided with some information.

The board-dependent code does the registration by calling the function spi_register_board_info. It takes two parameters: list of devices connected and the size of this list. The example might look similar to the following:

static const struct spi_board_info panda_spi[] __initconst = {
       {
                      .modalias = "spidev",
                      .bus_num = 1,
                      .chip_select = 1,
                      .max_speed_hz = 1000,
                      .mode = SPI_MODE_1,
        },    {
                     .modalias = "ds3234",
                     .bus_num = 1,
                     .chip_select = 0,
                     .max_speed_hz = 400000,
       },
};

Also, register this spi_board_info array in the function omap4_panda_init:

spi_register_board_info(panda_spi, ARRAY_SIZE(panda_spi));

In this code snippet, two SPI devices are registered. The first device is something generic attached to CS#1 on the SPI bus 1 (McSPI1) controlled by the “spidev.” It has a maximum speed of 1kHz, which is just for the sample because the real speed can be up to 48MHz.

The second device is connected to CS#0, has a maximum speed of 400kHz (enough for RTC) and is controlled by the “ds3234” driver. It is a good “SPI functional device driver,” and is doing all the work to exchange data over the SPI bus.

Working with a device attached to the PandaBoard
First of all, because the kernel has been modified, it has to be recompiled. It is a good idea to make sure that all the necessary options are switched on:

CONFIG_SPI = y
CONFIG_SPI_MASTER = y
CONFIG_SPI_OMAP_24xx = y
CONFIG_RTC_DRV_DS3234 = y
CONFIG_SPI_SPIDEV = y

The last option can be set to “m,” meaning this will be a separate module. In this case, do not forget to update the modules directory. After the kernel is compiled and started, the following messages will appear:

ds3234   spi1.0:   rtc core:   registered   ds3234 as  rtc0

This means that the ds3234 driver has been attached to the SPI device, and exposes its RTC interface via /dev/rtc0. Now one can run any tools to access the RTC (hwclock is a very useful utility):

# hwclock   –show

You can also access the device via the spidev interface, which allows userspace application to send/receive bytes on its own, for example, using this script:

import  os,  sys

def spidev_test(devnode):
           #
           # very simple. no exception handling, just five steps:
           #

           # 1. Open device
          spi = os.open(devnode, os.O_RDWR, 0777)

           # 2. Write single zero byte
           write_bytes = "\x00"
           w_res = os.write(spi, write_bytes, len(write_bytes))
           if written != len(write_bytes):
                         raise Exception("Wrote less bytes than requested")

            # 3. read 8 bytes back
            rd = 8
            rd_bytes = os.read(spi, rd)
            if len(rd_bytes) != rd:
                         raise Exception("Read less than expected")

            # 4. print the result
            print ["%x" % ord(rd) for rd in rd_bytes]

            # 5. close the handle
            os.close(spi)
if __name__ == "__main__":
           spidev_test ("/dev/spidev1.0")
           sys.exit(0)
else:

            print "How do you want to use spidev-test?"

The script will try to send a zero byte to the device, and print the response of 8 bytes. If one attaches the spidev driver instead of ds3234 to the DS3234 device (in the code snipped above, just replace “ds3234” with “spidev), the output might look as follows:

# python spi-sample.py
['5', '10', '12', '2', '1', '5', '12']

This is just a sample to demonstrate the SPI exchange. Parsing of this data is usually done by the ds3234 driver. However, it might be a good starting point to start development of one’s own protocol driver, especially if something new and unknown was connected to the Linux kernel.

< Previous
Page 3 of 4
Next >

Loading comments...

Most Commented

  • Currently no items

Parts Search Datasheets.com

KNOWLEDGE CENTER