- Last edited 6 months ago ago
This article gives basic information about the Linux® SPI framework and STM32 SPI driver installation. It explains how to use the SPI and more specifically:
- how to activate the SPI interface on a Linux® BSP
- how to access the SPI from kernel space
- how to access the SPI from user space.
- 1 Framework purpose
- 2 System overview
- 2.1 Component description
- 2.2 API description
- 3 Configuration
- 4 How to use the framework
- 5 How to trace and debug the framework
- 6 Source code location
- 7 References
1 Framework purpose
The Linux kernel provides a specific framework for SPI protocol support. The SPI (serial peripheral interface) is a synchronous serial communication interface used for short distance communications, mainly in embedded systems.
This interface was created by Motorola and has become a de facto standard. As it is not defined by a consortium such as I2C, there are different signal names and signal polarity modes.
SPI devices communicate either in Full duplex, Half duplex, or Simplex (rx/tx) mode using a master-slave architecture with a single master.
The Linux kernel SPI framework provides a complete support for SPI master (the Linux kernel initiates SPI messaging on the bus) and more recently for SPI slave (the Linux kernel answers to requests from the bus master).
See  for an introduction on the Linux kernel SPI framework.
2 System overview
The user can add many SPI external devices around the microprocessor device, to create a custom board. Each external device can be accessed through the SPI from the user space or the kernel space.
2.1 Component description
2.1.1 Board external SPI devices
Master/Slave devices 'X' are physical devices (connected to the STM32 microprocessor via an SPI bus) that behave as slaves or master with respect to the STM32.
The STM32 is the SPI bus controller.
A chip select signal allows selecting independently each device.
2.1.2 STM32 SPI internal peripheral controller
The STM32 SPI controller handles any external SPI devices connected to the same bus.
The STM32 microprocessor devices usually embed several instances of the SPI internal peripheral allowing to manage multiple SPI buses.
For more information about STM32 SPI internal peripherals, please refer to SPI_internal_peripheral#SPI_main_features
2.1.3 STM32 QSPI internal peripheral controller
The STM32 QSPI controller can handles external SPI devices connected to the same bus.
For more information about STM32 QSPI internal peripherals, please refer to QUADSPI_internal_peripheral#Peripheral_overview
The STM32 SPI controller driver offers an ST SPI internal peripheral abstraction layer to the spi-core.
It defines all the SPI transfer methods to be used by the SPI core base.
spi-core is the "brain of the communication": it instantiates and manages all buses and peripherals.
- As stated by its name, this is the SPI engine. It is also in charge of parsing device tree entries both for adapter and devices. It implements the standard SPI modes: 0, 1, 2 and 3.
2.1.6 Device drivers
This layer represents all the drivers associated to physical peripherals.
spidev is the interface between the user and the peripheral. This is a kernel driver that offers a unified SPI bus access to the user space application using this dev-interface API. See API Description for examples.
The application can control all peripherals thanks to the spidev interface.
2.2 API description
2.2.1 User space application
The user space application uses a kernel driver (spidev) for SPI transfers through the devfs.
Let's take the example of an SPI device connected to bus B with chip select C. The spidev driver provides the following interfaces:
- /dev/spidevB.C: character special device created by "udev" that is used by the user space application to control and transfer data to the SPI device.
Supported system calls : open(), close(), read(), write(), ioctl(), llseek(), release().
|SPI_IOC_RD_MODE, SPI_IOC_WR_MODE||Gets/sets SPI transfer mode|
|SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST||Gets/sets bit justification used to transfer SPI words.|
|SPI_IOC_RD_BITS_PER_WORD, SPI_IOC_WR_BITS_PER_WORD||Gets/sets the number of bits in each SPI transfer word.|
|SPI_IOC_RD_MAX_SPEED_HZ, SPI_IOC_WR_MAX_SPEED_HZ||Gets/sets the maximum SPI transfer speed in Hz.|
The table above shows only the main commands. Additional commands are defined in the framework (see dev-interface API for a complete list).
2.2.2 Kernel space peripheral driver
The kernel space peripheral driver communicates with SPI devices and uses the following SPI core API: 
3.1 Kernel configuration
Enable SPI support (SPI framework and STM32 SPI driver) in the kernel configuration through the Linux Menuconfig tool: Menuconfig or how to configure kernel.
[x] Device Drivers [x] SPI support *** SPI Master Controller Drivers *** [x] STMicroelectronics STM32 SPI controller *** SPI Protocol Masters *** [x] User mode SPI device driver support [x] SPI slave protocol handlers
This can be done manually in your kernel:
CONFIG_SPI=y CONFIG_SPI_MASTER=y CONFIG_SPI_SLAVE=y CONFIG_SPI_STM32=y CONFIG_SPI_SPIDEV=y
Drivers (controller and peripheral) can be compiled as a kernel module (selected by the 'm' kernel configuration file) or directly into the kernel (aka built-in) (selected by the 'y' kernel configuration file).
3.2 Device tree configuration
Please refer to SPI device tree configuration.
4 How to use the framework
Detailed information on how to write an SPI device driver to control an SPI device are available in the Linux kernel documentation.
User-space examples can be found in How to use SPI from Linux userland with spidev.
5 How to trace and debug the framework
5.1 How to trace
5.1.1 Activating SPI framework debug messages
To get verbose messages from the SPI Framework, activate "Debug support for SPI drivers" in the Linux kernel via menuconfig Menuconfig or how to configure kernel.
[x] Device Drivers [x] SPI support [x] Debug support for SPI drivers
This is done manually in your kernel .config file:
CONFIG_SPI=y CONFIG_SPI_DEBUG=y CONFIG_SPI_MASTER=y ...
the debug support for SPI drivers (CONFIG_SPI_DEBUG) compiles all the SPI files located in Linux kernel drivers/spi folder with DEBUG flag.
5.1.2 Dynamic trace
A detailed dynamic trace is available in How to use the kernel dynamic debug
echo "file spi* +p" > /sys/kernel/debug/dynamic_debug/control
This command enables all the traces related to the SPI core and drivers at runtime.
A finer selection can be made by choosing only the files to trace.
5.2 How to debug
5.2.1 Detecting SPI configuration
When a peripheral is instantiated, the spi-core and the kernel export several files through the sysfs :
- /sys/class/spi_master/spix shows all the instantiated SPI buses, 'x' being the SPI bus number.
- /sys/bus/spi/devices lists all the instantiated peripherals. For example, the repository named spi0.0 corresponds to the peripheral connected to SPI bus 0 and chip select 0. Below an example representing the "TPM" device:
- /sys/bus/spi/drivers lists all the instantiated drivers. The tpm_tis_spi/ repository is the driver of TPM 2.0. The spidev/ repository is the generic driver of SPI user mode.
/sys/bus/spi/devices/spi0.0/ / /drivers/tpm_tis_spi/spi0.0/ /drivers/spidev/...
/sys/class/spi_master/spi0/spi0.0 /spi1/ /spi2/
If the spidev driver is compiled into the kernel, the repository /dev contains all SPI device entries. They are numbered spix.y where:
- 'x' is the SPI bus number
- 'y' is the chip select index on the bus.
Unlike i2c-dev which allows full access to the I2C bus, the spidev offers direct access to the SPI device identified by its chip select signal defined in the device tree node.
Below example shows user mode SPI device on SPI bus 4, chipselect 2.
For more information, please refer to the spidev documentation .
6 Source code location
- The SPI framework is available under drivers/spi
- The STM32 SPI driver is available under drivers/spi/spi-stm32.c
- The user API for the SPI bus is available under include/linux/spi/spi.h and SPI dev is include/uapi/linux/spi/spidev.h .
- ↑ https://en.wikipedia.org/w/index.php?title=Serial_Peripheral_Interface
- ↑ https://bootlin.com/doc/training/linux-kernel/
- ↑ 3.03.1 Documentation/spi/spidev.rst dev-interface API
- ↑ Serial Peripheral Interface (SPI)
- ↑ Documentation/spi/spi-summary.rst Linux kernel SPI framework summary