|
| 1 | +.. _lib_bm_spi_mngr: |
| 2 | + |
| 3 | +SPI transaction manager |
| 4 | +####################### |
| 5 | + |
| 6 | +.. contents:: |
| 7 | + :local: |
| 8 | + :depth: 2 |
| 9 | + |
| 10 | +This library runs SPI master (SPIM) work on a single hardware instance, one job at a time. |
| 11 | + |
| 12 | +Overview |
| 13 | +******** |
| 14 | + |
| 15 | +Applications describe work as *transactions*, where each transaction is one or more *transfers* (TX/RX steps) that run in order on the bus. |
| 16 | +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. |
| 17 | + |
| 18 | +The library sits on top of the nrfx SPIM driver and offers both a non-blocking mode that queues work and returns immediately, and a blocking mode that waits until the work is done. |
| 19 | +Both share the same queue and scheduling engine. |
| 20 | + |
| 21 | +Each transaction can use the default SPIM configuration or supply its own. |
| 22 | +This makes it possible to share one SPIM instance between several devices on the same bus, for example by giving each device its own chip select pin. |
| 23 | + |
| 24 | +Configuration |
| 25 | +************* |
| 26 | + |
| 27 | +Set the :kconfig:option:`CONFIG_BM_SPI_MNGR` Kconfig option to enable the library. |
| 28 | + |
| 29 | +The option depends on :kconfig:option:`CONFIG_NRFX_SPIM` and selects :kconfig:option:`CONFIG_RING_BUFFER` for the internal queue. |
| 30 | + |
| 31 | +Initialization |
| 32 | +============== |
| 33 | + |
| 34 | +The manager instance is declared using the :c:macro:`BM_SPI_MNGR_DEF` macro, specifying the instance name, queue size, and SPIM instance. |
| 35 | +The queue size is the number of transactions that can wait in the queue, not counting the one currently running. |
| 36 | + |
| 37 | +Before initializing, connect and enable the SPIM interrupt for the chosen instance, for example with :c:macro:`BM_IRQ_DIRECT_CONNECT`. |
| 38 | +The interrupt handler must forward the event to the nrfx SPIM driver. |
| 39 | + |
| 40 | +To initialize the manager, call the :c:func:`bm_spi_mngr_init` function with an :c:type:`nrfx_spim_config_t` configuration, created with :c:macro:`NRFX_SPIM_DEFAULT_CONFIG` and customized as needed. |
| 41 | + |
| 42 | +The following example shows how to declare, connect, and initialize a manager instance: |
| 43 | + |
| 44 | +.. code-block:: c |
| 45 | +
|
| 46 | + #include <bm/bm_spi_mngr.h> |
| 47 | +
|
| 48 | + BM_SPI_MNGR_DEF(spi_mgr, 4, SPIM_INST); |
| 49 | +
|
| 50 | + static nrfx_spim_config_t spim_cfg = NRFX_SPIM_DEFAULT_CONFIG(PIN_SCK, PIN_MOSI, PIN_MISO, PIN_CSN); |
| 51 | +
|
| 52 | + ISR_DIRECT_DECLARE(spim_isr) |
| 53 | + { |
| 54 | + nrfx_spim_irq_handler(spi_mgr.spim); |
| 55 | + return 0; |
| 56 | + } |
| 57 | +
|
| 58 | + BM_IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(SPIM_INST), IRQ_PRIO_LOWEST, spim_isr, 0); |
| 59 | + irq_enable(NRFX_IRQ_NUMBER_GET(SPIM_INST)); |
| 60 | +
|
| 61 | + bm_spi_mngr_init(&spi_mgr, &spim_cfg); |
| 62 | +
|
| 63 | +You can uninitialize a manager instance with the :c:func:`bm_spi_mngr_uninit` function. |
| 64 | +Do not call it while a transaction is running or while a caller is blocked in :c:func:`bm_spi_mngr_perform`, as it does not cancel pending work or release blocked callers. |
| 65 | + |
| 66 | +Usage |
| 67 | +***** |
| 68 | + |
| 69 | +Work is described in a :c:struct:`bm_spi_mngr_transaction` structure, holding an array of transfers and the number of transfers. |
| 70 | +Use the :c:macro:`BM_SPI_MNGR_TRANSFER` macro to set up each transfer. |
| 71 | + |
| 72 | +A transaction can optionally provide a begin callback, an end callback, and a per-transaction SPIM configuration. |
| 73 | +Both callbacks may run from the SPIM interrupt handler, so keep them short, for example setting a flag. |
| 74 | + |
| 75 | +.. note:: |
| 76 | + |
| 77 | + The transaction descriptor and any configuration it points to must stay valid until the transaction finishes, because the library stores only a pointer to it. |
| 78 | + |
| 79 | +The following is a list of operations you can perform with this library. |
| 80 | + |
| 81 | +Schedule (non-blocking) |
| 82 | +======================= |
| 83 | + |
| 84 | +Use the :c:func:`bm_spi_mngr_schedule` function to add a transaction to the queue and return immediately. |
| 85 | +The transaction starts at once if the bus is idle, otherwise it runs after the transactions ahead of it. |
| 86 | +The completion of the transaction is reported by the optional end callback. |
| 87 | + |
| 88 | +Perform (blocking) |
| 89 | +================== |
| 90 | + |
| 91 | +Use the :c:func:`bm_spi_mngr_perform` function to schedule a single transaction and wait until it completes. |
| 92 | + |
| 93 | +While waiting, the function can call an optional idle function repeatedly. |
| 94 | +Because the function blocks until the transaction finishes, do not call it from an interrupt handler. |
| 95 | + |
| 96 | +Busy state |
| 97 | +========== |
| 98 | + |
| 99 | +Use the :c:func:`bm_spi_mngr_is_idle` function to check whether all scheduled work has finished. |
| 100 | + |
| 101 | +Dependencies |
| 102 | +************ |
| 103 | + |
| 104 | +This library has the following |BMshort| dependencies: |
| 105 | + |
| 106 | +* nrfx SPIM - :kconfig:option:`CONFIG_NRFX_SPIM` |
| 107 | +* Zephyr ring buffer - :kconfig:option:`CONFIG_RING_BUFFER` |
| 108 | + |
| 109 | +API documentation |
| 110 | +***************** |
| 111 | + |
| 112 | +| Header file: :file:`include/bm/bm_spi_mngr.h` |
| 113 | +| Source files: :file:`lib/bm_spi_mngr/` |
| 114 | +
|
| 115 | +:ref:`SPI transaction manager API reference <api_bm_spi_mngr>` |
0 commit comments