Serial Peripheral Interface (SPI) Bus

Overview

API Reference

group spi_interface

SPI Interface.

SPI operational mode

SPI_OP_MODE_MASTER

Master mode.

SPI_OP_MODE_SLAVE

Slave mode.

SPI_OP_MODE_GET(_operation_)

Get SPI operational mode.

SPI Polarity & Phase Modes

SPI_MODE_CPOL

Clock Polarity: if set, clock idle state will be 1 and active state will be 0.

If untouched, the inverse will be true which is the default.

SPI_MODE_CPHA

Clock Phase: this dictates when is the data captured, and depends clock’s polarity.

When SPI_MODE_CPOL is set and this bit as well, capture will occur on low to high transition and high to low if this bit is not set (default). This is fully reversed if CPOL is not set.

SPI_MODE_LOOP

Whatever data is transmitted is looped-back to the receiving buffer of the controller.

This is fully controller dependent as some may not support this, and can be used for testing purposes only.

SPI_MODE_GET(_mode_)

Get SPI polarity and phase mode bits.

SPI Transfer modes (host controller dependent)

SPI_TRANSFER_MSB

Most significant bit first.

SPI_TRANSFER_LSB

Least significant bit first.

SPI word size

SPI_WORD_SIZE_GET(_operation_)

Get SPI word size.

SPI_WORD_SET(_word_size_)

Set SPI word size.

Specific SPI devices control bits

SPI_HOLD_ON_CS

Requests - if possible - to keep CS asserted after the transaction.

SPI_LOCK_ON

Keep the device locked after the transaction for the current config.

Use this with extreme caution (see spi_release() below) as it will prevent other callers to access the SPI device until spi_release() is properly called.

SPI_CS_ACTIVE_HIGH

Active high logic on CS.

Usually, and by default, CS logic is active low. However, some devices may require the reverse logic: active high. This bit will request the controller to use that logic. Note that not all controllers are able to handle that natively. In this case deferring the CS control to a gpio line through struct spi_cs_control would be the solution.

SPI MISO lines

Some controllers support dual, quad or octal MISO lines connected to slaves.

Default is single, which is the case most of the time. Without CONFIG_SPI_EXTENDED_MODES being enabled, single is the only supported one.

SPI_LINES_SINGLE

Single line.

SPI_LINES_DUAL

Dual lines.

SPI_LINES_QUAD

Quad lines.

SPI_LINES_OCTAL

Octal lines.

SPI_LINES_MASK

Mask for MISO lines in spi_operation_t.

SPI duplex mode

Some controllers support half duplex transfer, which results in 3-wire usage.

By default, full duplex will prevail.

SPI_FULL_DUPLEX
SPI_HALF_DUPLEX

SPI Frame Format

2 frame formats are exposed: Motorola and TI.

The main difference is the behavior of the CS line. In Motorola it stays active the whole transfer. In TI, it’s active only one serial clock period prior to actually make the transfer, it is thus inactive during the transfer, which ends when the clocks ends as well. By default, as it is the most commonly used, the Motorola frame format will prevail.

SPI_FRAME_FORMAT_MOTOROLA
SPI_FRAME_FORMAT_TI

Defines

SPI_CS_GPIOS_DT_SPEC_GET(spi_dev)

Get a struct gpio_dt_spec for a SPI device’s chip select pin.

Example devicetree fragment:

gpio1: gpio@abcd0001 { ... };

gpio2: gpio@abcd0002 { ... };

spi@abcd0003 {
        compatible = "vnd,spi";
        cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
                   <&gpio2 20 GPIO_ACTIVE_LOW>;

        a: spi-dev-a@0 {
                reg = <0>;
        };

        b: spi-dev-b@1 {
                reg = <1>;
        };
};

Example usage:

SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(a)) \
      // { DEVICE_DT_GET(DT_NODELABEL(gpio1)), 10, GPIO_ACTIVE_LOW }
SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(b)) \
      // { DEVICE_DT_GET(DT_NODELABEL(gpio2)), 20, GPIO_ACTIVE_LOW }
Parameters:
  • spi_dev – a SPI device node identifier

Returns:

gpio_dt_spec struct corresponding with spi_dev’s chip select

SPI_CS_GPIOS_DT_SPEC_INST_GET(inst)

Get a struct gpio_dt_spec for a SPI device’s chip select pin.

This is equivalent to SPI_CS_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst)).

Parameters:
  • inst – Devicetree instance number

Returns:

gpio_dt_spec struct corresponding with spi_dev’s chip select

SPI_CS_CONTROL_INIT(node_id, delay_)

Initialize and get a pointer to a spi_cs_control from a devicetree node identifier.

This helper is useful for initializing a device on a SPI bus. It initializes a struct spi_cs_control and returns a pointer to it. Here, node_id is a node identifier for a SPI device, not a SPI controller.

Example devicetree fragment:

spi@abcd0001 {
        cs-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
        spidev: spi-device@0 { ... };
};

Example usage:

struct spi_cs_control ctrl =
        SPI_CS_CONTROL_INIT(DT_NODELABEL(spidev), 2);

This example is equivalent to:

struct spi_cs_control ctrl = {
        .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(spidev)),
        .delay = 2,
};
Parameters:
  • node_id – Devicetree node identifier for a device on a SPI bus

  • delay_ – The delay field to set in the spi_cs_control

Returns:

a pointer to the spi_cs_control structure

SPI_CS_CONTROL_INIT_INST(inst, delay_)

Get a pointer to a spi_cs_control from a devicetree node.

This is equivalent to SPI_CS_CONTROL_INIT(DT_DRV_INST(inst), delay).

Therefore, DT_DRV_COMPAT must already be defined before using this macro.

Parameters:
  • inst – Devicetree node instance number

  • delay_ – The delay field to set in the spi_cs_control

Returns:

a pointer to the spi_cs_control structure

SPI_CONFIG_DT(node_id, operation_, delay_)

Structure initializer for spi_config from devicetree.

This helper macro expands to a static initializer for a struct spi_config by reading the relevant frequency, slave, and cs data from the devicetree.

Parameters:
  • node_id – Devicetree node identifier for the SPI device whose struct spi_config to create an initializer for

  • operation_ – the desired operation field in the struct spi_config

  • delay_ – the desired delay field in the struct spi_config’s spi_cs_control, if there is one

SPI_CONFIG_DT_INST(inst, operation_, delay_)

Structure initializer for spi_config from devicetree instance.

This is equivalent to SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_).

Parameters:
  • inst – Devicetree instance number

  • operation_ – the desired operation field in the struct spi_config

  • delay_ – the desired delay field in the struct spi_config’s spi_cs_control, if there is one

SPI_DT_SPEC_GET(node_id, operation_, delay_)

Structure initializer for spi_dt_spec from devicetree.

This helper macro expands to a static initializer for a struct spi_dt_spec by reading the relevant bus, frequency, slave, and cs data from the devicetree.

Important: multiple fields are automatically constructed by this macro which must be checked before use. spi_is_ready performs the required device_is_ready checks.

Deprecated:

Use spi_is_ready_dt instead.

Parameters:
  • node_id – Devicetree node identifier for the SPI device whose struct spi_dt_spec to create an initializer for

  • operation_ – the desired operation field in the struct spi_config

  • delay_ – the desired delay field in the struct spi_config’s spi_cs_control, if there is one

SPI_DT_SPEC_INST_GET(inst, operation_, delay_)

Structure initializer for spi_dt_spec from devicetree instance.

This is equivalent to SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_).

Parameters:
  • inst – Devicetree instance number

  • operation_ – the desired operation field in the struct spi_config

  • delay_ – the desired delay field in the struct spi_config’s spi_cs_control, if there is one

SPI_DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, prio, api, ...)
SPI_STATS_RX_BYTES_INC(dev_)
SPI_STATS_TX_BYTES_INC(dev_)
SPI_STATS_TRANSFER_ERROR_INC(dev_)
spi_transceive_stats(dev, error, tx_bufs, rx_bufs)
SPI_DT_IODEV_DEFINE(name, node_id, operation_, delay_)

Define an iodev for a given dt node on the bus.

These do not need to be shared globally but doing so will save a small amount of memory.

Parameters:
  • name – Symbolic name to use for defining the iodev

  • node_id – Devicetree node identifier

  • operation_ – SPI operational mode

  • delay_ – Chip select delay in microseconds

Typedefs

typedef uint16_t spi_operation_t

Opaque type to hold the SPI operation flags.

typedef int (*spi_api_io)(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs)

Callback API for I/O See spi_transceive() for argument descriptions.

Callback API for asynchronous I/O See spi_transceive_async() for argument descriptions.

typedef void (*spi_callback_t)(const struct device *dev, int result, void *data)

SPI callback for asynchronous transfer requests.

Param dev:

SPI device which is notifying of transfer completion or error

Param result:

Result code of the transfer request. 0 is success, -errno for failure.

Param data:

Transfer requester supplied data which is passed along to the callback.

typedef int (*spi_api_io_async)(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, spi_callback_t cb, void *userdata)
typedef int (*spi_api_release)(const struct device *dev, const struct spi_config *config)

Callback API for unlocking SPI device.

See spi_release() for argument descriptions

Functions

static inline bool spi_cs_is_gpio(const struct spi_config *config)

Check if SPI CS is controlled using a GPIO.

Parameters:
  • config – SPI configuration.

Returns:

true If CS is controlled using a GPIO.

Returns:

false If CS is controlled by hardware or any other means.

static inline bool spi_cs_is_gpio_dt(const struct spi_dt_spec *spec)

Check if SPI CS in spi_dt_spec is controlled using a GPIO.

Parameters:
  • spec – SPI specification from devicetree.

Returns:

true If CS is controlled using a GPIO.

Returns:

false If CS is controlled by hardware or any other means.

static inline bool spi_is_ready(const struct spi_dt_spec *spec)

Validate that SPI bus is ready.

Parameters:
  • spec – SPI specification from devicetree

Return values:
  • true – if the SPI bus is ready for use.

  • false – if the SPI bus is not ready for use.

static inline bool spi_is_ready_dt(const struct spi_dt_spec *spec)

Validate that SPI bus (and CS gpio if defined) is ready.

Parameters:
  • spec – SPI specification from devicetree

Return values:
  • true – if the SPI bus is ready for use.

  • false – if the SPI bus (or the CS gpio defined) is not ready for use.

int spi_transceive(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs)

Read/write the specified amount of data from the SPI driver.

Note

This function is synchronous.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • tx_bufs – Buffer array where data to be sent originates from, or NULL if none.

  • rx_bufs – Buffer array where data to be read will be written to, or NULL if none.

Return values:
  • frames – Positive number of frames received in slave mode.

  • 0 – If successful in master mode.

  • -errno – Negative errno code on failure.

static inline int spi_transceive_dt(const struct spi_dt_spec *spec, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs)

Read/write data from an SPI bus specified in spi_dt_spec.

This is equivalent to:

spi_transceive(spec->bus, &spec->config, tx_bufs, rx_bufs);

Parameters:
  • spec – SPI specification from devicetree

  • tx_bufs – Buffer array where data to be sent originates from, or NULL if none.

  • rx_bufs – Buffer array where data to be read will be written to, or NULL if none.

Returns:

a value from spi_transceive().

static inline int spi_read(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *rx_bufs)

Read the specified amount of data from the SPI driver.

Note

This function is synchronous.

Note

This function is a helper function calling spi_transceive.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • rx_bufs – Buffer array where data to be read will be written to.

Return values:
  • frames – Positive number of frames received in slave mode.

  • 0 – If successful.

  • -errno – Negative errno code on failure.

static inline int spi_read_dt(const struct spi_dt_spec *spec, const struct spi_buf_set *rx_bufs)

Read data from a SPI bus specified in spi_dt_spec.

This is equivalent to:

spi_read(spec->bus, &spec->config, rx_bufs);

Parameters:
  • spec – SPI specification from devicetree

  • rx_bufs – Buffer array where data to be read will be written to.

Returns:

a value from spi_read().

static inline int spi_write(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs)

Write the specified amount of data from the SPI driver.

Note

This function is synchronous.

Note

This function is a helper function calling spi_transceive.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • tx_bufs – Buffer array where data to be sent originates from.

Return values:
  • 0 – If successful.

  • -errno – Negative errno code on failure.

static inline int spi_write_dt(const struct spi_dt_spec *spec, const struct spi_buf_set *tx_bufs)

Write data to a SPI bus specified in spi_dt_spec.

This is equivalent to:

spi_write(spec->bus, &spec->config, tx_bufs);

Parameters:
  • spec – SPI specification from devicetree

  • tx_bufs – Buffer array where data to be sent originates from.

Returns:

a value from spi_write().

static inline int spi_transceive_cb(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, spi_callback_t callback, void *userdata)

Read/write the specified amount of data from the SPI driver.

Note

This function is asynchronous.

Note

This function is available only if CONFIG_SPI_ASYNC is selected.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • tx_bufs – Buffer array where data to be sent originates from, or NULL if none.

  • rx_bufs – Buffer array where data to be read will be written to, or NULL if none.

  • callback – Function pointer to completion callback. (Note: if NULL this function will not notify the end of the transaction, and whether it went successfully or not).

  • userdata – Userdata passed to callback

Return values:
  • frames – Positive number of frames received in slave mode.

  • 0 – If successful in master mode.

  • -errno – Negative errno code on failure.

static inline int spi_transceive_signal(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, struct k_poll_signal *sig)

Read/write the specified amount of data from the SPI driver.

Note

This function is asynchronous.

Note

This function is available only if CONFIG_SPI_ASYNC and CONFIG_POLL are selected.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • tx_bufs – Buffer array where data to be sent originates from, or NULL if none.

  • rx_bufs – Buffer array where data to be read will be written to, or NULL if none.

  • sig – A pointer to a valid and ready to be signaled struct k_poll_signal. (Note: if NULL this function will not notify the end of the transaction, and whether it went successfully or not).

Return values:
  • frames – Positive number of frames received in slave mode.

  • 0 – If successful in master mode.

  • -errno – Negative errno code on failure.

static inline int spi_transceive_async(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, struct k_poll_signal *sig)

Alias for spi_transceive_signal for backwards compatibility.

Deprecated:

Use spi_transceive_signal instead.

static inline int spi_read_signal(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *rx_bufs, struct k_poll_signal *sig)

Read the specified amount of data from the SPI driver.

Note

This function is asynchronous.

Note

This function is a helper function calling spi_transceive_signal.

Note

This function is available only if CONFIG_SPI_ASYNC and CONFIG_POLL are selected.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • rx_bufs – Buffer array where data to be read will be written to.

  • sig – A pointer to a valid and ready to be signaled struct k_poll_signal. (Note: if NULL this function will not notify the end of the transaction, and whether it went successfully or not).

Return values:
  • frames – Positive number of frames received in slave mode.

  • 0 – If successful

  • -errno – Negative errno code on failure.

static inline int spi_read_async(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *rx_bufs, struct k_poll_signal *sig)

Alias for spi_read_signal for backwards compatibility.

Deprecated:

Use spi_read_signal instead.

static inline int spi_write_signal(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, struct k_poll_signal *sig)

Write the specified amount of data from the SPI driver.

Note

This function is asynchronous.

Note

This function is a helper function calling spi_transceive_async.

Note

This function is available only if CONFIG_SPI_ASYNC and CONFIG_POLL are selected.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance. Pointer-comparison may be used to detect changes from previous operations.

  • tx_bufs – Buffer array where data to be sent originates from.

  • sig – A pointer to a valid and ready to be signaled struct k_poll_signal. (Note: if NULL this function will not notify the end of the transaction, and whether it went successfully or not).

Return values:
  • 0 – If successful.

  • -errno – Negative errno code on failure.

static inline int spi_write_async(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, struct k_poll_signal *sig)

Alias for spi_write_signal for backwards compatibility.

Deprecated:

Use spi_write_signal instead.

static inline void spi_iodev_submit(struct rtio_iodev_sqe *iodev_sqe)

Submit a SPI device with a request.

Parameters:
  • iodev_sqe – Prepared submissions queue entry connected to an iodev defined by SPI_IODEV_DEFINE. Must live as long as the request is in flight.

static inline bool spi_is_ready_iodev(const struct rtio_iodev *spi_iodev)

Validate that SPI bus (and CS gpio if defined) is ready.

Parameters:
  • spi_iodev – SPI iodev defined with SPI_DT_IODEV_DEFINE

Return values:
  • true – if the SPI bus is ready for use.

  • false – if the SPI bus (or the CS gpio defined) is not ready for use.

static inline int spi_rtio_copy(struct rtio *r, struct rtio_iodev *iodev, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, struct rtio_sqe **last_sqe)

Copy the tx_bufs and rx_bufs into a set of RTIO requests.

Parameters:
  • r[in] rtio context

  • iodev[in] iodev to transceive with

  • tx_bufs[in] transmit buffer set

  • rx_bufs[in] receive buffer set

  • last_sqe[out] last sqe submitted, NULL if not enough memory

Return values:
  • Number – of submission queue entries

  • -ENOMEM – out of memory

int spi_release(const struct device *dev, const struct spi_config *config)

Release the SPI device locked on and/or the CS by the current config.

Note: This synchronous function is used to release either the lock on the SPI device and/or the CS line that was kept if, and if only, given config parameter was the last one to be used (in any of the above functions) and if it has the SPI_LOCK_ON bit set and/or the SPI_HOLD_ON_CS bit set into its operation bits field. This can be used if the caller needs to keep its hand on the SPI device for consecutive transactions and/or if it needs the device to stay selected. Usually both bits will be used along each other, so the the device is locked and stays on until another operation is necessary or until it gets released with the present function.

Parameters:
  • dev – Pointer to the device structure for the driver instance

  • config – Pointer to a valid spi_config structure instance.

Return values:
  • 0 – If successful.

  • -errno – Negative errno code on failure.

static inline int spi_release_dt(const struct spi_dt_spec *spec)

Release the SPI device specified in spi_dt_spec.

This is equivalent to:

spi_release(spec->bus, &spec->config);

Parameters:
  • spec – SPI specification from devicetree

Returns:

a value from spi_release().

Variables

const struct rtio_iodev_api spi_iodev_api
struct spi_cs_control
#include <spi.h>

SPI Chip Select control structure.

This can be used to control a CS line via a GPIO line, instead of using the controller inner CS logic.

Public Members

struct gpio_dt_spec gpio

GPIO devicetree specification of CS GPIO.

The device pointer can be set to NULL to fully inhibit CS control if necessary. The GPIO flags GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct spi_config.

uint32_t delay

Delay in microseconds to wait before starting the transmission and before releasing the CS line.

struct spi_config
#include <spi.h>

SPI controller configuration structure.

Public Members

uint32_t frequency

Bus frequency in Hertz.

spi_operation_t operation

Operation flags.

It is a bit field with the following parts:

  • 0: Master or slave.

  • 1..3: Polarity, phase and loop mode.

  • 4: LSB or MSB first.

  • 5..10: Size of a data frame in bits.

  • 11: Full/half duplex.

  • 12: Hold on the CS line if possible.

  • 13: Keep resource locked for the caller.

  • 14: Active high CS logic.

  • 15: Motorola or TI frame format (optional).

If CONFIG_SPI_EXTENDED_MODES is enabled:

  • 16..17: MISO lines (Single/Dual/Quad/Octal).

  • 18..31: Reserved for future use.

uint16_t slave

Slave number from 0 to host controller slave limit.

struct spi_cs_control cs

GPIO chip-select line (optional, must be initialized to zero if not used).

struct spi_dt_spec
#include <spi.h>

Complete SPI DT information.

Public Members

const struct device *bus

SPI bus.

struct spi_config config

Slave specific configuration.

struct spi_buf
#include <spi.h>

SPI buffer structure.

Public Members

void *buf

Valid pointer to a data buffer, or NULL otherwise.

size_t len

Length of the buffer buf.

If buf is NULL, length which as to be sent as dummy bytes (as TX buffer) or the length of bytes that should be skipped (as RX buffer).

struct spi_buf_set
#include <spi.h>

SPI buffer array structure.

Public Members

const struct spi_buf *buffers

Pointer to an array of spi_buf, or NULL.

size_t count

Length of the array pointed by buffers.

struct spi_driver_api
#include <spi.h>

SPI driver API This is the mandatory API any SPI driver needs to expose.