SPI¶
Low-level SPI peripheral driver.
This interface defines an abstraction for using a CPU’s hardware SPI units. The interface only supports SPI master mode.
As SPI buses can have multiple devices connected to them they are to be considered as shared resources. To reflect this, the SPI interface is based on a transaction model. This requires that the bus needs to be acquired before usage and released afterwards, using the spi_acquire()
and the spi_release()
functions.
This interface supports both software and hardware chip select lines. This is reflected by the cpi_cs_t type, which overloads the gpio_t type with platform specific values for defining platform dependent hardware chip select lines.
Some devices have however very uncommon requirements on the usage and the timings of their chip select line. For those cases this interface allows to manage the chip select line manually from the user code (e.g. by calling gpio_set/clear explicitly) while deactivating the SPI driver internal chip select handling by passing gpio.h::GPIO_UNDEF
as CS parameter.
In the time, when the SPI bus is not used, the SPI unit should be in low-power mode to save energy.
The SPI unit’s initialization is split into 3 parts:
spi_init()
should be called once for each SPI unit defined by a board during system initialization.spi_init_cs()
should be called during device driver initialization, as each chip select pin/line is used uniquely by a specific device, i.e. chip select lines are no shared resource.spi_acquire()
needs to be called for each new transaction. This function configures the bus with specific parameters (clock, mode) for the duration of that transaction.
-
enum
@149
¶ - SPI_OK
= 0
- everything went as planned
- SPI_NODEV
= -1
- invalid SPI bus specified
- SPI_NOCS
= -2
- invalid chip select line specified
- SPI_NOMODE
= -3
- selected mode is not supported
- SPI_NOCLK
= -4
- selected clock value is not supported
- SPI_OK
-
enum
spi_mode_t
¶ - SPI_MODE_0
= SPI_MODE_SEL(0, 0)
- mode 0
- SPI_MODE_1
= SPI_MODE_SEL(0, 1)
- mode 1
- SPI_MODE_2
= SPI_MODE_SEL(1, 0)
- mode 2
- SPI_MODE_3
= SPI_MODE_SEL(1, 1)
- mode 3
- SPI_MODE_0
-
enum
spi_clk_t
¶ - SPI_CLK_4MHZ
= 4000000
- drive the SPI bus with 4MHz
- SPI_CLK_100KHZ
= SPI_CLK_SEL(0, 1, 1)
- 16/128 -> 125KHz
- SPI_CLK_400KHZ
= SPI_CLK_SEL(1, 1, 0)
- 16/32 -> 500KHz
- SPI_CLK_1MHZ
= SPI_CLK_SEL(0, 0, 1)
- 16/16 -> 1MHz
- SPI_CLK_5MHZ
= SPI_CLK_SEL(0, 0, 0)
- 16/4 -> 4MHz
- SPI_CLK_10MHZ
= SPI_CLK_SEL(1, 0, 0)
- 16/2 -> 8MHz
- SPI_CLK_4MHZ
-
unsigned int
spi_t
¶ Default type for SPI devices.
-
gpio.h::gpio_t
spi_cs_t
¶ Chip select pin type overlaps with gpio_t so it can be casted to this.
-
void
spi_init
(spi.h::spi_t
bus)¶ Basic initialization of the given SPI bus.
This function does the basic initialization including pin configuration for MISO, MOSI, and CLK pins. After initialization, the given device should be in power down state.
This function is intended to be called by the board initialization code during system startup to prepare the (shared) SPI device for further usage. It uses the board specific initialization parameters as defined in the board’s
periph_conf.h
.Errors (e.g. invalid
bus
parameter) are not signaled through a return value, but should be signaled using theassert.h::assert
function internally.Note
This function MUST not be called more than once per bus!
Parameters
bus: SPI device to initialize
-
void
spi_init_pins
(spi.h::spi_t
bus)¶ Initialize the used SPI bus pins, i.e.
MISO, MOSI, and CLK
After calling spi_init, the pins must be initialized (i.e. spi_init is calling this function internally). In normal cases, this function will not be used. But there are some devices (e.g. CC110x), that use SPI bus lines also for other purposes and need the option to dynamically re-configure one or more of the used pins. So they can take control over certain pins and return control back to the SPI driver using this function.
The pins used are configured in the board’s periph_conf.h.
Parameters
bus: SPI device the pins are configure for
-
int
spi_init_cs
(spi.h::spi_t
bus,spi.h::spi_cs_t
cs)¶ Initialize the given chip select pin.
The chip select can be any generic GPIO pin (e.g.
gpio.h::GPIO_PIN
), or it can be a hardware chip select line. The existence and number of hardware chip select lines depends on the underlying platform and the actual pins used for hardware chip select lines are defined in the board’speriph_conf.h
.Define the used chip select line using the
spi.h::SPI_HWCS
macro for hardware chip select linex
or thegpio.h::GPIO_PIN
macro for using any GPIO pin for manual chip select.Parameters
bus: SPI device that is used with the given CS line cs: chip select pin to initialize Return values
- SPI_OK on success
- SPI_NODEV on invalid device
- SPI_NOCS on invalid CS pin/line
-
int
spi_acquire
(spi.h::spi_t
bus,spi.h::spi_cs_t
cs,atmega_common/include/periph_cpu_common.h::spi_mode_t
mode,atmega_common/include/periph_cpu_common.h::spi_clk_t
clk)¶ Start a new SPI transaction.
Starting a new SPI transaction will get exclusive access to the SPI bus and configure it according to the given values. If another SPI transaction is active when this function is called, this function will block until the other transaction is complete (spi_relase was called).
Note
This function expects the
bus
and thecs
parameters to be valid (they are checked in spi_init and spi_init_cs before)Parameters
bus: SPI device to access cs: chip select pin/line to use, set to SPI_CS_UNDEF if chip select should not be handled by the SPI driver mode: mode to use for the new transaction clk: bus clock speed to use for the transaction Return values
- SPI_OK on success
- SPI_NOMODE if given mode is not supported
- SPI_NOCLK if given clock speed is not supported
-
void
spi_release
(spi.h::spi_t
bus)¶ Finish an ongoing SPI transaction by releasing the given SPI bus.
After release, the given SPI bus should be fully powered down until acquired again.
Parameters
bus: SPI device to release
-
uint8_t
spi_transfer_byte
(spi.h::spi_t
bus,spi.h::spi_cs_t
cs, bool cont, uint8_t out)¶ Transfer one byte on the given SPI bus.
Parameters
bus: SPI device to use cs: chip select pin/line to use, set to SPI_CS_UNDEF if chip select should not be handled by the SPI driver cont: if true, keep device selected after transfer out: byte to send out, set NULL if only receiving Return values
- the received byte
-
void
spi_transfer_bytes
(spi.h::spi_t
bus,spi.h::spi_cs_t
cs, bool cont, const void * out, void * in,msp430_types.h::size_t
len)¶ Transfer a number bytes using the given SPI bus.
Parameters
bus: SPI device to use cs: chip select pin/line to use, set to SPI_CS_UNDEF if chip select should not be handled by the SPI driver cont: if true, keep device selected after transfer out: buffer to send data from, set NULL if only receiving in: buffer to read into, set NULL if only sending len: number of bytes to transfer
-
uint8_t
spi_transfer_reg
(spi.h::spi_t
bus,spi.h::spi_cs_t
cs, uint8_t reg, uint8_t out)¶ Transfer one byte to/from a given register address.
This function is a shortcut function for easier handling of SPI devices that implement a register based access scheme.
Parameters
bus: SPI device to use cs: chip select pin/line to use, set to SPI_CS_UNDEF if chip select should not be handled by the SPI driver reg: register address to transfer data to/from out: byte to send, set NULL if only receiving data Return values
- value that was read from the given register address
-
void
spi_transfer_regs
(spi.h::spi_t
bus,spi.h::spi_cs_t
cs, uint8_t reg, const void * out, void * in,msp430_types.h::size_t
len)¶ Transfer a number of bytes to/from a given register address.
This function is a shortcut function for easier handling of SPI devices that implement a register based access scheme.
Parameters
bus: SPI device to use cs: chip select pin/line to use, set to SPI_CS_UNDEF if chip select should not be handled by the SPI driver reg: register address to transfer data to/from out: buffer to send data from, set NULL if only receiving in: buffer to read into, set NULL if only sending len: number of bytes to transfer
-
SPI_DEV
( x)¶ Default SPI device access macro.
1
(x)
-
SPI_UNDEF
¶ Define global value for undefined SPI device.
1
(UINT_MAX)
-
SPI_CS_UNDEF
¶ Define value for unused CS line.
1
(GPIO_UNDEF)
-
SPI_HWCS
( x)¶ Default SPI hardware chip select access macro.
1
(SPI_CS_UNDEF)
Per default, we map all hardware chip select lines to be not defined. If an implementation makes use of HW chip select lines, this value needs to be overridden by the corresponding CPU.