SPICC26X4DMA.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021-2023 Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of Texas Instruments Incorporated nor the names of
17  * its contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /* clang-format off */
33 /*!*****************************************************************************
34  * @file SPICC26X4DMA.h
35  *
36  * @brief SPI driver implementation for a CC26X4 SPI controller using
37  * the UDMA controller.
38  *
39  * # Driver include #
40  * The SPI header file should be included in an application as follows:
41  * @code
42  * #include <ti/drivers/SPI.h>
43  * #include <ti/drivers/spi/SPICC26X4DMA.h>
44  * #include <ti/drivers/dma/UDMACC26XX.h>
45  * @endcode
46  *
47  * Refer to @ref SPI.h for a complete description of APIs.
48  *
49  * Note that the user also needs to include the UDMACC26XX.h driver since the
50  * SPI uses uDMA in order to improve throughput.
51  *
52  * # Overview #
53  * The general SPI API should be used in application code, i.e. SPI_open()
54  * should be used instead of SPICC26X4DMA_open(). The board file will define the device
55  * specific config, and casting in the general API will ensure that the correct
56  * device specific functions are called.
57  * This is also reflected in the example code in [Use Cases](@ref USE_CASES_SPI_X4).
58  *
59  * # General Behavior #
60  * Before using SPI on CC26X4:
61  * - The SPI driver is initialized by calling SPI_init().
62  * - The SPI HW is configured and flags system dependencies (e.g. IOs,
63  * power, etc.) by calling SPI_open().
64  * - The SPI driver makes use of DMA in order to optimize throughput.
65  * This is handled directly by the SPI driver, so the application should never
66  * make any calls directly to the UDMACC26XX.h driver.
67  * - This implementation supports queueing multiple transactions in callback
68  * mode. See the @ref USE_CASE_QUEUE_X4 "queueing example."
69  * - When queueing multiple transactions that should transfer one after the
70  * other, it is recommended to use the driver in 'manual start' mode by using
71  * the #SPICC26X4DMA_CMD_SET_MANUAL command. In this mode, the driver will
72  * not start any queued transfers until SPI_control() is called with the
73  * #SPICC26X4DMA_CMD_MANUAL_START command. This mode is off by default and
74  * can be disabled by using command #SPICC26X4DMA_CMD_CLR_MANUAL. See the
75  * @ref USE_CASE_MANUAL_START_X4 "Manual Start Example".
76  *
77  * The following is true for peripheral operation:
78  * - RX overrun IRQ, SPI and UDMA modules are enabled by calling SPI_transfer().
79  * - All received bytes are ignored after SPI_open() is called, until
80  * the first SPI_transfer().
81  * - If an RX overrun occurs or if SPI_transferCancel() is called, RX overrun IRQ, SPI and UDMA
82  * modules are disabled, TX and RX FIFOs are flushed and all bytes are ignored.
83  * - After a successful transfer, RX overrun IRQ and SPI module remains enabled and UDMA module is disabled.
84  * SPI_transfer() must be called again before RX FIFO fills up in order to
85  * avoid overflow. If the TX buffer overflows, zeros will be output.
86  * It is safe to call another SPI_transfer() from the transfer callback,
87  * see [Continuous Peripheral Transfer] (@ref USE_CASE_CST_X4) use case below.
88  * - The SPI driver supports partial return, that can be used if the
89  * transfer size is unknown. If #SPICC26X4DMA_CMD_RETURN_PARTIAL_ENABLE is
90  * passed to SPI_control(), the transfer will end when chip select is
91  * deasserted. The #SPI_Transaction.status and the #SPI_Transaction.count
92  * will be updated to indicate whether the transfer ended due to a chip
93  * select deassertion and how many bytes were transferred. See
94  * [Peripheral Mode With Return Partial] (@ref USE_CASE_RP_X4) use case below.
95  * - When queueing several transactions if the first is a 'short'
96  * transaction (8 or fewer frames), it is required to use
97  * @ref USE_CASE_MANUAL_START_X4 "Manual Start mode."
98  *
99  * The following apply for controller operation:
100  * - SPI and UDMA modules are enabled by calling SPI_transfer().
101  * - If the SPI_transfer() succeeds, SPI module is enabled and UDMA module is disabled.
102  * - If SPI_transferCancel() is called, SPI and UDMA modules are disabled and
103  * TX and RX FIFOs are flushed.
104  *
105  * After SPI operation has ended:
106  * - Release system dependencies for SPI by calling SPI_close().
107  *
108  * The callback function is always called in a SWI context.
109  *
110  * # Error handling #
111  * If an RX overrun occurs during peripheral operation:
112  * - If a transfer is ongoing, all bytes received up until the error occurs will be returned, with the
113  * error signaled in the #SPI_Transaction.status field. RX overrun IRQ, SPI and UDMA modules are then disabled,
114  * TX and RX FIFOs are flushed and all bytes will be ignored until a new transfer is issued.
115  * - If a transfer is not ongoing, RX overrun IRQ, SPI and UDMA modules are disabled,
116  * TX and RX FIFOs are flushed and all bytes will be ignored until a new transfer is issued.
117  *
118  * # Timeout #
119  * Timeout can occur in #SPI_MODE_BLOCKING, there's no timeout in #SPI_MODE_CALLBACK.
120  * When in #SPI_MODE_CALLBACK, the transfer must be cancelled by calling SPI_transferCancel().@n
121  * If a timeout happens in either #SPI_PERIPHERAL or #SPI_CONTROLLER mode,
122  * the receive buffer will contain the bytes received up until the timeout occurred.
123  * The SPI transaction status will be set to #SPI_TRANSFER_FAILED.
124  * The SPI transaction count will be set to the number of bytes sent/received before timeout.
125  * The remaining bytes will be flushed from the TX FIFO so that the subsequent transfer
126  * can be executed correctly. Note that specifying a timeout prevents the
127  * driver from performing a polling transfer when in peripheral mode.
128  *
129  * # Power Management #
130  * The TI-RTOS power management framework will try to put the device into the most
131  * power efficient mode whenever possible. Please see the technical reference
132  * manual for further details on each power mode.
133  *
134  * The SPICC26X4DMA.h driver is setting a power constraint during transfers to keep
135  * the device out of standby. When the transfer has finished, the power
136  * constraint is released.
137  * The following statements are valid:
138  * - After SPI_open(): the device is still allowed to enter standby.
139  * - In peripheral mode:
140  * - During SPI_transfer(): the device cannot enter standby, only idle.
141  * - After an RX overflow: device is allowed to enter standby.
142  * - After a successful SPI_transfer(): the device is allowed
143  * to enter standby, but SPI module remains enabled.
144  * - _Note_: In peripheral mode, the device might enter standby while a byte is being
145  * transferred if SPI_transfer() is not called again after a successful
146  * transfer. This could result in corrupt data being transferred.
147  * - Application thread should typically either issue another transfer after
148  * SPI_transfer() completes successfully, or call
149  * SPI_transferCancel() to disable the SPI module and thus assuring that no data
150  * is received while entering standby.
151  * .
152  * - In controller mode:
153  * - During SPI_transfer(): the device cannot enter standby, only idle.
154  * - After SPI_transfer() succeeds: the device can enter standby.
155  * - If SPI_transferCancel() is called: the device can enter standby.
156  *
157  * @note The external hardware connected to the SPI might have some pull configured on the
158  * SPI lines. When the SPI is inactive, this might cause leakage on the IO and the
159  * current consumption to increase. The application must configure a pull configuration
160  * that aligns with the external hardware.
161  * See [Ensure low power during inactive periods] (@ref USE_CASE_LPWR_X4) for code example.
162  *
163  * # SPI details #
164  * ## Chip Select #
165  * This SPI controller supports a hardware chip select pin. Refer to the
166  * user manual on how this hardware chip select pin behaves in regards
167  * to the SPI frame format.
168  *
169  * <table>
170  * <tr>
171  * <th>Chip select type</th>
172  * <th>SPI_CONTROLLER mode</th>
173  * <th>SPI_PERIPHERAL mode</th>
174  * </tr>
175  * <tr>
176  * <td>Hardware chip select</td>
177  * <td>No action is needed by the application to select the peripheral.</td>
178  * <td>See the device documentation on it's chip select requirements.</td>
179  * </tr>
180  * <tr>
181  * <td>Software chip select</td>
182  * <td>The application is responsible to ensure that correct SPI peripheral is
183  * selected before performing a SPI_transfer().</td>
184  * <td>See the device documentation on it's chip select requirements.</td>
185  * </tr>
186  * </table>
187  *
188  * ### Multiple peripherals when operating in controller mode #
189  * In a scenario where the SPI module is operating in controller mode with multiple
190  * SPI peripherals, the chip select pin can be reallocated at runtime to select the
191  * appropriate peripheral device. See [Controller Mode With Multiple Peripherals](@ref USE_CASE_MMMS_X4) use case below.
192  * This is only relevant when chip select is a hardware chip select. Otherwise the application
193  * can control the chip select pins directly using the GPIO driver.
194  *
195  * ## Data Frames #
196  *
197  * When the SPI is configured as SPI controller, the data frame can be any size from 4-bits to 32-bits.
198  * When the SPI is configured as SPI peripheral , the minimum data frame is 7-bits and the maximum is 32-bits.
199  * If the dataSize in #SPI_Params is greater that 8-bits, then the SPICC26X4DMA driver
200  * implementation will assume that the #SPI_Transaction txBuf and rxBuf
201  * point to an array of 16-bit uint16_t elements. Similarly, if the dataSize in
202  * #SPI_Params is greater than 16-bits, the SPICC26X4DMA driver will assume buffers
203  * of uint32_t elements are used.
204  *
205  * dataSize | buffer element size |
206  * -------- | ------------------- |
207  * 4-8 bits | uint8_t |
208  * 9-16 bits | uint16_t |
209  * 17-32 bits | uint32_t |
210  *
211  * ## Bit Rate ##
212  * When the SPI is configured as SPI peripheral, the maximum bit rate is 8MHz.
213  *
214  * When the SPI is configured as SPI controller, the maximum bit rate is 12MHz.
215  *
216  *
217  * ## UDMA #
218  * ### Interrupts #
219  * The UDMA module generates IRQs on the SPI interrupt vector. This driver automatically
220  * installs a UDMA aware Hwi (interrupt) to service the assigned UDMA channels.
221  *
222  * ### Transfer Size Limit #
223  *
224  * The UDMA controller only supports data transfers of up to 1024 data frames.
225  * A transfer with more than 1024 frames will be transmitted/received in
226  * multiple 1024 sized portions until all data has been transmitted/received.
227  * A data frame can be 4 to 32 bits in length depending on SPI controller or peripheral mode.
228  *
229  * ### Scratch Buffers #
230  * A uint16_t scratch buffer is used to allow SPI_transfers where txBuf or rxBuf
231  * are NULL. Rather than requiring txBuf or rxBuf to have a dummy buffer of size
232  * of the transfer count, a single-word UDMA accessible uint16_t scratch buffer is used.
233  * When rxBuf is NULL, the UDMA will transfer all the received SPI data into the
234  * scratch buffer as a "bit-bucket".
235  * When txBuf is NULL, the scratch buffer is initialized to defaultTxBufValue
236  * so the uDMA will send some known value.
237  * Each SPI driver instance uses its own scratch buffer.
238  *
239  * ### TX and RX buffers #
240  * Before SPI_transfer, txBuf should be filled with the outgoing SPI data. These
241  * data are sent out during the transfer, while the incoming data are received
242  * into rxBuf. To save memory space, txBuf and rxBuf can be assigned to the same
243  * buffer location. At the beginning of the transfer, this buffer holds outgoing
244  * data. At the end of the transfer, the outgoing data are overwritten and
245  * the buffer holds the received SPI data.
246  *
247  * ## Polling SPI transfers #
248  * When used in blocking mode small SPI transfers are can be done by polling
249  * the peripheral & sending data frame-by-frame. A controller device can perform
250  * the transfer immediately and return, but a peripheral will block until it
251  * receives the number of frames specified in the SPI_Transfer() call.
252  * The minDmaTransferSize field in the hardware attributes is
253  * the threshold; if the transaction count is below the threshold a polling
254  * transfer is performed; otherwise a DMA transfer is done. This is intended
255  * to reduce the overhead of setting up a DMA transfer to only send a few
256  * data frames.
257  *
258  * Notes:
259  * - Specifying a timeout prevents peripheral devices from using polling transfers.
260  * - Keep in mind that during polling transfers the current task
261  * is still being executed; there is no context switch to another task.
262  *
263  * # Supported Functions #
264  * Generic API function | API function | Description
265  * ----------------------|------------------------------- |------------------------------------------------------------
266  * SPI_init() | SPICC26X4DMA_init() | Initialize SPI driver
267  * SPI_open() | SPICC26X4DMA_open() | Initialize SPI HW and set system dependencies
268  * SPI_close() | SPICC26X4DMA_close() | Disable SPI and UDMA HW and release system dependencies
269  * SPI_control() | SPICC26X4DMA_control() | Configure an already opened SPI handle
270  * SPI_transfer() | SPICC26X4DMA_transfer() | Start transfer from SPI
271  * SPI_transferCancel() | SPICC26X4DMA_transferCancel() | Cancel ongoing transfer from SPI
272  *
273  * @note All calls should go through the generic API
274  *
275  * # Unsupported Functionality #
276  * The SPI driver is unable to access flash memory in the address range 0x0000 - 0x2000
277  * on devices based on the Cortex M33+ core (CC26X3/CC26X4) due to security constraints.
278  *
279  * ## Use Cases @anchor USE_CASES_SPI_X4 ##
280  * ### Basic Peripheral Mode #
281  * Receive 100 bytes over SPI in #SPI_MODE_BLOCKING.
282  * @code
283  * SPI_Handle handle;
284  * SPI_Params params;
285  * SPI_Transaction transaction;
286  * uint8_t rxBuf[100]; // Receive buffer
287  *
288  * // Init SPI and specify non-default parameters
289  * SPI_Params_init(&params);
290  * params.bitRate = 1000000;
291  * params.frameFormat = SPI_POL1_PHA1;
292  * params.mode = SPI_PERIPHERAL;
293  *
294  * // Configure the transaction
295  * transaction.count = 100;
296  * transaction.txBuf = NULL;
297  * transaction.rxBuf = rxBuf;
298  *
299  * // Open the SPI and perform the transfer
300  * handle = SPI_open(CONFIG_SPI, &params);
301  * SPI_transfer(handle, &transaction);
302  * @endcode
303  *
304  * ### Peripheral Mode With Return Partial @anchor USE_CASE_RP_X4 #
305  * This use case will perform a transfer in #SPI_MODE_BLOCKING until the wanted
306  * amount of bytes is transferred or until chip select is deasserted by the SPI
307  * controller.
308  * This SPI_transfer() call can be used when unknown amount of bytes shall
309  * be transferred.
310  * <br> Note: Partial return is also possible in #SPI_MODE_CALLBACK mode.
311  * In callback mode, partial transfers can be queued by calling SPI_transfer()
312  * multiple times.
313  * <br> Note: Polling transfers are not available when using return partial mode.
314  * @code
315  * SPI_Handle handle;
316  * SPI_Params params;
317  * SPI_Transaction transaction;
318  * uint8_t rxBuf[100]; // Receive buffer
319  *
320  * // Init SPI and specify non-default parameters
321  * SPI_Params_init(&params);
322  * params.bitRate = 1000000;
323  * params.frameFormat = SPI_POL1_PHA1;
324  * params.mode = SPI_PERIPHERAL;
325  *
326  * // Configure the transaction
327  * transaction.count = 100;
328  * transaction.txBuf = NULL;
329  * transaction.rxBuf = rxBuf;
330  *
331  * // Open the SPI and initiate the partial read
332  * handle = SPI_open(CONFIG_SPI, &params);
333  *
334  * // Enable RETURN_PARTIAL
335  * SPI_control(handle, SPICC26X4DMA_RETURN_PARTIAL_ENABLE, NULL);
336  *
337  * // Begin transfer
338  * SPI_transfer(handle, &transaction);
339  * @endcode
340  *
341  * ### Continuous Peripheral Transfer In #SPI_MODE_CALLBACK @anchor USE_CASE_CST_X4 #
342  * This use case will configure the SPI driver to transfer continuously in
343  * #SPI_MODE_CALLBACK, 16 bytes at the time and echoing received data after every
344  * 16 bytes.
345  * @code
346  * // Callback function
347  * static void transferCallback(SPI_Handle handle, SPI_Transaction *transaction)
348  * {
349  * // Start another transfer
350  * SPI_transfer(handle, transaction);
351  * }
352  *
353  * static void taskFxn(uintptr_t a0, uintptr_t a1)
354  * {
355  * SPI_Handle handle;
356  * SPI_Params params;
357  * SPI_Transaction transaction;
358  * uint8_t buf[16]; // Receive and transmit buffer
359  *
360  * // Init SPI and specify non-default parameters
361  * SPI_Params_init(&params);
362  * params.bitRate = 1000000;
363  * params.frameFormat = SPI_POL1_PHA1;
364  * params.mode = SPI_PERIPHERAL;
365  * params.transferMode = SPI_MODE_CALLBACK;
366  * params.transferCallbackFxn = transferCallback;
367  *
368  * // Configure the transaction
369  * transaction.count = 16;
370  * transaction.txBuf = buf;
371  * transaction.rxBuf = buf;
372  *
373  * // Open the SPI and initiate the first transfer
374  * handle = SPI_open(CONFIG_SPI, &params);
375  * SPI_transfer(handle, &transaction);
376  *
377  * // Wait forever
378  * while(true);
379  * }
380  * @endcode
381  *
382  * ### Basic Controller Mode #
383  * This use case will configure a SPI controller to send the data in txBuf while receiving data to rxBuf in
384  * BLOCKING_MODE.
385  * @code
386  * SPI_Handle handle;
387  * SPI_Params params;
388  * SPI_Transaction transaction;
389  * uint8_t txBuf[] = "Hello World"; // Transmit buffer
390  * uint8_t rxBuf[11]; // Receive buffer
391  *
392  * // Init SPI and specify non-default parameters
393  * SPI_Params_init(&params);
394  * params.bitRate = 1000000;
395  * params.frameFormat = SPI_POL1_PHA1;
396  * params.mode = SPI_CONTROLLER;
397  *
398  * // Configure the transaction
399  * transaction.count = sizeof(txBuf);
400  * transaction.txBuf = txBuf;
401  * transaction.rxBuf = rxBuf;
402  *
403  * // Open the SPI and perform the transfer
404  * handle = SPI_open(CONFIG_SPI, &params);
405  * SPI_transfer(handle, &transaction);
406  * @endcode
407  *
408  * ### Controller Mode With Multiple Peripherals @anchor USE_CASE_MMMS_X4 #
409  * This use case will configure a SPI controller to send data to one peripheral and then to another in
410  * BLOCKING_MODE. It is assumed that SysConfig is configured so that the two chip select
411  * pins have a default setting of a high output and that the #SPICC26X4DMA_HWAttrs used points
412  * to one of them since the SPI driver will revert to this default setting when switching the
413  * chip select pin.
414  *
415  * @code
416  * // From ti_drivers_config.c
417  * // Use the sysconfig settings to make sure both pins are set to HIGH when not in use
418  * GPIO_PinConfig gpioPinConfigs[31] = {
419  * ...
420  * GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH, // CONFIG_CSN_0
421  * ...
422  * GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH, // CONFIG_CSN_1
423  * }
424  *
425  * const SPICC26X4DMA_HWAttrs SPICC26X4DMAHWAttrs[CONFIG_SPI_COUNT] = {
426  * { // Use SPI0 module with default chip select on CONFIG_CSN_0
427  * .baseAddr = SPI0_BASE,
428  * .intNum = INT_SSI0_COMB,
429  * .intPriority = (~0),
430  * .swiPriority = 0,
431  * .powerMngrId = PowerCC26XX_PERIPH_SSI0,
432  * .defaultTxBufValue = 0xFF,
433  * .rxChannelBitMask = 1<<UDMA_CHAN_SSI0_RX,
434  * .txChannelBitMask = 1<<UDMA_CHAN_SSI0_TX,
435  * .dmaTxTableEntryPri = &dmaSpi0TxControlTableEntry,
436  * .dmaRxTableEntryPri = &dmaSpi0RxControlTableEntry,
437  * .dmaTxTableEntryAlt = &dmaSpi0TxAltControlTableEntry,
438  * .dmaRxTableEntryAlt = &dmaSpi0RxAltControlTableEntry,
439  * .minDmaTransferSize = 10,
440  * .txPinMux = IOC_PORT_MCU_SSI0_TX,
441  * .rxPinMux = IOC_PORT_MCU_SSI0_RX,
442  * .clkPinMux = IOC_PORT_MCU_SSI0_CLK,
443  * .csnPinMux = IOC_PORT_MCU_SSI0_FSS,
444  * .picoPin = CONFIG_GPIO_SPI_CONTROLLER_PICO,
445  * .pociPin = CONFIG_GPIO_SPI_CONTROLLER_POCI,
446  * .clkPin = CONFIG_GPIO_SPI_CONTROLLER_SCLK,
447  * .csnPin = CONFIG_CSN_0
448  * }
449  *
450  * // From your_application.c
451  * static void taskFxn(uintptr_t a0, uintptr_t a1)
452  * {
453  * SPI_Handle handle;
454  * SPI_Params params;
455  * SPI_Transaction transaction;
456  * uint_least8_t csnPin1 = CONFIG_CSN_1;
457  * uint8_t txBuf[] = "Hello World"; // Transmit buffer
458  *
459  * // Init SPI and specify non-default parameters
460  * SPI_Params_init(&params);
461  * params.bitRate = 1000000;
462  * params.frameFormat = SPI_POL1_PHA1;
463  * params.mode = SPI_CONTROLLER;
464  *
465  * // Configure the transaction
466  * transaction.count = sizeof(txBuf);
467  * transaction.txBuf = txBuf;
468  * transaction.rxBuf = NULL;
469  *
470  * // Open the SPI and perform transfer to the first peripheral
471  * handle = SPI_open(CONFIG_SPI, &params);
472  * SPI_transfer(handle, &transaction);
473  *
474  * // Then switch chip select pin and perform transfer to the second peripheral
475  * SPI_control(handle, SPICC26X4DMA_SET_CSN_PIN, &csnPin1);
476  * SPI_transfer(handle, &transaction);
477  * }
478  * @endcode
479  *
480  * ### Queueing Transactions in Callback Mode #
481  * @anchor USE_CASE_QUEUE_X4
482  * Below is an example of queueing three transactions
483  * @code
484  * // SPI already opened in callback mode
485  * SPI_Transaction t0, t1, t2;
486  *
487  * t0.txBuf = txBuff0;
488  * t0.rxBuf = rxBuff0;
489  * t0.count = 2000;
490  *
491  * t1.txBuf = txBuff1;
492  * t1.rxBuf = rxBuff1;
493  * t1.count = 1000;
494  *
495  * t2.txBuf = txBuff2;
496  * t2.rxBuf = NULL;
497  * t2.count = 1000;
498  *
499  * bool transferOk = false;
500  *
501  * if (SPI_transfer(spiHandle, &t0)) {
502  * if (SPI_transfer(spiHandle, &t1)) {
503  * transferOk = SPI_transfer(spiHandle, &t2);
504  * }
505  * }
506  * }
507  * @endcode
508  *
509  * ### Queueing in Manual Start Mode#
510  * This example shows a peripheral device queueing two transactions that will
511  * complete one after the other. From the controller's perspective there will be
512  * one long transfer.
513  * @note Manual mode also works while the device is in #SPI_CONTROLLER mode. The
514  * control call to MANUAL_START will start the transfers.
515  *
516  * @warning Manual start mode should not be enabled or disabled while a
517  * transaction is in progress.
518  *
519  * @anchor USE_CASE_MANUAL_START_X4
520  * @code
521  * SPI_Handle spi;
522  * SPI_Params params;
523  * SPI_Transaction t0, t1;
524  * uint8_t status = SPI_STATUS_SUCCESS;
525  *
526  * SPI_Params_init(&params);
527  * params.mode = SPI_PERIPHERAL;
528  * spi = SPI_open(CONFIG_SPI, &params);
529  *
530  * if (spi == NULL) {
531  * exit(0);
532  * }
533  *
534  * // Enable manual start mode
535  * SPI_control(spi, SPICC26X4DMA_CMD_SET_MANUAL, NULL);
536  *
537  * // Queue transactions
538  * t0.txBuf = txBuff0;
539  * t0.rxBuf = rxBuff0;
540  * t0.count = 2000;
541  * if (!SPI_transfer(spi, &t0)) {
542  * status = SPI_STATUS_FAIL;
543  * }
544  *
545  * t1.txBuf = txBuff1;
546  * t1.rxBuf = rxBuff1;
547  * t1.count = 1000;
548  * if (!SPI_transfer(spi, &t1)) {
549  * status = SPI_STATUS_FAIL;
550  * }
551  *
552  * // Enable the transfers
553  * if (status == SPI_STATUS_SUCCESS) {
554  * SPI_control(spi, SPICC26X4DMA_CMD_MANUAL_START, NULL);
555  * }
556  * else {
557  * status = SPI_STATUS_FAILURE;
558  * }
559  *
560  * // At this point the peripheral is ready for the controller to start the transfer
561  * // Assume the callback implementation (not shown) posts a semaphore when
562  * // the last transaction completes
563  * sem_wait(&spiSemaphore);
564  *
565  * // Disable manual start mode
566  * SPI_control(spi, SPICC26X4DMA_CMD_CLR_MANUAL, NULL);
567  *
568  * @endcode
569  *
570  * ### Ensure low power during inactive periods @anchor USE_CASE_LPWR_X4 #
571  * External hardware connected on the SPI, i.e. SPI controller/peripheral, might have configured
572  * a pull on one or more of the SPI lines. Dependent on the hardware, it might conflict
573  * with the pull used for the CC26X4 SPI. To avoid increased leakage and ensure the lowest
574  * possible power consumption when the SPI is inactive, the application must configure a
575  * matching pull on the SPI IOs. An example of how this can be done is shown below.
576  *
577  * @code
578  * SPI_Handle handle;
579  * SPI_Params params;
580  * SPI_Transaction transaction;
581  * uint8_t txBuf[] = "Heartbeat"; // Transmit buffer
582  * uint8_t rxBuf[9]; // Receive buffer
583  * uint32_t standbyDurationMs = 100;
584  *
585  * // Init SPI and specify non-default parameters
586  * SPI_Params_init(&params);
587  * params.bitRate = 1000000;
588  * params.frameFormat = SPI_POL1_PHA1;
589  * params.mode = SPI_CONTROLLER;
590  *
591  * // Configure the transaction
592  * transaction.count = sizeof(txBuf);
593  * transaction.txBuf = txBuf;
594  * transaction.rxBuf = rxBuf;
595  *
596  * // Open the SPI and perform the transfer
597  * handle = SPI_open(CONFIG_SPI_0, &params);
598  *
599  * // Apply low power sleep pull config for POCI
600  * GPIO_setConfig(CONFIG_GPIO_SPI_0_POCI, GPIO_CFG_IN_PU);
601  *
602  * // Do forever
603  * while(1) {
604  * // Transfer data
605  * SPI_transfer(handle, &transaction);
606  * // Sleep
607  * Task_sleep(standbyDurationMs*100);
608  * }
609  * @endcode
610  *
611  * ### Wake Up On Chip Select Deassertion In Peripheral Mode Using #SPI_MODE_CALLBACK #
612  * This example demonstrates using a GPIO callback on Chip Select to wake up the device
613  * to allow low power modes while waiting for a chip select edge.
614  *
615  * In sysconfig or the board file, the CSN GPIO should be configured
616  * as input/pull up with an interrupt on falling edge. Otherwise, SPI_close()
617  * will reset the pin to the wrong settings and you may see line glitches.
618  *
619  * *Note: The SPI controller must allow enough time between deasserting the chip select and the
620  * start of the transaction for the SPI peripheral to wake up and open up the SPI driver.
621  *
622  * @code
623  * // Global variables
624  * SPI_Handle spiHandle
625  * SPI_Params spiParams;
626  * SPI_Transaction spiTransaction;
627  * const uint8_t transferSize = 8;
628  * uint8_t txBuf[8];
629  *
630  * // Chip select callback
631  * static void chipSelectCallback(uint_least8_t)
632  * {
633  * // Open SPI driver, which will override any previous GPIO configuration
634  * spiHandle = SPI_open(CONFIG_SPI, &spiParams);
635  * // Issue the transfer
636  * SPI_transfer(spiHandle, &spiTransaction);
637  * }
638  *
639  * // SPI transfer callback
640  * static void transferCallback(SPI_Handle handle, SPI_Transaction *transaction)
641  * {
642  * // Close the SPI driver
643  * SPI_close(handle);
644  *
645  * // Note: SPI_close() will reset the pin configuration, so it is important to
646  * // set the default values correctly in sysconfig. We just need to set the
647  * // callback and enable the falling edge interrupt
648  *
649  * GPIO_setCallback(CS_PIN_INDEX, chipSelectCallback);
650  * GPIO_enableInt(CS_PIN_INDEX);
651  * }
652  *
653  * // From your_application.c
654  * static void taskFxn(uintptr_t a0, uintptr_t a1)
655  * {
656  * uint8_t i;
657  *
658  * // Setup SPI params
659  * SPI_Params_init(&spiParams);
660  * spiParams.bitRate = 1000000;
661  * spiParams.frameFormat = SPI_POL1_PHA1;
662  * spiParams.mode = SPI_PERIPHERAL;
663  * spiParams.dataSize = transferSize;
664  * spiParams.transferMode = SPI_MODE_CALLBACK;
665  * spiParams.transferCallbackFxn = transferCallback;
666  *
667  * // Setup SPI transaction
668  * spiTransaction.arg = NULL;
669  * spiTransaction.count = transferSize;
670  * spiTransaction.txBuf = txBuf;
671  * spiTransaction.rxBuf = txBuf;
672  *
673  * // First echo message
674  * for (i = 0; i < transferSize; i++) {
675  * txBuf[i] = i;
676  * }
677  *
678  * // Configure chip select callback
679  * GPIO_setCallback(CS_PIN_INDEX, chipSelectCallback);
680  * GPIO_enableInt(CS_PIN_INDEX);
681  *
682  * // Wait forever
683  * while(true);
684  * }
685  * @endcode
686  *
687  * <hr>
688  */
689 /* clang-format on */
690 #ifndef ti_drivers_spi_SPICC26X4DMA__include
691 #define ti_drivers_spi_SPICC26X4DMA__include
692 
693 #include <stdint.h>
694 #include <ti/drivers/SPI.h>
696 #include <ti/drivers/Power.h>
698 
699 #include <ti/drivers/dpl/HwiP.h>
700 #include <ti/drivers/dpl/SemaphoreP.h>
701 #include <ti/drivers/dpl/SwiP.h>
702 
703 #ifdef __cplusplus
704 extern "C" {
705 #endif
706 
717 /* Add SPICC26X4DMA_STATUS_* macros here */
718 
739 #define SPICC26X4DMA_CMD_RETURN_PARTIAL_ENABLE (SPI_CMD_RESERVED + 0)
740 
748 #define SPICC26X4DMA_CMD_RETURN_PARTIAL_DISABLE (SPI_CMD_RESERVED + 1)
749 
756 #define SPICC26X4DMA_CMD_SET_CSN_PIN (SPI_CMD_RESERVED + 2)
757 
763 #define SPICC26X4DMA_CMD_CLEAR_CSN_PIN (SPI_CMD_RESERVED + 3)
764 
778 #define SPICC26X4DMA_CMD_SET_MANUAL (SPI_CMD_RESERVED + 4)
779 
789 #define SPICC26X4DMA_CMD_CLR_MANUAL (SPI_CMD_RESERVED + 5)
790 
801 #define SPICC26X4DMA_CMD_MANUAL_START (SPI_CMD_RESERVED + 6)
802 
822 #define SPICC26X4DMA_CMD_SET_SAMPLE_DELAY (SPI_CMD_RESERVED + 7)
823 
826 /* BACKWARDS COMPATIBILITY */
827 #define SPICC26X4DMA_RETURN_PARTIAL_ENABLE SPICC26X4DMA_CMD_RETURN_PARTIAL_ENABLE
828 #define SPICC26X4DMA_RETURN_PARTIAL_DISABLE SPICC26X4DMA_CMD_RETURN_PARTIAL_DISABLE
829 #define SPICC26X4DMA_SET_CSN_PIN SPICC26X4DMA_CMD_SET_CSN_PIN
830 /* END BACKWARDS COMPATIBILITY */
831 
838 
848 typedef enum
849 {
853 
861 typedef enum
862 {
867 
922 typedef struct
923 {
925  uint32_t baseAddr;
927  uint8_t intNum;
942  uint8_t intPriority;
949  uint32_t swiPriority;
951  PowerCC26XX_Resource powerMngrId;
959  volatile tDMAControlTable *dmaTxTableEntryPri;
961  volatile tDMAControlTable *dmaRxTableEntryPri;
963  volatile tDMAControlTable *dmaTxTableEntryAlt;
965  volatile tDMAControlTable *dmaRxTableEntryAlt;
967  int32_t txPinMux;
969  int32_t rxPinMux;
971  int32_t clkPinMux;
973  int32_t csnPinMux;
975  uint_least8_t picoPin;
977  uint_least8_t pociPin;
979  uint_least8_t clkPin;
981  uint_least8_t csnPin;
982 
986 
992 typedef struct
993 {
994  HwiP_Struct hwi;
996  SwiP_Struct swi;
997  SemaphoreP_Struct transferComplete;
998 
1004 
1009 
1010  uint32_t activeChannel;
1011  uint32_t bitRate;
1012  uint32_t dataSize;
1014  uint32_t busyBit;
1015  uint32_t dsample;
1016 
1017  uint16_t rxScratchBuf;
1018  uint16_t txScratchBuf;
1019 
1022  uint8_t format;
1023  uint_least8_t csnPin;
1025  bool isOpen;
1028 
1029 #ifdef __cplusplus
1030 }
1031 #endif
1032 
1033 #endif /* ti_drivers_spi_SPICC26X4DMA__include */
volatile tDMAControlTable * dmaTxTableEntryPri
Definition: SPICC26X4DMA.h:959
Definition: SPICC26X4DMA.h:850
uint32_t baseAddr
SPI Peripheral&#39;s base address.
Definition: SPICC26X4DMA.h:925
uint_least8_t csnPin
Definition: SPICC26X4DMA.h:981
Serial Peripheral Interface (SPI) Driver Interface.
void(* SPI_CallbackFxn)(SPI_Handle handle, SPI_Transaction *transaction)
The definition of a callback function used by the SPI driver when used in SPI_MODE_CALLBACK.
Definition: SPI.h:592
SPICC26X4DMA Object.
Definition: SPICC26X4DMA.h:992
uint8_t intNum
Definition: SPICC26X4DMA.h:927
SPICC26X4DMA_ReturnPartial returnPartial
Definition: SPICC26X4DMA.h:1024
PowerCC26XX_Resource powerMngrId
Definition: SPICC26X4DMA.h:951
SPI_TransferMode
SPI transfer mode determines the whether the SPI controller operates synchronously or asynchronously...
Definition: SPI.h:629
volatile tDMAControlTable * dmaRxTableEntryAlt
Definition: SPICC26X4DMA.h:965
Definition: SPICC26X4DMA.h:864
Power Manager.
Definition: SPICC26X4DMA.h:851
int32_t txPinMux
Definition: SPICC26X4DMA.h:967
UDMACC26XX Global configuration.
Definition: UDMACC26XX.h:253
Power manager interface for CC26XX/CC13XX.
uint8_t intPriority
SPI CC26X4DMA Peripheral&#39;s interrupt priority.
Definition: SPICC26X4DMA.h:942
int32_t clkPinMux
Definition: SPICC26X4DMA.h:971
uint32_t bitRate
Definition: SPICC26X4DMA.h:1011
UDMACC26XX_Handle udmaHandle
Definition: SPICC26X4DMA.h:1003
uint32_t transferTimeout
Definition: SPICC26X4DMA.h:1013
The definition of a SPI function table that contains the required set of functions to control a speci...
Definition: SPI.h:718
int32_t csnPinMux
Definition: SPICC26X4DMA.h:973
SPICC26X4DMA Hardware attributes.
Definition: SPICC26X4DMA.h:922
SPICC26X4DMA_ReturnPartial
Definition: SPICC26X4DMA.h:861
volatile tDMAControlTable * dmaTxTableEntryAlt
Definition: SPICC26X4DMA.h:963
uint8_t format
Definition: SPICC26X4DMA.h:1022
SPI_Transaction * completedTransfers
Definition: SPICC26X4DMA.h:1002
size_t altTransferSize
Definition: SPICC26X4DMA.h:1008
int32_t rxPinMux
Definition: SPICC26X4DMA.h:969
SwiP_Struct swi
Definition: SPICC26X4DMA.h:996
UDMACC26XX driver implementation.
A SPI_Transaction data structure is used with SPI_transfer(). It indicates how many SPI_FrameFormat f...
Definition: SPI.h:570
Power notify object structure.
Definition: Power.h:442
uint32_t txChannelBitMask
Definition: SPICC26X4DMA.h:957
Definition: SPICC26X4DMA.h:865
SPI_Mode
Definitions for various SPI modes of operation.
Definition: SPI.h:597
uint32_t activeChannel
Definition: SPICC26X4DMA.h:1010
uint_least8_t pociPin
Definition: SPICC26X4DMA.h:977
SPI_TransferMode transferMode
Definition: SPICC26X4DMA.h:1020
uint32_t minDmaTransferSize
Definition: SPICC26X4DMA.h:984
SPI_Mode mode
Definition: SPICC26X4DMA.h:1021
uint32_t dataSize
Definition: SPICC26X4DMA.h:1012
uint_least8_t picoPin
Definition: SPICC26X4DMA.h:975
size_t framesQueued
Definition: SPICC26X4DMA.h:1005
SPI_CallbackFxn transferCallbackFxn
Definition: SPICC26X4DMA.h:999
SPI_Transaction * headPtr
Definition: SPICC26X4DMA.h:1000
uint16_t defaultTxBufValue
Definition: SPICC26X4DMA.h:953
uint32_t busyBit
Definition: SPICC26X4DMA.h:1014
const SPI_FxnTable SPICC26X4DMA_fxnTable
uint32_t rxChannelBitMask
Definition: SPICC26X4DMA.h:955
size_t priTransferSize
Definition: SPICC26X4DMA.h:1007
size_t framesTransferred
Definition: SPICC26X4DMA.h:1006
HwiP_Struct hwi
Definition: SPICC26X4DMA.h:994
uint16_t rxScratchBuf
Definition: SPICC26X4DMA.h:1017
uint32_t swiPriority
SPI SWI priority. The higher the number, the higher the priority. The minimum is 0 and the maximum is...
Definition: SPICC26X4DMA.h:949
uint_least8_t csnPin
Definition: SPICC26X4DMA.h:1023
bool manualStart
Definition: SPICC26X4DMA.h:1026
Definition: SPICC26X4DMA.h:863
volatile tDMAControlTable * dmaRxTableEntryPri
Definition: SPICC26X4DMA.h:961
uint16_t txScratchBuf
Definition: SPICC26X4DMA.h:1018
uint32_t dsample
Definition: SPICC26X4DMA.h:1015
SPI_Transaction * tailPtr
Definition: SPICC26X4DMA.h:1001
SemaphoreP_Struct transferComplete
Definition: SPICC26X4DMA.h:997
uint_least8_t clkPin
Definition: SPICC26X4DMA.h:979
SPICC26X4DMA_FrameSize
Definition: SPICC26X4DMA.h:848
Power_NotifyObj spiPostObj
Definition: SPICC26X4DMA.h:995
bool isOpen
Definition: SPICC26X4DMA.h:1025
© Copyright 1995-2023, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale