SPILPF3DMA.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022-2025, 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 /*!*****************************************************************************
33  * @file SPILPF3DMA.h
34  *
35  * @brief SPI driver implementation for a Low Power F3 device SPI
36  * controller using the UDMA controller.
37  *
38  * # Driver include #
39  * The SPI header file should be included in an application as follows:
40  * @code
41  * #include <ti/drivers/SPI.h> #include <ti/drivers/spi/SPILPF3DMA.h> #include
42  * <ti/drivers/dma/UDMALPF3.h>
43  * @endcode
44  *
45  * Refer to @ref SPI.h for a complete description of APIs.
46  *
47  * Note that the user also needs to include the UDMALPF3.h driver since the SPI
48  * uses uDMA in order to improve throughput.
49  *
50  * # Overview #
51  * The general SPI API should be used in application code, i.e. SPI_open()
52  * should be used instead of SPILPF3DMA_open(). The board file will define the
53  * device specific config, and casting in the general API will ensure that the
54  * correct device specific functions are called. This is also reflected in the
55  * example code in [Use Cases](@ref USE_CASES_SPI_23X0).
56  *
57  * # General Behavior #
58  * Before using SPI on Low Power F3 devices:
59  * - The SPI driver is initialized by calling SPI_init().
60  * - The SPI HW is configured and flags system dependencies (e.g. IOs, power,
61  * etc.) by calling SPI_open().
62  * - The SPI driver makes use of DMA in order to optimize throughput. This is
63  * handled directly by the SPI driver, so the application should never make
64  * any calls directly to the UDMALPF3.h driver.
65  * - This implementation supports queueing multiple transactions in callback
66  * mode. See the @ref USE_CASE_QUEUE_23X0 "queueing example."
67  * - When queueing multiple transactions that should transfer one after the
68  * other, it is recommended to use the driver in 'manual start' mode by
69  * using the #SPILPF3DMA_CMD_SET_MANUAL command. In this mode, the driver
70  * will not start any queued transfers until SPI_control() is called with
71  * the #SPILPF3DMA_CMD_MANUAL_START command. This mode is off by default and
72  * can be disabled by using command #SPILPF3DMA_CMD_CLR_MANUAL. See the
73  * @ref USE_CASE_MANUAL_START_23X0 "Manual Start Example".
74  *
75  * The following is true for peripheral operation:
76  * - RX overrun IRQ, SPI and UDMA modules are enabled by calling
77  SPI_transfer().
78  * - All received bytes are ignored after SPI_open() is called, until the
79  * first SPI_transfer().
80  * - If an RX overrun occurs or if SPI_transferCancel() is called, RX overrun
81  IRQ, SPI and UDMA modules are disabled, TX and RX FIFOs are flushed and
82  all bytes are ignored.
83  * - After a successful transfer, RX overrun IRQ and SPI module remains
84  enabled and UDMA module is disabled. SPI_transfer() must be called again
85  before RX FIFO fills up in order to avoid overflow. If the TX buffer
86  overflows, zeros will be output. It is safe to call another
87  SPI_transfer() from the transfer callback, see [Continuous Peripheral
88  Transfer] (@ref USE_CASE_CST_23X0) use case below.
89  * - The SPI driver supports partial return, that can be used if the transfer
90  * size is unknown. If #SPILPF3DMA_CMD_RETURN_PARTIAL_ENABLE is passed to
91  * SPI_control(), the transfer will end when chip select is deasserted. The
92  * #SPI_Transaction.status and the #SPI_Transaction.count will be updated to
93  * indicate whether the transfer ended due to a chip select deassertion and
94  * how many bytes were transferred. See [Peripheral Mode With Return
95  * Partial] (@ref USE_CASE_RP_23X0) use case below.
96  * - When queueing several transactions if the first is a 'short' transaction
97  * (8 or fewer frames), it is required to use
98  * @ref USE_CASE_MANUAL_START_23X0 "Manual Start mode."
99  *
100  * The following apply for controller operation:
101  * - SPI and UDMA modules are enabled by calling SPI_transfer().
102  * - If the SPI_transfer() succeeds, SPI module is enabled and UDMA module is
103  disabled.
104  * - If SPI_transferCancel() is called, SPI and UDMA modules are disabled and
105  * TX and RX FIFOs are flushed.
106  *
107  * After SPI operation has ended:
108  * - Release system dependencies for SPI by calling SPI_close().
109  *
110  * The callback function is always called in a SWI context.
111  *
112  * # Error handling #
113  * If an RX overrun occurs during peripheral operation:
114  * - If a transfer is ongoing, all bytes received up until the error occurs
115  will be returned, with the error signaled in the #SPI_Transaction.status
116  field. RX overrun IRQ, SPI and UDMA modules are then disabled, TX and RX
117  FIFOs are flushed and all bytes will be ignored until a new transfer is
118  issued.
119  * - If a transfer is not ongoing, RX overrun IRQ, SPI and UDMA modules are
120  disabled, TX and RX FIFOs are flushed and all bytes will be ignored until
121  a new transfer is issued.
122  *
123  * # Timeout #
124  * Timeout can occur in #SPI_MODE_BLOCKING, there's no timeout in
125  #SPI_MODE_CALLBACK. When in #SPI_MODE_CALLBACK, the transfer must be
126  cancelled by calling SPI_transferCancel().@n If a timeout happens in either
127  #SPI_PERIPHERAL or #SPI_CONTROLLER mode, the receive buffer will contain the
128  bytes received up until the timeout occurred. The SPI transaction status will
129  be set to #SPI_TRANSFER_FAILED. The SPI transaction count will be set to the
130  number of bytes sent/received before timeout. The remaining bytes will be
131  flushed from the TX FIFO so that the subsequent transfer can be executed
132  correctly. Note that specifying a timeout prevents the driver from performing
133  a polling transfer when in peripheral mode.
134  *
135  * # Power Management #
136  * The TI-RTOS power management framework will try to put the device into the
137  most power efficient mode whenever possible. Please see the technical
138  reference manual for further details on each power mode.
139  *
140  * The SPILPF3DMA.h driver is setting a power constraint during transfers to
141  keep the device out of standby. When the transfer has finished, the power
142  constraint is released. The following statements are valid:
143  * - After SPI_open(): the device is still allowed to enter standby.
144  * - In peripheral mode:
145  * - During SPI_transfer(): the device cannot enter standby, only idle.
146  * - After an RX overflow: device is allowed to enter standby.
147  * - After a successful SPI_transfer(): the device is allowed to enter
148  * standby, but SPI module remains enabled.
149  * - _Note_: In peripheral mode, the device might enter standby while a
150  byte is being transferred if SPI_transfer() is not called again after
151  a successful transfer. This could result in corrupt data being
152  transferred.
153  * - Application thread should typically either issue another transfer after
154  * SPI_transfer() completes successfully, or call SPI_transferCancel() to
155  * disable the SPI module and thus assuring that no data is received while
156  * entering standby.
157  * - In controller mode:
158  * - During SPI_transfer(): the device cannot enter standby, only idle.
159  * - After SPI_transfer() succeeds: the device can enter standby.
160  * - If SPI_transferCancel() is called: the device can enter standby.
161  *
162  * @note The external hardware connected to the SPI might have some pull
163  configured on the SPI lines. When the SPI is inactive, this might cause
164  leakage on the IO and the current consumption to increase. The application
165  must configure a pull configuration that aligns with the external hardware.
166  See [Ensure low power during inactive periods] (@ref USE_CASE_LPWR_23X0) for
167  code example.
168  *
169  * # SPI details #
170  * ## Chip Select #
171  * This SPI controller supports a hardware chip select pin. Refer to the user
172  * manual on how this hardware chip select pin behaves in regards to the SPI
173  * frame format.
174  *
175  * <table>
176  * <tr>
177  * <th>Chip select type</th>
178  * <th>SPI_CONTROLLER mode</th>
179  * <th>SPI_PERIPHERAL mode</th>
180  * </tr>
181  * <tr>
182  * <td>Hardware chip select</td>
183  * <td>No action is needed by the application to select the peripheral.</td>
184  * <td>See the device documentation on it's chip select requirements.</td>
185  * </tr>
186  * <tr>
187  * <td>Software chip select</td>
188  * <td>The application is responsible to ensure that correct SPI peripheral is
189  * selected before performing a SPI_transfer().</td>
190  * <td>See the device documentation on it's chip select requirements.</td>
191  * </tr>
192  * </table>
193  *
194  * ### Multiple peripherals when operating in controller mode #
195  * In a scenario where the SPI module is operating in controller mode with
196  multiple SPI peripherals, the chip select pin can be reallocated at runtime
197  to select the appropriate peripheral device. See [Controller Mode With
198  Multiple Peripherals](@ref USE_CASE_MMMS_23X0) use case below. This is only
199  relevant when chip select is a hardware chip select. Otherwise the
200  application can control the chip select pins directly using the GPIO driver.
201  *
202  * ## Data Frames #
203  *
204  * SPI data frames can be any size from 4-bits to 16-bits. If the dataSize in
205  * #SPI_Params is greater that 8-bits, then the SPILPF3DMA driver
206  * implementation will assume that the #SPI_Transaction txBuf and rxBuf point
207  * to an array of 16-bit uint16_t elements.
208  *
209  * dataSize | buffer element size |
210  * -------- | ------------------- |
211  * 4-8 bits | uint8_t |
212  * 9-16 bits | uint16_t |
213  *
214  * ## Bit Rate ##
215  * When the SPI is configured as SPI peripheral, the maximum bit rate is 12MHz.
216  *
217  * When the SPI is configured as SPI controller, the maximum bit rate is 12MHz.
218  *
219  *
220  * ## UDMA #
221  * ### Interrupts #
222  * The UDMA module generates IRQs on the SPI interrupt vector. This driver
223  automatically installs a UDMA aware Hwi (interrupt) to service the assigned
224  UDMA channels.
225  *
226  * ### Transfer Size Limit #
227  *
228  * The UDMA controller only supports data transfers of up to 1024 data frames.
229  * A transfer with more than 1024 frames will be transmitted/received in
230  * multiple 1024 sized portions until all data has been transmitted/received. A
231  * data frame can be 4 to 16 bits in length.
232  *
233  * ### Scratch Buffers #
234  * A uint16_t scratch buffer is used to allow SPI_transfers where txBuf or
235  rxBuf are NULL. Rather than requiring txBuf or rxBuf to have a dummy buffer
236  of size of the transfer count, a single-word UDMA accessible uint16_t
237  scratch buffer is used. When rxBuf is NULL, the UDMA will transfer all the
238  received SPI data into the scratch buffer as a "bit-bucket". When txBuf is
239  NULL, the scratch buffer is initialized to defaultTxBufValue so the uDMA
240  will send some known value. Each SPI driver instance uses its own scratch
241  buffer.
242  *
243  * ### TX and RX buffers #
244  * Before SPI_transfer, txBuf should be filled with the outgoing SPI data.
245  These data are sent out during the transfer, while the incoming data are
246  received into rxBuf. To save memory space, txBuf and rxBuf can be assigned
247  to the same buffer location. At the beginning of the transfer, this buffer
248  holds outgoing data. At the end of the transfer, the outgoing data are
249  overwritten and the buffer holds the received SPI data.
250  *
251  * ## Polling SPI transfers #
252  * When used in blocking mode small SPI transfers are can be done by polling
253  * the peripheral & sending data frame-by-frame. A controller device can
254  * perform the transfer immediately and return, but a peripheral will block
255  * until it receives the number of frames specified in the SPI_Transfer() call.
256  * The minDmaTransferSize field in the hardware attributes is the threshold; if
257  * the transaction count is below the threshold a polling transfer is
258  * performed; otherwise a DMA transfer is done. This is intended to reduce the
259  * overhead of setting up a DMA transfer to only send a few data frames.
260  *
261  * Notes:
262  * - Specifying a timeout prevents peripheral devices from using polling
263  transfers.
264  * - Keep in mind that during polling transfers the current task is still being
265  * executed; there is no context switch to another task.
266  *
267  * # Supported Functions #
268  * Generic API function | API function | Description
269  * ----------------------|------------------------------- |------------------------------------------------------------
270  * SPI_init() | SPICC26X4DMA_init() | Initialize SPI driver
271  * SPI_open() | SPICC26X4DMA_open() | Initialize SPI HW and set system dependencies
272  * SPI_close() | SPICC26X4DMA_close() | Disable SPI and UDMA HW and release system dependencies
273  * SPI_control() | SPICC26X4DMA_control() | Configure an already opened SPI handle
274  * SPI_transfer() | SPICC26X4DMA_transfer() | Start transfer from SPI
275  * SPI_transferCancel() | SPICC26X4DMA_transferCancel() | Cancel ongoing transfer from SPI
276  *
277  * @note All calls should go through the generic API
278  *
279  * ## Use Cases @anchor USE_CASES_SPI_23X0 ##
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_23X0 #
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. This SPI_transfer() call can be used when unknown amount of
308  * bytes shall be transferred. Note: The partial return is also possible in
309  * #SPI_MODE_CALLBACK mode. Note: Polling transfers are not available when
310  * using return partial mode.
311  * @code
312  * SPI_Handle handle;
313  * SPI_Params params;
314  * SPI_Transaction transaction;
315  * uint8_t rxBuf[100]; // Receive buffer
316  *
317  * // Init SPI and specify non-default parameters
318  * SPI_Params_init(&params);
319  * params.bitRate = 1000000;
320  * params.frameFormat = SPI_POL1_PHA1;
321  * params.mode = SPI_PERIPHERAL;
322  *
323  * // Configure the transaction
324  * transaction.count = 100;
325  * transaction.txBuf = NULL;
326  * transaction.rxBuf = rxBuf;
327  *
328  * // Open the SPI and initiate the partial read
329  * handle = SPI_open(CONFIG_SPI, &params);
330  *
331  * // Enable RETURN_PARTIAL
332  * SPI_control(handle, SPILPF3DMA_RETURN_PARTIAL_ENABLE, NULL);
333  *
334  * // Begin transfer
335  * SPI_transfer(handle, &transaction);
336  * @endcode
337  *
338  * ### Continuous Peripheral Transfer In #SPI_MODE_CALLBACK @anchor USE_CASE_CST_23X0 #
339  * This use case will configure the SPI driver to transfer continuously in
340  * #SPI_MODE_CALLBACK, 16 bytes at the time and echoing received data after
341  * every 16 bytes.
342  * @code
343  * // Callback function
344  * static void transferCallback(SPI_Handle handle, SPI_Transaction *transaction)
345  * {
346  * // Start another transfer
347  * SPI_transfer(handle, transaction);
348  * }
349  *
350  * static void taskFxn(uintptr_t a0, uintptr_t a1)
351  * {
352  * SPI_Handle handle;
353  * SPI_Params params;
354  * SPI_Transaction transaction;
355  * uint8_t buf[16]; // Receive and transmit buffer
356  *
357  * // Init SPI and specify non-default parameters
358  * SPI_Params_init(&params);
359  * params.bitRate = 1000000;
360  * params.frameFormat = SPI_POL1_PHA1;
361  * params.mode = SPI_PERIPHERAL;
362  * params.transferMode = SPI_MODE_CALLBACK;
363  * params.transferCallbackFxn = transferCallback;
364  *
365  * // Configure the transaction
366  * transaction.count = 16;
367  * transaction.txBuf = buf;
368  * transaction.rxBuf = buf;
369  *
370  * // Open the SPI and initiate the first transfer
371  * handle = SPI_open(CONFIG_SPI, &params);
372  * SPI_transfer(handle, &transaction);
373  *
374  * // Wait forever
375  * while(true);
376  * }
377  * @endcode
378  *
379  * ### Basic Controller Mode #
380  * This use case will configure a SPI controller to send the data in txBuf
381  while receiving data to rxBuf in BLOCKING_MODE.
382  * @code
383  * SPI_Handle handle;
384  * SPI_Params params;
385  * SPI_Transaction transaction;
386  * uint8_t txBuf[] = "Hello World"; // Transmit buffer
387  * uint8_t rxBuf[11]; // Receive buffer
388  *
389  * // Init SPI and specify non-default parameters
390  * SPI_Params_init(&params);
391  * params.bitRate = 1000000; params.frameFormat = SPI_POL1_PHA1;
392  * params.mode = SPI_CONTROLLER;
393  *
394  * // Configure the transaction
395  * transaction.count = sizeof(txBuf);
396  * transaction.txBuf = txBuf;
397  * transaction.rxBuf = rxBuf;
398  *
399  * // Open the SPI and perform the transfer
400  * handle = SPI_open(CONFIG_SPI, &params);
401  * SPI_transfer(handle, &transaction);
402  * @endcode
403  *
404  * ### Controller Mode With Multiple Peripherals @anchor USE_CASE_MMMS_23X0 #
405  * This use case will configure a SPI controller to send data to one peripheral
406  and then to another in BLOCKING_MODE. It is assumed that SysConfig is
407  configured so that the two chip select pins have a default setting of a high
408  output and that the #SPILPF3DMA_HWAttrs used points to one of them since the
409  SPI driver will revert to this default setting when switching the chip
410  select pin.
411  *
412  * @code
413  * // From ti_drivers_config.c
414  * // Use the sysconfig settings to make sure both pins are set to HIGH when
415  * // not in use
416  * GPIO_PinConfig gpioPinConfigs[31] = {
417  * ...
418  * GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH, // CONFIG_CSN_0
419  * ...
420  * GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH, // CONFIG_CSN_1
421  * }
422  *
423  * const SPILPF3DMA_HWAttrs SPILPF3DMAHWAttrs[CONFIG_SPI_COUNT] = {
424  * // Use SPI0 module with default chip select on CONFIG_CSN_0
425  * .baseAddr = SPI0_BASE,
426  * .intNum = INT_SPI0_COMB,
427  * .intPriority = (~0),
428  * .swiPriority = 0,
429  * .powerID = PowerLPF3_PERIPH_SPI0,
430  * .defaultTxBufValue = 0xFF,
431  * .rxChannelBitMask = UDMA_CHANNEL_1_M,
432  * .txChannelBitMask = UDMA_CHANNEL_0_M,
433  * .rxChannelEvtMux = EVTSVT_DMA_TRIG_SPI0RXTRG,
434  * .txChannelEvtMux = EVTSVT_DMA_TRIG_SPI0TXTRG,
435  * .rxChannelSubscriberId = EVTSVT_DMA_CH1,
436  * .txChannelSubscriberId = EVTSVT_DMA_CH0,
437  * .dmaTxTableEntryPri = &dmaChannel0ControlTableEntry,
438  * .dmaRxTableEntryPri = &dmaChannel1ControlTableEntry,
439  * .dmaTxTableEntryAlt = &dmaChannel0AltControlTableEntry,
440  * .dmaRxTableEntryAlt = &dmaChannel1AltControlTableEntry,
441  * .minDmaTransferSize = 10,
442  * .picoPinMux = GPIO_MUX_PORTCFG_PFUNC2,
443  * .pociPinMux = GPIO_MUX_PORTCFG_PFUNC1,
444  * .sclkPinMux = GPIO_MUX_PORTCFG_PFUNC4,
445  * .csnPinMux = GPIO_MUX_PORTCFG_PFUNC1,
446  * .picoPin = CONFIG_GPIO_SPI_CONTROLLER_PICO,
447  * .pociPin = CONFIG_GPIO_SPI_CONTROLLER_POCI,
448  * .sclkPin = CONFIG_GPIO_SPI_CONTROLLER_SCLK,
449  * .csnPin = CONFIG_SPI_CSN_0,
450  * }
451  *
452  * // From your_application.c
453  * static void taskFxn(uintptr_t a0, uintptr_t a1) {
454  * SPI_Handle handle;
455  * SPI_Params params;
456  * SPI_Transaction transaction;
457  * uint_least8_t csnPin1 = CONFIG_CSN_1;
458  * uint8_t txBuf[] = "Hello World"; // Transmit buffer
459  *
460  * // Init SPI and specify non-default parameters
461  * SPI_Params_init(&params);
462  * params.bitRate = 1000000;
463  * params.frameFormat = SPI_POL1_PHA1;
464  * params.mode = SPI_CONTROLLER;
465  *
466  * // Configure the transaction
467  * transaction.count = sizeof(txBuf);
468  * transaction.txBuf = txBuf;
469  * transaction.rxBuf = NULL;
470  *
471  * // Open the SPI and perform transfer to the first peripheral
472  * handle = SPI_open(CONFIG_SPI, &params);
473  * SPI_transfer(handle, &transaction);
474  *
475  * // Then switch chip select pin and perform transfer to the second
476  * peripheral
477  * SPI_control(handle, SPILPF3DMA_SET_CSN_PIN, &csnPin1);
478  * SPI_transfer(handle, &transaction);
479  * }
480  * @endcode
481  *
482  * ### Queueing Transactions in Callback Mode #
483  * @anchor USE_CASE_QUEUE_23X0 Below is an example of queueing three
484  * transactions
485  * @code
486  * // SPI already opened in callback mode
487  * SPI_Transaction t0, t1, t2;
488  * t0.txBuf = txBuff0; t0.rxBuf = rxBuff0; t0.count = 2000;
489  *
490  * t1.txBuf = txBuff1; t1.rxBuf = rxBuff1; t1.count = 1000;
491  *
492  * t2.txBuf = txBuff2; t2.rxBuf = NULL; t2.count = 1000;
493  *
494  * bool transferOk = false;
495  *
496  * if (SPI_transfer(spiHandle, &t0)) {
497  * if (SPI_transfer(spiHandle, &t1)) {
498  * transferOk = SPI_transfer(spiHandle, &t2);
499  * }
500  * }
501  * @endcode
502  *
503  * ### Queueing in Manual Start Mode#
504  * This example shows a peripheral device queueing two transactions that will
505  * complete one after the other. From the controller's perspective there will
506  * be one long transfer.
507  * @note Manual mode also works while the device is in #SPI_CONTROLLER mode.
508  * The control call to MANUAL_START will start the transfers.
509  *
510  * @warning Manual start mode should not be enabled or disabled while a
511  * transaction is in progress.
512  *
513  * @anchor USE_CASE_MANUAL_START_23X0
514  * @code
515  * SPI_Handle spi;
516  * SPI_Params params;
517  * SPI_Transaction t0, t1;
518  * uint8_t status = SPI_STATUS_SUCCESS;
519  *
520  * SPI_Params_init(&params);
521  * params.mode = SPI_PERIPHERAL;
522  * spi = SPI_open(CONFIG_SPI, &params);
523  *
524  * if (spi == NULL) {
525  * exit(0);
526  * }
527  *
528  * // Enable manual start mode
529  * SPI_control(spi, SPILPF3DMA_CMD_SET_MANUAL, NULL);
530  *
531  * // Queue transactions
532  * t0.txBuf = txBuff0;
533  * t0.rxBuf = rxBuff0;
534  * t0.count = 2000;
535  * if (!SPI_transfer(spi, &t0)) {
536  * status = SPI_STATUS_FAIL;
537  * }
538  *
539  * t1.txBuf = txBuff1;
540  * t1.rxBuf = rxBuff1;
541  * t1.count = 1000;
542  * if (!SPI_transfer(spi, &t1)) {
543  * status = SPI_STATUS_FAIL;
544  * }
545  *
546  * // Enable the transfers
547  * if (status == SPI_STATUS_SUCCESS) {
548  * SPI_control(spi, SPILPF3DMA_CMD_MANUAL_START, NULL);
549  * }
550  * else {
551  * status = SPI_STATUS_FAILURE;
552  * }
553  *
554  * // At this point the peripheral is ready for the controller to
555  * // start the transfer
556  * // Assume the callback implementation (not shown) posts a semaphore when
557  * // the last transaction completes
558  * sem_wait(&spiSemaphore);
559  *
560  * // Disable manual start mode
561  * SPI_control(spi, SPILPF3DMA_CMD_CLR_MANUAL, NULL);
562  *
563  * @endcode
564  *
565  * ### Ensure low power during inactive periods @anchor USE_CASE_LPWR_23X0 #
566  * External hardware connected on the SPI, i.e. SPI controller/peripheral,
567  * might have configured a pull on one or more of the SPI lines. Dependent on
568  * the hardware, it might conflict with the pull used for the Low Power F3
569  * device SPI. To avoid increased leakage and ensure the lowest possible power
570  * consumption when the SPI is inactive, the application must configure a
571  * matching pull on the SPI IOs. An example of how this can be done is shown
572  * below.
573  *
574  * @code
575  * SPI_Params params;
576  * SPI_Transaction transaction;
577  * uint8_t txBuf[] = "Heartbeat"; // Transmit buffer
578  * uint8_t rxBuf[9]; // Receive buffer
579  * uint32_t standbyDurationMs = 100;
580  *
581  * // Init SPI and specify non-default parameters
582  * SPI_Params_init(&params);
583  * params.bitRate = 1000000;
584  * params.frameFormat = SPI_POL1_PHA1;
585  * params.mode = SPI_CONTROLLER;
586  *
587  * // Configure the transaction
588  * transaction.count = sizeof(txBuf);
589  * transaction.txBuf = txBuf;
590  * transaction.rxBuf = rxBuf;
591  *
592  * // Open the SPI and perform the transfer
593  * handle = SPI_open(CONFIG_SPI_0, &params);
594  *
595  * // Apply low power sleep pull config for POCI
596  * GPIO_setConfig(CONFIG_GPIO_SPI_0_POCI, GPIO_CFG_IN_PU);
597  *
598  * // Do forever
599  * while(1) {
600  * // Transfer data
601  * SPI_transfer(handle, &transaction);
602  *
603  * // Sleep
604  * Task_sleep(standbyDurationMs*100);
605  * }
606  * @endcode
607  *
608  * ### Wake Up On Chip Select Deassertion In Peripheral Mode Using #SPI_MODE_CALLBACK #
609  * This example demonstrates using a GPIO callback on Chip Select to wake up
610  * the device to allow low power modes while waiting for a chip select edge.
611  *
612  * In sysconfig or the board file, the CSN GPIO should be configured as
613  * input/pull up with an interrupt on falling edge. Otherwise, SPI_close() will
614  * reset the pin to the wrong settings and you may see line glitches.
615  *
616  * *Note: The SPI controller must allow enough time between deasserting the
617  * chip select and the start of the transaction for the SPI peripheral to wake
618  * up and open up the SPI driver.
619  *
620  * @code
621  * // Global variables
622  * SPI_Handle spiHandle;
623  * SPI_Params spiParams;
624  * SPI_Transaction spiTransaction;
625  * const uint8_t transferSize = 8;
626  * uint8_t txBuf[8];
627  *
628  * // Chip select callback
629  * static void chipSelectCallback(uint_least8_t)
630  * {
631  * // Open SPI driver, which will override any previous GPIO configuration
632  * spiHandle = SPI_open(CONFIG_SPI, &spiParams);
633  *
634  * // Issue the transfer
635  * SPI_transfer(spiHandle, &spiTransaction);
636  * }
637  *
638  * // SPI transfer callback static void transferCallback(SPI_Handle handle,
639  * SPI_Transaction *transaction)
640  * {
641  * // Close the SPI driver
642  * SPI_close(handle);
643  *
644  * // Note: SPI_close() will reset the pin configuration, so it is
645  important to
646  // set the default values correctly in sysconfig. We just need to set
647  the
648  // callback and enable the falling edge interrupt
649  *
650  * GPIO_setCallback(CS_PIN_INDEX, chipSelectCallback);
651  * GPIO_enableInt(CS_PIN_INDEX);
652  * }
653  *
654  * // From your_application.c 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 
690 #ifndef ti_drivers_spi_SPILPF3DMA__include
691 #define ti_drivers_spi_SPILPF3DMA__include
692 
693 #include <stdint.h>
694 #include <ti/drivers/SPI.h>
696 #include <ti/drivers/dma/UDMALPF3.h>
697 #include <ti/drivers/Power.h>
698 
699 #include <ti/drivers/dpl/HwiP.h>
701 #include <ti/drivers/dpl/SwiP.h>
702 
703 #ifdef __cplusplus
704 extern "C" {
705 #endif
706 
717 /* Add SPILPF3DMA_STATUS_* macros here */
718 
739 #define SPILPF3DMA_CMD_RETURN_PARTIAL_ENABLE (SPI_CMD_RESERVED + 0)
740 
748 #define SPILPF3DMA_CMD_RETURN_PARTIAL_DISABLE (SPI_CMD_RESERVED + 1)
749 
756 #define SPILPF3DMA_CMD_SET_CSN_PIN (SPI_CMD_RESERVED + 2)
757 
763 #define SPILPF3DMA_CMD_CLEAR_CSN_PIN (SPI_CMD_RESERVED + 3)
764 
778 #define SPILPF3DMA_CMD_SET_MANUAL (SPI_CMD_RESERVED + 4)
779 
789 #define SPILPF3DMA_CMD_CLR_MANUAL (SPI_CMD_RESERVED + 5)
790 
801 #define SPILPF3DMA_CMD_MANUAL_START (SPI_CMD_RESERVED + 6)
802 
822 #define SPILPF3DMA_CMD_SET_SAMPLE_DELAY (SPI_CMD_RESERVED + 7)
823 
826 /* BACKWARDS COMPATIBILITY */
827 #define SPILPF3DMA_RETURN_PARTIAL_ENABLE SPILPF3DMA_CMD_RETURN_PARTIAL_ENABLE
828 #define SPILPF3DMA_RETURN_PARTIAL_DISABLE SPILPF3DMA_CMD_RETURN_PARTIAL_DISABLE
829 #define SPILPF3DMA_SET_CSN_PIN SPILPF3DMA_CMD_SET_CSN_PIN
830 /* END BACKWARDS COMPATIBILITY */
831 
837 extern const SPI_FxnTable SPILPF3DMA_fxnTable;
838 
848 typedef enum
849 {
853 
861 typedef enum
862 {
867 
922 typedef struct
923 {
925  uint32_t baseAddr;
932  uint32_t swiPriority;
938  volatile uDMAControlTableEntry *dmaTxTableEntryPri;
940  volatile uDMAControlTableEntry *dmaRxTableEntryPri;
942  volatile uDMAControlTableEntry *dmaTxTableEntryAlt;
944  volatile uDMAControlTableEntry *dmaRxTableEntryAlt;
946  int32_t pociPinMux;
948  int32_t picoPinMux;
950  int32_t sclkPinMux;
952  int32_t csnPinMux;
956  PowerLPF3_Resource powerID;
964  uint8_t intNum;
976  uint8_t intPriority;
978  uint_least8_t picoPin;
980  uint_least8_t pociPin;
982  uint_least8_t sclkPin;
984  uint_least8_t csnPin;
994 
1000 typedef struct
1001 {
1006 
1011 
1016 
1017  uint32_t activeChannel;
1018  uint32_t bitRate;
1019  uint32_t dataSize;
1021  uint32_t busyBit;
1022  uint32_t dsample;
1023 
1024  uint16_t rxScratchBuf;
1025  uint16_t txScratchBuf;
1026 
1029  uint8_t format;
1030  uint_least8_t csnPin;
1032  bool isOpen;
1035 
1036 #ifdef __cplusplus
1037 }
1038 #endif
1039 
1040 #endif /* ti_drivers_spi_SPILPF3DMA__include */
uint32_t busyBit
Definition: SPILPF3DMA.h:1021
volatile uDMAControlTableEntry * dmaTxTableEntryAlt
Definition: SPILPF3DMA.h:942
uint16_t rxScratchBuf
Definition: SPILPF3DMA.h:1024
volatile uDMAControlTableEntry * dmaTxTableEntryPri
Definition: SPILPF3DMA.h:938
Definition: SPILPF3DMA.h:851
HwiP structure.
Definition: HwiP.h:166
volatile uDMAControlTableEntry * dmaRxTableEntryPri
Definition: SPILPF3DMA.h:940
SPI_Transaction * headPtr
Definition: SPILPF3DMA.h:1008
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:587
SPI_Transaction * tailPtr
Definition: SPILPF3DMA.h:1009
Power_NotifyObj spiPostObj
Definition: SPILPF3DMA.h:1003
size_t framesQueued
Definition: SPILPF3DMA.h:1012
volatile uDMAControlTableEntry * dmaRxTableEntryAlt
Definition: SPILPF3DMA.h:944
SPI_TransferMode
SPI transfer mode determines the whether the SPI controller operates synchronously or asynchronously...
Definition: SPI.h:624
uint16_t txScratchBuf
Definition: SPILPF3DMA.h:1025
SPI_Transaction * completedTransfers
Definition: SPILPF3DMA.h:1010
Power Manager.
size_t priTransferSize
Definition: SPILPF3DMA.h:1014
SPI_CallbackFxn transferCallbackFxn
Definition: SPILPF3DMA.h:1007
uint_least8_t picoPin
Definition: SPILPF3DMA.h:978
uint32_t baseAddr
SPI Peripheral&#39;s base address.
Definition: SPILPF3DMA.h:925
size_t altTransferSize
Definition: SPILPF3DMA.h:1015
uint32_t txChannelBitMask
Definition: SPILPF3DMA.h:936
SemaphoreP_Struct transferComplete
Definition: SPILPF3DMA.h:1005
Definition: SPILPF3DMA.h:863
uint32_t bitRate
Definition: SPILPF3DMA.h:1018
uint32_t activeChannel
Definition: SPILPF3DMA.h:1017
HwiP_Struct hwi
Definition: SPILPF3DMA.h:1002
uint32_t rxChannelSubscriberId
Definition: SPILPF3DMA.h:992
uint32_t dsample
Definition: SPILPF3DMA.h:1022
uint32_t dataSize
Definition: SPILPF3DMA.h:1019
Semaphore module for the RTOS Porting Interface.
const SPI_FxnTable SPILPF3DMA_fxnTable
The definition of a SPI function table that contains the required set of functions to control a speci...
Definition: SPI.h:714
uint32_t rxChannelBitMask
Definition: SPILPF3DMA.h:934
uint32_t transferTimeout
Definition: SPILPF3DMA.h:1020
int32_t sclkPinMux
Definition: SPILPF3DMA.h:950
int32_t csnPinMux
Definition: SPILPF3DMA.h:952
PowerLPF3_Resource powerID
Definition: SPILPF3DMA.h:956
uint8_t txChannelEvtMux
Definition: SPILPF3DMA.h:960
SPILPF3DMA_FrameSize
Definition: SPILPF3DMA.h:848
SPILPF3DMA Object.
Definition: SPILPF3DMA.h:1000
SwiP_Struct swi
Definition: SPILPF3DMA.h:1004
Definition: SPILPF3DMA.h:850
Software Interrupt module for the RTOS Porting Interface.
A SPI_Transaction data structure is used with SPI_transfer(). It indicates how many SPI_FrameFormat f...
Definition: SPI.h:565
Power notify object structure.
Definition: Power.h:441
GPIO driver implementation for Low Power F3 devices.
SPI_Mode
Definitions for various SPI modes of operation.
Definition: SPI.h:592
uint8_t intNum
Definition: SPILPF3DMA.h:964
uint8_t rxChannelEvtMux
Definition: SPILPF3DMA.h:962
Definition: SPILPF3DMA.h:864
bool isOpen
Definition: SPILPF3DMA.h:1032
uint_least8_t sclkPin
Definition: SPILPF3DMA.h:982
int32_t pociPinMux
Definition: SPILPF3DMA.h:946
SPI_TransferMode transferMode
Definition: SPILPF3DMA.h:1027
Definition: SPILPF3DMA.h:865
uint8_t format
Definition: SPILPF3DMA.h:1029
SPILPF3DMA_ReturnPartial returnPartial
Definition: SPILPF3DMA.h:1031
uint_least8_t pociPin
Definition: SPILPF3DMA.h:980
SPILPF3DMA Hardware attributes.
Definition: SPILPF3DMA.h:922
uint8_t intPriority
SPILPF3DMA Peripheral&#39;s interrupt priority.
Definition: SPILPF3DMA.h:976
int32_t picoPinMux
Definition: SPILPF3DMA.h:948
size_t framesTransferred
Definition: SPILPF3DMA.h:1013
UDMALPF3 driver implementation.
uint32_t txChannelSubscriberId
Definition: SPILPF3DMA.h:988
Hardware Interrupt module for the RTOS Porting Interface.
uint_least8_t csnPin
Definition: SPILPF3DMA.h:1030
SemaphoreP structure.
Definition: SwiP.h:68
SPI_Mode mode
Definition: SPILPF3DMA.h:1028
uint16_t defaultTxBufValue
Definition: SPILPF3DMA.h:958
uint_least8_t csnPin
Definition: SPILPF3DMA.h:984
uint32_t swiPriority
SPI SWI priority. The higher the number, the higher the priority. The minimum is 0 and the maximum is...
Definition: SPILPF3DMA.h:932
SemaphoreP structure.
Definition: SemaphoreP.h:84
bool manualStart
Definition: SPILPF3DMA.h:1033
SPILPF3DMA_ReturnPartial
Definition: SPILPF3DMA.h:861
uint32_t minDmaTransferSize
Definition: SPILPF3DMA.h:954
© Copyright 1995-2025, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale