How to use SPI from Linux userland with spidev

Revision as of 07:24, 6 October 2020 by Registered User (Fix comment and removal of echo based SPI writting)


  • How to use SPI from Linux userland? (Uses "spidev": SPI devices userspace API)

Once agreed, new page with correct title will be created and current one trashed}}


1. Article purpose[edit source]

Linux® SPI framework offers several ways to access to SPI peripherals. Among them, the spidev framework allows for easy control of a SPI peripheral straight from Linux® userspace.
Before going further in reading this document, reader might be interested in having a look at the SPI overview article. This article describes how to use SPI when the peripheral is assigned to Linux®.

  • How to configure a SPI device via the board device tree (example using "spidev")
  • How to perform data transfers in userland

2. SPI easy testing - loopback MOSI / MISO[edit source]

Short-circuit the MISO and MOSI lines of SPI bus to create a loopback allows the bus to receive the same data it is sending. This is interesting to execute quickly basic tests and to execute performance tests. On the On the STM32MP157X-DKX discovery board, MOSI and MISO signals are accessible via the D12 and D11 pins of the STM32MP157x-DKx_-_hardware_description#Arduino_Uno_connector.

3. Configuration (DT, kernel)[edit source]

In order to be able to control the SPI device from user-space, the "User mode SPI device driver support" must be enabled. Its configuration is explained in the SPI_overview#Kernel_configuration.
In addition to that, the device tree must be customized in order to expose the SPI peripheral via the spidev framework. Overall device tree configuration is explained in SPI_device_tree_configuration.

In our example of performing MOSI/MISO loopback on the STM32MP157X-DKX discovery board, the device tree stm32mp157a-dk1.dts[1] which already include the board skeleton for spi4 must be customized as followed:

  • Configure the PE11 GPIO as the chip select by using the cs-gpios property
  • Activate SPI controller by setting status "okay"
  • Add a spidev child node
    • Enable spidev by adding compatible "spidev";
    • Add a reg property within that node to indicate the address of the SPI peripheral exposed via spidev. (in case of loopback test, any address would work)
    • Configure bus speed when talking to the SPI peripheral by setting the spi-max-frequency property
&spi4 {
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&spi4_pins_a>;
    pinctrl-1 = <&spi4_sleep_pins_a>;
    status = "okay";
    cs-gpios = <&gpioe 11 0>;
 
    spidev@0{
        compatible = "spidev";
        reg = <0>;
        spi-max-frequency = <4000000>;
    };
};

4. SPI unitary tests using spidev_test[edit source]

The spidev_test tool, from the Linux® kernel, provides a test tool for performing tests via the spidev interface.

4.1. Compilation of the spidev_test tool[edit source]

The Linux® kernel spidev_test tool source code can be found under tools/spi[2].
This tool is not compiled by default when compiling the Linux kernel for the target board. It can be compiled independently: How to build Linux kernel user space tools and then installed on the target.

4.2. List the spidev options[edit source]

The spidev_test tool options can be listed:

 spidev_test -h
Usage: spidev_test [-DsbdlHOLC3vpNR24SItx]
  -D --device   device to use (default /dev/spidev1.1)
  -s --speed    max speed (Hz)
  -d --delay    delay (usec)
  -b --bpw      bits per word
  -i --input    input data from a file (e.g. "test.bin")
  -o --output   output data to a file (e.g. "results.bin")
  -l --loop     loopback
  -H --cpha     clock phase
  -O --cpol     clock polarity
  -L --lsb      least significant bit first
  -C --cs-high  chip select active high
  -3 --3wire    SI/SO signals shared
  -v --verbose  Verbose (show tx buffer)
  -p            Send data (e.g. "1234\xde\xad")
  -N --no-cs    no chip select
  -R --ready    slave pulls low to pause
  -2 --dual     dual transfer
  -4 --quad     quad transfer
  -S --size     transfer size
  -I --iter     iterations
  -t --txonly   simplex tx transfer
  -r --rxonly   simplex rx transfer

4.3. Example to transfer 32 bytes in full-duplex with loopback[edit source]

 spidev_test -D /dev/spidev0.0 -v
			spi mode: 0x0
			bits per word: 8
			max speed: 500000 Hz (500 KHz)
			TX | FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D  | ......@.... .................. .
			RX | FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D  | ......@.... .................. .

5. References[edit source]

  1. arch/arm/boot/dts/stm32mp157a-dk1.dts
  2. tools/spi , Linux® spi source code directory