SPI transaction manager
This library runs SPI controller (SPIM) work on a single hardware instance, one job at a time.
Overview
Applications describe work as transactions, where each transaction is one or more transfers (TX/RX steps) that run in order on the bus. The library keeps pending transactions in a FIFO queue and runs them one after another, so the application can keep scheduling work without waiting for the bus to be free.
The library resides on top of the nrfx SPIM driver. Scheduling is non-blocking. Work is added to the queue and the call returns immediately, with completion reported through an optional end callback.
Each transaction can use the default SPIM configuration or supply its own. This enables sharing one SPIM instance between several devices on the same bus, for example by giving each device its own chip-select pin.
Configuration
Set the CONFIG_BM_SPI_MNGR Kconfig option to enable the library.
The option depends on CONFIG_NRFX_SPIM and selects CONFIG_RING_BUFFER for the internal queue.
Initialization
The manager instance is declared using the BM_SPI_MNGR_DEF macro, specifying the instance name, queue size, and SPIM instance.
The queue size is the number of transactions that can wait in the queue, not counting the one currently running.
Before initializing, connect and enable the SPIM interrupt for the chosen instance, for example with BM_IRQ_DIRECT_CONNECT.
The interrupt handler must forward the event to the nrfx SPIM driver.
To initialize the manager, call the bm_spi_mngr_init() function with an nrfx_spim_config_t configuration, created with NRFX_SPIM_DEFAULT_CONFIG and customized as needed.
The following example shows how to declare, connect, and initialize a manager instance:
#include <bm/bm_spi_mngr.h>
BM_SPI_MNGR_DEF(spi_mgr, 4, SPIM_INST);
static nrfx_spim_config_t spim_cfg = NRFX_SPIM_DEFAULT_CONFIG(PIN_SCK, PIN_MOSI, PIN_MISO, PIN_CSN);
ISR_DIRECT_DECLARE(spim_isr)
{
nrfx_spim_irq_handler(spi_mgr.spim);
return 0;
}
BM_IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(SPIM_INST), IRQ_PRIO_LOWEST, spim_isr, 0);
irq_enable(NRFX_IRQ_NUMBER_GET(SPIM_INST));
bm_spi_mngr_init(&spi_mgr, &spim_cfg);
To uninitialize a manager instance, use the bm_spi_mngr_uninit() function.
Do not call it while a transaction is running, as it does not cancel pending work.
Usage
The usage of this library is demonstrated in the SPI Manager sample.
Work is described in a bm_spi_mngr_transaction structure, holding an array of transfers and the number of transfers.
Use the BM_SPI_MNGR_TRANSFER macro to set up each transfer.
A transaction can optionally provide a begin callback, an end callback, and a per-transaction SPIM configuration. Both callbacks may run from the SPIM interrupt handler, so keep them short, for example setting a flag.
Note
The transaction descriptor and any configuration it points to must stay valid until the transaction completes, because the library stores only a pointer to it.
The following is a list of operations you can perform with this library.
Schedule transactions
Use the bm_spi_mngr_schedule() function to add a transaction to the queue.
The transaction starts at once if the bus is idle, otherwise it runs after the transactions ahead of it.
The completion of the transaction is reported by the optional end callback.
Busy state
Use the bm_spi_mngr_is_idle() function to check whether all scheduled work has completed.
Dependencies
This library has the following Bare Metal dependencies:
nrfx SPIM -
CONFIG_NRFX_SPIMZephyr ring buffer -
CONFIG_RING_BUFFER
API documentation
include/bm/bm_spi_mngr.hlib/bm_spi_mngr/