Module spi_hal

SPI Hardware Abstraction Layer behavior.

Description

This module defines the behavior that platform-specific SPI modules must implement. It provides a common interface for SPI (Serial Peripheral Interface) operations across all supported platforms.

Currently, only ESP32 provides an SPI implementation.

Lifecycle

An SPI bus is opened with open/1 and closed with close/1. The open/1 function takes a configuration that includes both bus parameters (pins, peripheral) and device configurations. Multiple devices can share the same SPI bus.

Device names

Each device on the SPI bus is identified by a device_name() atom. Device names are defined during open/1 configuration and used in all subsequent read/write operations. For example, if the configuration includes {my_sensor, [{cs, 5}]}, then my_sensor is used as the device name in calls like spi:read_at(SPI, my_sensor, Address, Len).

Simple read/write

For simple address-based operations:

  • read_at/4 - Read data from a device at a given address

  • write_at/5 - Write data to a device at a given address

Transaction-based operations

For more complex operations, use transaction maps with write/3 or write_read/3:

  Transaction = #{
      command => 16#42,
      address => 16#00,
      write_data => <<1, 2, 3>>,
      write_bits => 24,
      read_bits => 8
  },
  {ok, ReadData} = spi:write_read(SPI, my_device, Transaction).

Configuration parameters

The open/1 function accepts a proplist or map with bus and device configuration. Bus parameters include:

  • {sclk, non_neg_integer()} - SCLK (clock) pin number (required)

  • {miso, non_neg_integer()} - MISO pin number (optional)

  • {mosi, non_neg_integer()} - MOSI pin number (optional)

  • {peripheral, string() | binary()} - SPI peripheral (e.g. "spi2", "spi3", default: "spi2")

Device parameters are specified as {DeviceName, DeviceOpts} entries:

  • {cs, non_neg_integer()} - Chip Select pin number

  • {clock_speed_hz, non_neg_integer()} - Clock speed (default:

  • {mode, 0..3} - SPI mode (default: 0)

  • {address_len_bits, 0..64} - Address width in bits (default:

  • {command_len_bits, 0..16} - Command width in bits (default:

Example

  SPI = spi:open([
      {sclk, 18}, {miso, 19}, {mosi, 23},
      {my_device, [{cs, 5}, {clock_speed_hz, 1000000}]}
  ]),
  {ok, Value} = spi:read_at(SPI, my_device, 16#0F, 8),
  spi:close(SPI).

Data Types

address()


address() = non_neg_integer()

SPI device address.

device_name()


device_name() = atom()

Name identifying an SPI device, as specified in the device configuration passed to open/1.

params()


params() = [term()] | map()

Initialization parameters for the SPI bus and its devices. See the module documentation for common parameters.

spi()


spi() = port() | pid() | term()

Handle returned by open/1.

transaction()


transaction() = #{command => integer(), address => non_neg_integer(), write_data => binary(), write_bits => non_neg_integer(), read_bits => non_neg_integer()}