SPI¶
SPI (Serial Peripheral Interface) is a synchronous 4-wire serial interface commonly used to connect components in embedded systems.
For a detailed description of SPI, see Wikipedia.
Description¶
The Mynewt HAL interface supports the SPI master functionality with both blocking and non-blocking interface. SPI slave functionality is supported in non-blocking mode.
Theory Of Operation¶
SPI is called a 4-wire interface because of the 4 signals, MISO, MOSI, CLK, and SS. The SS signal (slave select) is an active low signal that activates a SPI slave device. This is how a master “addresses” a particular slave device. Often this signal is also referred to as “chip select” as it selects particular slave device for communications.
The Mynewt SPI HAL has blocking and non-blocking transfers. Blocking means that the API call to transfer a byte will wait until the byte completes transmissions before the function returns. Blocking interface can be used for only the master slave SPI type. Non-blocking means he function returns control to the execution environment immediately after the API call and a callback function is executed at the completion of the transmission. Non-blocking interface can be used for both master and slave SPI types.
The hal_spi_config
method in the API above allows the SPI to be
configured with appropriate settings for master or slave. It Must be
called after the spi is initialized (i.e. after hal_spi_init is
called) and when the spi is disabled (i.e. user must call
hal_spi_disable if the spi has been enabled through hal_spi_enable
prior to calling this function). It can also be used to reconfigure an
initialized SPI (assuming it is disabled as described previously).
int hal_spi_config(int spi_num, struct hal_spi_settings *psettings);
The SPI settings consist of the following:
struct hal_spi_settings {
uint8_t data_mode;
uint8_t data_order;
uint8_t word_size;
uint32_t baudrate; /* baudrate in kHz */
};
The Mynewt SPI HAL does not include built-in SS (Slave Select) signaling. It’s up to the hal_spi user to control their own SS pins. Typically applications will do this with GPIO.
API¶
-
typedef void (*
hal_spi_txrx_cb
)(void *arg, int len)¶
-
int
hal_spi_init
(int spi_num, void *cfg, uint8_t spi_type)¶ Initialize the SPI, given by spi_num.
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: The number of the SPI to initializecfg
: HW/MCU specific configuration, passed to the underlying implementation, providing extra configuration.spi_type
: SPI type (master or slave)
-
int
hal_spi_init_hw
(uint8_t spi_num, uint8_t spi_type, const struct hal_spi_hw_settings *cfg)¶ Initialize SPI controller.
This initializes SPI controller hardware before 1st use. Shall be called only once.
- Return
0 on success, non-zero error code on failure
- Parameters
spi_num
: Number of SPI controllercfg
: Configuration
-
int
hal_spi_config
(int spi_num, struct hal_spi_settings *psettings)¶ Configure the spi.
Must be called after the spi is initialized (after hal_spi_init is called) and when the spi is disabled (user must call hal_spi_disable if the spi has been enabled through hal_spi_enable prior to calling this function). Can also be used to reconfigure an initialized SPI (assuming it is disabled as described previously).
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: The number of the SPI to configure.psettings
: The settings to configure this SPI with
-
int
hal_spi_set_txrx_cb
(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)¶ Sets the txrx callback (executed at interrupt context) when the buffer is transferred by the master or the slave using the non-blocking API.
Cannot be called when the spi is enabled. This callback will also be called when chip select is de-asserted on the slave.
NOTE: This callback is only used for the non-blocking interface and must be called prior to using the non-blocking API.
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: SPI interface on which to set callbacktxrx
: Callback functionarg
: Argument to be passed to callback function
-
int
hal_spi_enable
(int spi_num)¶ Enables the SPI.
This does not start a transmit or receive operation; it is used for power mgmt. Cannot be called when a SPI transfer is in progress.
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
:
-
int
hal_spi_disable
(int spi_num)¶ Disables the SPI.
Used for power mgmt. It will halt any current SPI transfers in progress.
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
:
-
uint16_t
hal_spi_tx_val
(int spi_num, uint16_t val)¶ Blocking call to send a value on the SPI.
Returns the value received from the SPI slave.
MASTER: Sends the value and returns the received value from the slave. SLAVE: Invalid API. Returns 0xFFFF
- Return
uint16_t Value received on SPI interface from slave. Returns 0xFFFF if called when the SPI is configured to be a slave
- Parameters
spi_num
: Spi interface to useval
: Value to send
-
int
hal_spi_txrx
(int spi_num, void *txbuf, void *rxbuf, int cnt)¶ Blocking interface to send a buffer and store the received values from the slave.
The transmit and receive buffers are either arrays of 8-bit (uint8_t) values or 16-bit values depending on whether the spi is configured for 8 bit data or more than 8 bits per value. The ‘cnt’ parameter is the number of 8-bit or 16-bit values. Thus, if ‘cnt’ is 10, txbuf/rxbuf would point to an array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
NOTE: these buffers are in the native endian-ness of the platform.
MASTER: master sends all the values in the buffer and stores the stores the values in the receive buffer if rxbuf is not NULL. The txbuf parameter cannot be NULL. SLAVE: cannot be called for a slave; returns -1
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: SPI interface to usetxbuf
: Pointer to buffer where values to transmit are stored.rxbuf
: Pointer to buffer to store values received from peer.cnt
: Number of 8-bit or 16-bit values to be transferred.
-
int
hal_spi_txrx_noblock
(int spi_num, void *txbuf, void *rxbuf, int cnt)¶ Non-blocking interface to send a buffer and store received values.
Can be used for both master and slave SPI types. The user must configure the callback (using hal_spi_set_txrx_cb); the txrx callback is executed at interrupt context when the buffer is sent.
The transmit and receive buffers are either arrays of 8-bit (uint8_t) values or 16-bit values depending on whether the spi is configured for 8 bit data or more than 8 bits per value. The ‘cnt’ parameter is the number of 8-bit or 16-bit values. Thus, if ‘cnt’ is 10, txbuf/rxbuf would point to an array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
NOTE: these buffers are in the native endian-ness of the platform.
MASTER: master sends all the values in the buffer and stores the stores the values in the receive buffer if rxbuf is not NULL. The txbuf parameter cannot be NULL SLAVE: Slave "preloads" the data to be sent to the master (values stored in txbuf) and places received data from master in rxbuf (if not NULL). The txrx callback occurs when len values are transferred or master de-asserts chip select. If txbuf is NULL, the slave transfers its default byte. Both rxbuf and txbuf cannot be NULL.
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: SPI interface to usetxbuf
: Pointer to buffer where values to transmit are stored.rxbuf
: Pointer to buffer to store values received from peer.cnt
: Number of 8-bit or 16-bit values to be transferred.
-
int
hal_spi_slave_set_def_tx_val
(int spi_num, uint16_t val)¶ Sets the default value transferred by the slave.
Not valid for master
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: SPI interface to use
-
int
hal_spi_abort
(int spi_num)¶ This aborts the current transfer but keeps the spi enabled.
NOTE: does not return an error if no transfer was in progress.
- Return
int 0 on success, non-zero error code on failure.
- Parameters
spi_num
: SPI interface on which transfer should be aborted.
-
int
hal_spi_data_mode_breakout
(uint8_t data_mode, int *out_cpol, int *out_cpha)¶ Extracts CPOL and CPHA values from a data-mode constant.
Utility function, defined once for every MCU.
- Return
0 on success; nonzero on invalid input.
- Parameters
data_mode
: The HAL_SPI_MODE value to convert.out_cpol
: The CPOL gets written here on success.out_cpha
: The CPHA gets written here on success.
-
HAL_SPI_TYPE_MASTER
¶
-
HAL_SPI_TYPE_SLAVE
¶
-
HAL_SPI_MODE0
¶ SPI mode 0.
-
HAL_SPI_MODE1
¶ SPI mode 1.
-
HAL_SPI_MODE2
¶ SPI mode 2.
-
HAL_SPI_MODE3
¶ SPI mode 3.
-
HAL_SPI_MSB_FIRST
¶ SPI data order, most significant bit first.
-
HAL_SPI_LSB_FIRST
¶ SPI data order, least significant bit first.
-
HAL_SPI_WORD_SIZE_8BIT
¶ SPI word size 8 bit.
-
HAL_SPI_WORD_SIZE_9BIT
¶ SPI word size 9 bit.
-
struct
hal_spi_hw_settings
¶ - #include <hal_spi.h>
SPI controller hardware settings.
-
struct
hal_spi_settings
¶ - #include <hal_spi.h>
since one spi device can control multiple devices, some configuration can be changed on the fly from the hal