1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_dspi_edma.h"
10 
11 /***********************************************************************************************************************
12  * Definitions
13  ***********************************************************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.dspi_edma"
18 #endif
19 
20 /*!
21  * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private.
22  */
23 typedef struct _dspi_master_edma_private_handle
24 {
25     SPI_Type *base;                    /*!< DSPI peripheral base address. */
26     dspi_master_edma_handle_t *handle; /*!< dspi_master_edma_handle_t handle */
27 } dspi_master_edma_private_handle_t;
28 
29 /*!
30  * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private.
31  */
32 typedef struct _dspi_slave_edma_private_handle
33 {
34     SPI_Type *base;                   /*!< DSPI peripheral base address. */
35     dspi_slave_edma_handle_t *handle; /*!< dspi_master_edma_handle_t handle */
36 } dspi_slave_edma_private_handle_t;
37 
38 /***********************************************************************************************************************
39  * Prototypes
40  ***********************************************************************************************************************/
41 /*!
42  * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA.
43  * This is not a public API.
44  */
45 static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle,
46                                     void *g_dspiEdmaPrivateHandle,
47                                     bool transferDone,
48                                     uint32_t tcds);
49 
50 /*!
51  * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA.
52  * This is not a public API.
53  */
54 static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle,
55                                    void *g_dspiEdmaPrivateHandle,
56                                    bool transferDone,
57                                    uint32_t tcds);
58 
59 /***********************************************************************************************************************
60  * Variables
61  ***********************************************************************************************************************/
62 
63 /*! @brief Pointers to dspi edma handles for each instance. */
64 static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT];
65 static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT];
66 
67 /***********************************************************************************************************************
68  * Code
69  ***********************************************************************************************************************/
70 
71 /*!
72  * brief Initializes the DSPI master eDMA handle.
73  *
74  * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs.  Usually, for a
75  * specified DSPI instance, call this API once to get the initialized handle.
76  *
77  * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX  and TX are the same source) DMA request
78  * source.
79  * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
80  * TX DMAMUX source for edmaIntermediaryToTxRegHandle.
81  * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
82  *
83  * param base DSPI peripheral base address.
84  * param handle DSPI handle pointer to dspi_master_edma_handle_t.
85  * param callback DSPI callback.
86  * param userData A callback function parameter.
87  * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
88  * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t.
89  * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t.
90  */
DSPI_MasterTransferCreateHandleEDMA(SPI_Type * base,dspi_master_edma_handle_t * handle,dspi_master_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaRxRegToRxDataHandle,edma_handle_t * edmaTxDataToIntermediaryHandle,edma_handle_t * edmaIntermediaryToTxRegHandle)91 void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
92                                          dspi_master_edma_handle_t *handle,
93                                          dspi_master_edma_transfer_callback_t callback,
94                                          void *userData,
95                                          edma_handle_t *edmaRxRegToRxDataHandle,
96                                          edma_handle_t *edmaTxDataToIntermediaryHandle,
97                                          edma_handle_t *edmaIntermediaryToTxRegHandle)
98 {
99     assert(NULL != handle);
100     assert(NULL != edmaRxRegToRxDataHandle);
101 #if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET))
102     assert(NULL != edmaTxDataToIntermediaryHandle);
103 #endif
104     assert(NULL != edmaIntermediaryToTxRegHandle);
105 
106     /* Zero the handle. */
107     (void)memset(handle, 0, sizeof(*handle));
108 
109     uint32_t instance = DSPI_GetInstance(base);
110 
111     s_dspiMasterEdmaPrivateHandle[instance].base   = base;
112     s_dspiMasterEdmaPrivateHandle[instance].handle = handle;
113 
114     handle->callback = callback;
115     handle->userData = userData;
116 
117     handle->edmaRxRegToRxDataHandle        = edmaRxRegToRxDataHandle;
118     handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle;
119     handle->edmaIntermediaryToTxRegHandle  = edmaIntermediaryToTxRegHandle;
120 }
121 
122 /*!
123  * brief DSPI master transfer data using eDMA.
124  *
125  * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
126  * is transferred, the callback function is called.
127  *
128  * note The max transfer size of each transfer depends on whether the instance's Tx/Rx shares the same DMA request. If
129  * FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) is true, then the max transfer size is 32767 datawidth of data,
130  * otherwise is 511.
131  *
132  * param base DSPI peripheral base address.
133  * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
134  * param transfer A pointer to the dspi_transfer_t structure.
135  * return status of status_t.
136  */
DSPI_MasterTransferEDMA(SPI_Type * base,dspi_master_edma_handle_t * handle,dspi_transfer_t * transfer)137 status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer)
138 {
139     assert(NULL != handle);
140     assert(NULL != transfer);
141 
142     /* If the transfer count is zero, then return immediately.*/
143     if (transfer->dataSize == 0U)
144     {
145         return kStatus_InvalidArgument;
146     }
147 
148     /* If both send buffer and receive buffer is null */
149     if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData)))
150     {
151         return kStatus_InvalidArgument;
152     }
153 
154     /* Check that we're not busy.*/
155     if (handle->state == (uint8_t)kDSPI_Busy)
156     {
157         return kStatus_DSPI_Busy;
158     }
159 
160     handle->state = (uint8_t)kDSPI_Busy;
161 
162     uint32_t instance                = DSPI_GetInstance(base);
163     uint16_t wordToSend              = 0;
164     uint8_t dummyData                = DSPI_GetDummyDataInstance(base);
165     uint8_t dataAlreadyFed           = 0;
166     uint8_t dataFedMax               = 2;
167     uint32_t tmpMCR                  = 0;
168     size_t tmpRemainingSendByteCount = 0;
169 
170     uint32_t rxAddr = DSPI_GetRxRegisterAddress(base);
171     uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base);
172 
173     edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU));
174 
175     edma_transfer_config_t transferConfigA;
176     edma_transfer_config_t transferConfigB;
177 
178     handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData;
179 
180     dspi_command_data_config_t commandStruct;
181     DSPI_StopTransfer(base);
182     DSPI_FlushFifo(base, true, true);
183     DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
184 
185     commandStruct.whichPcs =
186         (uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
187     commandStruct.isEndOfQueue       = false;
188     commandStruct.clearTransferCount = false;
189     commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
190     commandStruct.isPcsContinuous =
191         (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
192     handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
193 
194     commandStruct.isEndOfQueue = true;
195     commandStruct.isPcsContinuous =
196         (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
197     handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
198 
199     handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U;
200 
201     tmpMCR = base->MCR;
202     if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK)))
203     {
204         handle->fifoSize = 1U;
205     }
206     else
207     {
208         handle->fifoSize = (uint8_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
209     }
210     handle->txData                    = transfer->txData;
211     handle->rxData                    = transfer->rxData;
212     handle->remainingSendByteCount    = transfer->dataSize;
213     handle->remainingReceiveByteCount = transfer->dataSize;
214     handle->totalByteCount            = transfer->dataSize;
215 
216     /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer
217      * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame
218      */
219     if (transfer->dataSize > DSPI_EDMA_MAX_TRANSFER_SIZE(base, (handle->bitsPerFrame)))
220     {
221         handle->state = (uint8_t)kDSPI_Idle;
222         return kStatus_DSPI_OutOfRange;
223     }
224 
225     /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */
226     if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U))
227     {
228         handle->state = (uint8_t)kDSPI_Idle;
229         return kStatus_InvalidArgument;
230     }
231 
232     DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
233 
234     EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback,
235                      &s_dspiMasterEdmaPrivateHandle[instance]);
236 
237     /*
238     (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C.
239     channel_A minor link to channel_B , channel_B minor link to channel_C.
240 
241     Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer.
242     channel_A:SPI_POPR to rxData,
243     channel_B:next txData to handle->command (low 16 bits),
244     channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data
245     (handle->lastCommand to SPI_PUSHR).
246 
247     (2)For DSPI instances with separate RX and TX DMA requests:
248     Rx DMA request -> channel_A
249     Tx DMA request -> channel_C -> channel_B .
250     channel_C major link to channel_B.
251     So need prepare the first data in "intermediary"  before the DMA
252     transfer and then channel_B is used to prepare the next data to "intermediary"
253 
254     channel_A:SPI_POPR to rxData,
255     channel_C: handle->command (32 bits) to SPI_PUSHR,
256     channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data
257     (handle->lastCommand to handle->Command).
258     */
259 
260     /*If dspi has separate dma request , prepare the first data in "intermediary" .
261     else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/
262     if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
263     {
264         /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to
265          * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel
266          */
267 
268         /*Prepare the firt data*/
269         if (handle->bitsPerFrame > 8U)
270         {
271             /* If it's the last word */
272             if (handle->remainingSendByteCount <= 2U)
273             {
274                 if (NULL != handle->txData)
275                 {
276                     wordToSend = *(handle->txData);
277                     ++handle->txData; /* increment to next data byte */
278                     wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
279                 }
280                 else
281                 {
282                     wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
283                 }
284                 handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
285                 handle->command     = handle->lastCommand;
286             }
287             else /* For all words except the last word , frame > 8bits */
288             {
289                 if (NULL != handle->txData)
290                 {
291                     wordToSend = *(handle->txData);
292                     ++handle->txData; /* increment to next data byte */
293                     wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
294                     ++handle->txData; /* increment to next data byte */
295                 }
296                 else
297                 {
298                     wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
299                 }
300                 handle->command = (handle->command & 0xffff0000U) | wordToSend;
301             }
302         }
303         else /* Optimized for bits/frame less than or equal to one byte. */
304         {
305             if (NULL != handle->txData)
306             {
307                 wordToSend = *(handle->txData);
308                 ++handle->txData; /* increment to next data word*/
309             }
310             else
311             {
312                 wordToSend = dummyData;
313             }
314 
315             if (handle->remainingSendByteCount == 1U)
316             {
317                 handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
318                 handle->command     = handle->lastCommand;
319             }
320             else
321             {
322                 handle->command = (handle->command & 0xffff0000U) | wordToSend;
323             }
324         }
325     }
326 
327     else /*dspi has shared dma request*/
328     {
329         /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to
330          * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel.
331          */
332 
333         /* If bits/frame is greater than one byte */
334         if (handle->bitsPerFrame > 8U)
335         {
336             while ((uint32_t)kDSPI_TxFifoFillRequestFlag ==
337                    (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
338             {
339                 if (handle->remainingSendByteCount <= 2U)
340                 {
341                     if (NULL != handle->txData)
342                     {
343                         wordToSend = *(handle->txData);
344                         ++handle->txData;
345                         wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
346                     }
347                     else
348                     {
349                         wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
350                     }
351                     handle->remainingSendByteCount = 0;
352                     base->PUSHR                    = (handle->lastCommand & 0xffff0000U) | wordToSend;
353                 }
354                 /* For all words except the last word */
355                 else
356                 {
357                     if (NULL != handle->txData)
358                     {
359                         wordToSend = *(handle->txData);
360                         ++handle->txData;
361                         wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
362                         ++handle->txData;
363                     }
364                     else
365                     {
366                         wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
367                     }
368                     handle->remainingSendByteCount -= 2U;
369                     base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
370                 }
371 
372                 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
373                 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
374 
375                 dataAlreadyFed += 2U;
376 
377                 /* exit loop if send count is zero, else update local variables for next loop */
378                 if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U)))
379                 {
380                     break;
381                 }
382             } /* End of TX FIFO fill while loop */
383         }
384         else /* Optimized for bits/frame less than or equal to one byte. */
385         {
386             while ((uint32_t)kDSPI_TxFifoFillRequestFlag ==
387                    (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
388             {
389                 if (NULL != handle->txData)
390                 {
391                     wordToSend = *(handle->txData);
392                     ++handle->txData;
393                 }
394                 else
395                 {
396                     wordToSend = dummyData;
397                 }
398 
399                 if (handle->remainingSendByteCount == 1U)
400                 {
401                     base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend;
402                 }
403                 else
404                 {
405                     base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
406                 }
407 
408                 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
409                 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
410 
411                 --handle->remainingSendByteCount;
412 
413                 dataAlreadyFed++;
414 
415                 /* exit loop if send count is zero, else update local variables for next loop */
416                 if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax))
417                 {
418                     break;
419                 }
420             } /* End of TX FIFO fill while loop */
421         }
422     }
423 
424     /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/
425     EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
426 
427     transferConfigA.srcAddr   = (uint32_t)rxAddr;
428     transferConfigA.srcOffset = 0;
429 
430     if (NULL != handle->rxData)
431     {
432         transferConfigA.destAddr   = (uint32_t) & (handle->rxData[0]);
433         transferConfigA.destOffset = 1;
434     }
435     else
436     {
437         transferConfigA.destAddr   = (uint32_t) & (handle->rxBuffIfNull);
438         transferConfigA.destOffset = 0;
439     }
440 
441     transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes;
442 
443     if (handle->bitsPerFrame <= 8U)
444     {
445         transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes;
446         transferConfigA.minorLoopBytes  = 1;
447         transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount;
448     }
449     else
450     {
451         transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes;
452         transferConfigA.minorLoopBytes  = 2;
453         transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U;
454     }
455 
456     /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
457     handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes);
458 
459     EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
460                            (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL);
461     EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
462                                  (uint32_t)kEDMA_MajorInterruptEnable);
463 
464     if (handle->remainingSendByteCount == 0U)
465     {
466         EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
467         DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable);
468         DSPI_StartTransfer(base);
469         return kStatus_Success;
470     }
471 
472     tmpRemainingSendByteCount = handle->remainingSendByteCount;
473     /*Calculate the last data : handle->lastCommand*/
474     if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
475         ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) ||
476           ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) &&
477          (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))))
478     {
479         if (NULL != handle->txData)
480         {
481             uint32_t bufferIndex = 0;
482 
483             if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
484             {
485                 if (handle->bitsPerFrame <= 8U)
486                 {
487                     bufferIndex = handle->remainingSendByteCount - 1U;
488                 }
489                 else
490                 {
491                     bufferIndex = handle->remainingSendByteCount - 2U;
492                 }
493             }
494             else
495             {
496                 bufferIndex = handle->remainingSendByteCount;
497             }
498 
499             uint32_t tmpLastCommand = handle->lastCommand;
500             uint8_t *tmpTxData      = handle->txData;
501 
502             if (handle->bitsPerFrame <= 8U)
503             {
504                 tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U];
505             }
506             else
507             {
508                 tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) |
509                                  tmpTxData[bufferIndex - 2U];
510             }
511 
512             handle->lastCommand = tmpLastCommand;
513         }
514         else
515         {
516             if (handle->bitsPerFrame <= 8U)
517             {
518                 wordToSend = dummyData;
519             }
520             else
521             {
522                 wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData);
523             }
524             handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
525         }
526     }
527 
528 /* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO,
529  * allowing a single write to the command word followed by multiple writes to the transmit word.
530  * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the
531  * transmit word into a 32-bit write that pushes both the command word and transmit word into
532  * the TX FIFO (PUSH TX FIFO Register In Master Mode)
533  * So, if this feature is supported, we can use use one channel to carry the receive data from
534  * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer
535  * to transmit register,and use the scatter/gather function to prepare the last data.
536  * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data.
537  */
538 #if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET
539     /*  For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data
540      * (handle->lastCommand) to PUSHR register.
541      */
542 
543     EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel);
544 
545     if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) ||
546         ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))))
547     {
548         transferConfigB.srcAddr          = (uint32_t) & (handle->lastCommand);
549         transferConfigB.destAddr         = (uint32_t)txAddr;
550         transferConfigB.srcTransferSize  = kEDMA_TransferSize4Bytes;
551         transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes;
552         transferConfigB.srcOffset        = 0;
553         transferConfigB.destOffset       = 0;
554         transferConfigB.minorLoopBytes   = 4;
555         transferConfigB.majorLoopCounts  = 1;
556 
557         EDMA_TcdReset(softwareTCD);
558         EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL);
559     }
560 
561     /*User_Send_Buffer(txData) to PUSHR register. */
562     if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) ||
563         ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U)))
564     {
565         if (handle->txData)
566         {
567             if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
568             {
569                 /* For DSPI with separate RX and TX DMA requests, one frame data has been carry
570                  * to handle->command, so need to reduce the pointer of txData.
571                  */
572                 transferConfigB.srcAddr =
573                     (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U)));
574                 transferConfigB.srcOffset = 1;
575             }
576             else
577             {
578                 /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry
579                  * to PUSHR register, so no need to change the pointer of txData.
580                  */
581                 transferConfigB.srcAddr   = (uint32_t)((uint8_t *)(handle->txData));
582                 transferConfigB.srcOffset = 1;
583             }
584         }
585         else
586         {
587             transferConfigB.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
588             transferConfigB.srcOffset = 0;
589         }
590 
591         transferConfigB.destAddr   = (uint32_t)txAddr;
592         transferConfigB.destOffset = 0;
593 
594         transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes;
595 
596         if (handle->bitsPerFrame <= 8U)
597         {
598             transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes;
599             transferConfigB.minorLoopBytes   = 1;
600 
601             transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U;
602         }
603         else
604         {
605             transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes;
606             transferConfigB.minorLoopBytes   = 2;
607             transferConfigB.majorLoopCounts  = (handle->remainingSendByteCount / 2U) - 1U;
608         }
609 
610         EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
611                                handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD);
612     }
613     /* If only one word to transmit, only carry the lastcommand. */
614     else
615     {
616         EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
617                                handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL);
618     }
619 
620     /*Start the EDMA channel_A , channel_C. */
621     EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
622     EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle);
623 
624     /* Set the channel link.
625      * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the
626      * receive register, and then carry transmit data to PUSHER register.
627      * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link.
628      */
629     if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
630     {
631         /*Set channel priority*/
632         uint8_t channelPriorityLow  = handle->edmaRxRegToRxDataHandle->channel;
633         uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel;
634         uint8_t t                   = 0;
635 
636         if (channelPriorityLow > channelPriorityHigh)
637         {
638             t                   = channelPriorityLow;
639             channelPriorityLow  = channelPriorityHigh;
640             channelPriorityHigh = t;
641         }
642 
643         edma_channel_Preemption_config_t preemption_config_t;
644         preemption_config_t.enableChannelPreemption = true;
645         preemption_config_t.enablePreemptAbility    = true;
646         preemption_config_t.channelPriority         = channelPriorityLow;
647 
648         EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
649                                         &preemption_config_t);
650 
651         preemption_config_t.channelPriority = channelPriorityHigh;
652         EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
653                                         handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
654         /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to
655           channelC to carry the next data to PUSHER register.(txData to PUSHER) */
656         if (handle->remainingSendByteCount > 0U)
657         {
658             EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
659                                 kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel);
660         }
661     }
662 
663     DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
664 
665     /* Setup control info to PUSHER register. */
666     *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U);
667 #else
668 
669     /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should
670     write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the
671     SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */
672 
673     EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel);
674 
675     /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data
676      * (handle->lastCommand) to handle->Command*/
677     if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
678     {
679         transferConfigB.srcAddr          = (uint32_t) & (handle->lastCommand);
680         transferConfigB.destAddr         = (uint32_t) & (handle->command);
681         transferConfigB.srcTransferSize  = kEDMA_TransferSize4Bytes;
682         transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes;
683         transferConfigB.srcOffset        = 0;
684         transferConfigB.destOffset       = 0;
685         transferConfigB.minorLoopBytes   = 4;
686         transferConfigB.majorLoopCounts  = 1;
687 
688         EDMA_TcdReset(softwareTCD);
689         EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL);
690     }
691 
692     tmpRemainingSendByteCount = handle->remainingSendByteCount;
693     /*User_Send_Buffer(txData) to intermediary(handle->command)*/
694     if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) ||
695           ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) &&
696          (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
697         (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
698     {
699         if (NULL != handle->txData)
700         {
701             transferConfigB.srcAddr   = (uint32_t)(handle->txData);
702             transferConfigB.srcOffset = 1;
703         }
704         else
705         {
706             transferConfigB.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
707             transferConfigB.srcOffset = 0;
708         }
709 
710         transferConfigB.destAddr   = (uint32_t)(&handle->command);
711         transferConfigB.destOffset = 0;
712 
713         transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes;
714 
715         if (handle->bitsPerFrame <= 8U)
716         {
717             transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes;
718             transferConfigB.minorLoopBytes   = 1;
719 
720             if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
721             {
722                 transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U;
723             }
724             else
725             {
726                 /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is
727                 majorlink , the majorlink would not trigger the channel_C*/
728                 transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U;
729             }
730         }
731         else
732         {
733             transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes;
734             transferConfigB.minorLoopBytes   = 2;
735             if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
736             {
737                 transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U;
738             }
739             else
740             {
741                 /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is
742                  * majorlink*/
743                 transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U;
744             }
745         }
746 
747         if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
748         {
749             EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
750                                    handle->edmaTxDataToIntermediaryHandle->channel,
751                                    (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD);
752             EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base,
753                                        handle->edmaIntermediaryToTxRegHandle->channel, false);
754         }
755         else
756         {
757             EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
758                                    handle->edmaTxDataToIntermediaryHandle->channel,
759                                    (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL);
760         }
761     }
762     else
763     {
764         EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
765                                handle->edmaTxDataToIntermediaryHandle->channel,
766                                (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL);
767     }
768 
769     /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to
770     handle the last data */
771 
772     edma_transfer_config_t transferConfigC;
773     EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel);
774 
775     tmpRemainingSendByteCount = handle->remainingSendByteCount;
776     /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data
777      * (handle->lastCommand) to SPI_PUSHR*/
778     if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U)))
779     {
780         transferConfigC.srcAddr          = (uint32_t) & (handle->lastCommand);
781         transferConfigC.destAddr         = (uint32_t)txAddr;
782         transferConfigC.srcTransferSize  = kEDMA_TransferSize4Bytes;
783         transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes;
784         transferConfigC.srcOffset        = 0;
785         transferConfigC.destOffset       = 0;
786         transferConfigC.minorLoopBytes   = 4;
787         transferConfigC.majorLoopCounts  = 1;
788 
789         EDMA_TcdReset(softwareTCD);
790         EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL);
791     }
792 
793     tmpRemainingSendByteCount = handle->remainingSendByteCount;
794     if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) ||
795         ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) ||
796         (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
797     {
798         transferConfigC.srcAddr  = (uint32_t)(&(handle->command));
799         transferConfigC.destAddr = (uint32_t)txAddr;
800 
801         transferConfigC.srcTransferSize  = kEDMA_TransferSize4Bytes;
802         transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes;
803         transferConfigC.srcOffset        = 0;
804         transferConfigC.destOffset       = 0;
805         transferConfigC.minorLoopBytes   = 4;
806         if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
807         {
808             if (handle->bitsPerFrame <= 8U)
809             {
810                 transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U;
811             }
812             else
813             {
814                 transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U;
815             }
816 
817             EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
818                                    handle->edmaIntermediaryToTxRegHandle->channel,
819                                    (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD);
820         }
821         else
822         {
823             transferConfigC.majorLoopCounts = 1;
824 
825             EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
826                                    handle->edmaIntermediaryToTxRegHandle->channel,
827                                    (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL);
828         }
829 
830         EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base,
831                                    handle->edmaIntermediaryToTxRegHandle->channel, false);
832     }
833     else
834     {
835         EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
836                                handle->edmaIntermediaryToTxRegHandle->channel,
837                                (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL);
838     }
839 
840     /*Start the EDMA channel_A , channel_B , channel_C transfer*/
841     EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
842     EDMA_StartTransfer(handle->edmaTxDataToIntermediaryHandle);
843     EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle);
844 
845     /*Set channel priority*/
846     uint8_t channelPriorityLow  = handle->edmaRxRegToRxDataHandle->channel;
847     uint8_t channelPriorityMid  = handle->edmaTxDataToIntermediaryHandle->channel;
848     uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel;
849     uint8_t t                   = 0;
850     if (channelPriorityLow > channelPriorityMid)
851     {
852         t                  = channelPriorityLow;
853         channelPriorityLow = channelPriorityMid;
854         channelPriorityMid = t;
855     }
856 
857     if (channelPriorityLow > channelPriorityHigh)
858     {
859         t                   = channelPriorityLow;
860         channelPriorityLow  = channelPriorityHigh;
861         channelPriorityHigh = t;
862     }
863 
864     if (channelPriorityMid > channelPriorityHigh)
865     {
866         t                   = channelPriorityMid;
867         channelPriorityMid  = channelPriorityHigh;
868         channelPriorityHigh = t;
869     }
870     edma_channel_Preemption_config_t preemption_config_t;
871     preemption_config_t.enableChannelPreemption = true;
872     preemption_config_t.enablePreemptAbility    = true;
873     preemption_config_t.channelPriority         = channelPriorityLow;
874 
875     if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
876     {
877         EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
878                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
879 
880         preemption_config_t.channelPriority = channelPriorityMid;
881         EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base,
882                                         handle->edmaTxDataToIntermediaryHandle->channel,
883                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
884 
885         preemption_config_t.channelPriority = channelPriorityHigh;
886         EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
887                                         handle->edmaIntermediaryToTxRegHandle->channel,
888                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
889     }
890     else
891     {
892         EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
893                                         handle->edmaIntermediaryToTxRegHandle->channel,
894                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
895 
896         preemption_config_t.channelPriority = channelPriorityMid;
897         EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base,
898                                         handle->edmaTxDataToIntermediaryHandle->channel,
899                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
900 
901         preemption_config_t.channelPriority = channelPriorityHigh;
902         EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
903                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
904     }
905 
906     /*Set the channel link.*/
907     if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
908     {
909         /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB
910         to prepare the next 32bits data (txData to handle->command) */
911         if (handle->remainingSendByteCount > 1U)
912         {
913             EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base,
914                                 handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink,
915                                 handle->edmaTxDataToIntermediaryHandle->channel);
916         }
917 
918         DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
919     }
920     else
921     {
922         if (handle->remainingSendByteCount > 0U)
923         {
924             EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
925                                 kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel);
926 
927             EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base,
928                                 handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink,
929                                 handle->edmaIntermediaryToTxRegHandle->channel);
930         }
931 
932         DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable);
933     }
934 #endif
935     DSPI_StartTransfer(base);
936 
937     return kStatus_Success;
938 }
939 
940 /*!
941  * brief Transfers a block of data using a eDMA method.
942  *
943  * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function,
944  * which returns right away. When all data is transferred, the callback function is called.
945  *
946  * param base DSPI base pointer
947  * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
948  * param transfer A pointer to the dspi_half_duplex_transfer_t structure.
949  * return status of status_t.
950  */
DSPI_MasterHalfDuplexTransferEDMA(SPI_Type * base,dspi_master_edma_handle_t * handle,dspi_half_duplex_transfer_t * xfer)951 status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
952                                            dspi_master_edma_handle_t *handle,
953                                            dspi_half_duplex_transfer_t *xfer)
954 {
955     assert(NULL != xfer);
956     assert(NULL != handle);
957     dspi_transfer_t tempXfer = {0};
958     status_t status;
959 
960     if (true == xfer->isTransmitFirst)
961     {
962         tempXfer.txData   = xfer->txData;
963         tempXfer.rxData   = NULL;
964         tempXfer.dataSize = xfer->txDataSize;
965     }
966     else
967     {
968         tempXfer.txData   = NULL;
969         tempXfer.rxData   = xfer->rxData;
970         tempXfer.dataSize = xfer->rxDataSize;
971     }
972     /* If the pcs pin keep assert between transmit and receive. */
973     if (true == xfer->isPcsAssertInTransfer)
974     {
975         tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer;
976     }
977     else
978     {
979         tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer);
980     }
981 
982     status = DSPI_MasterTransferBlocking(base, &tempXfer);
983     if (status != kStatus_Success)
984     {
985         return status;
986     }
987 
988     if (true == xfer->isTransmitFirst)
989     {
990         tempXfer.txData   = NULL;
991         tempXfer.rxData   = xfer->rxData;
992         tempXfer.dataSize = xfer->rxDataSize;
993     }
994     else
995     {
996         tempXfer.txData   = xfer->txData;
997         tempXfer.rxData   = NULL;
998         tempXfer.dataSize = xfer->txDataSize;
999     }
1000     tempXfer.configFlags = xfer->configFlags;
1001 
1002     status = DSPI_MasterTransferEDMA(base, handle, &tempXfer);
1003 
1004     return status;
1005 }
EDMA_DspiMasterCallback(edma_handle_t * edmaHandle,void * g_dspiEdmaPrivateHandle,bool transferDone,uint32_t tcds)1006 static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle,
1007                                     void *g_dspiEdmaPrivateHandle,
1008                                     bool transferDone,
1009                                     uint32_t tcds)
1010 {
1011     assert(NULL != edmaHandle);
1012     assert(NULL != g_dspiEdmaPrivateHandle);
1013 
1014     dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle;
1015 
1016     dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle;
1017 
1018     DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
1019 
1020     dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle;
1021 
1022     if (NULL != dspiEdmaPrivateHandle->handle->callback)
1023     {
1024         dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle,
1025                                                 kStatus_Success, dspiEdmaPrivateHandle->handle->userData);
1026     }
1027 }
1028 
1029 /*!
1030  * brief DSPI master aborts a transfer which is using eDMA.
1031  *
1032  * This function aborts a transfer which is using eDMA.
1033  *
1034  * param base DSPI peripheral base address.
1035  * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
1036  */
DSPI_MasterTransferAbortEDMA(SPI_Type * base,dspi_master_edma_handle_t * handle)1037 void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle)
1038 {
1039     assert(NULL != handle);
1040 
1041     DSPI_StopTransfer(base);
1042 
1043     DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
1044 
1045     EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
1046     EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle);
1047     EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle);
1048 
1049     handle->state = (uint8_t)kDSPI_Idle;
1050 }
1051 
1052 /*!
1053  * brief Gets the master eDMA transfer count.
1054  *
1055  * This function gets the master eDMA transfer count.
1056  *
1057  * param base DSPI peripheral base address.
1058  * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state.
1059  * param count A number of bytes transferred by the non-blocking transaction.
1060  * return status of status_t.
1061  */
DSPI_MasterTransferGetCountEDMA(SPI_Type * base,dspi_master_edma_handle_t * handle,size_t * count)1062 status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count)
1063 {
1064     assert(NULL != handle);
1065 
1066     if (NULL == count)
1067     {
1068         return kStatus_InvalidArgument;
1069     }
1070 
1071     /* Catch when there is not an active transfer. */
1072     if (handle->state != (uint8_t)kDSPI_Busy)
1073     {
1074         *count = 0;
1075         return kStatus_NoTransferInProgress;
1076     }
1077 
1078     size_t bytes;
1079 
1080     bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
1081                                                                        handle->edmaRxRegToRxDataHandle->channel);
1082 
1083     *count = handle->totalByteCount - bytes;
1084 
1085     return kStatus_Success;
1086 }
1087 
1088 /*!
1089  * brief Initializes the DSPI slave eDMA handle.
1090  *
1091  * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs.  Usually, for a
1092  * specified DSPI instance, call this API once to get the initialized handle.
1093  *
1094  * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX  and TX are the same source) DMA request
1095  * source.
1096  * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and
1097  * TX DMAMUX source for edmaTxDataToTxRegHandle.
1098  * (2)For the shared DMA request source,  enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle.
1099  *
1100  * param base DSPI peripheral base address.
1101  * param handle DSPI handle pointer to dspi_slave_edma_handle_t.
1102  * param callback DSPI callback.
1103  * param userData A callback function parameter.
1104  * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
1105  * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
1106  */
DSPI_SlaveTransferCreateHandleEDMA(SPI_Type * base,dspi_slave_edma_handle_t * handle,dspi_slave_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaRxRegToRxDataHandle,edma_handle_t * edmaTxDataToTxRegHandle)1107 void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base,
1108                                         dspi_slave_edma_handle_t *handle,
1109                                         dspi_slave_edma_transfer_callback_t callback,
1110                                         void *userData,
1111                                         edma_handle_t *edmaRxRegToRxDataHandle,
1112                                         edma_handle_t *edmaTxDataToTxRegHandle)
1113 {
1114     assert(NULL != handle);
1115     assert(NULL != edmaRxRegToRxDataHandle);
1116     assert(NULL != edmaTxDataToTxRegHandle);
1117 
1118     /* Zero the handle. */
1119     (void)memset(handle, 0, sizeof(*handle));
1120 
1121     uint32_t instance = DSPI_GetInstance(base);
1122 
1123     s_dspiSlaveEdmaPrivateHandle[instance].base   = base;
1124     s_dspiSlaveEdmaPrivateHandle[instance].handle = handle;
1125 
1126     handle->callback = callback;
1127     handle->userData = userData;
1128 
1129     handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
1130     handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
1131 }
1132 
1133 /*!
1134  * brief DSPI slave transfer data using eDMA.
1135  *
1136  * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
1137  * is transferred, the callback function is called.
1138  * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater
1139  * than eight.
1140  *
1141  * note The max transfer size of each transfer depends on whether the instance's Tx/Rx shares the same DMA request. If
1142  * FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) is true, then the max transfer size is 32767 datawidth of data,
1143  * otherwise is 511.
1144  *
1145  * param base DSPI peripheral base address.
1146  * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
1147  * param transfer A pointer to the dspi_transfer_t structure.
1148  * return status of status_t.
1149  */
DSPI_SlaveTransferEDMA(SPI_Type * base,dspi_slave_edma_handle_t * handle,dspi_transfer_t * transfer)1150 status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer)
1151 {
1152     assert(NULL != handle);
1153     assert(NULL != transfer);
1154 
1155     /* If send/receive length is zero */
1156     if (transfer->dataSize == 0U)
1157     {
1158         return kStatus_InvalidArgument;
1159     }
1160 
1161     /* If both send buffer and receive buffer is null */
1162     if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData)))
1163     {
1164         return kStatus_InvalidArgument;
1165     }
1166 
1167     /* Check that we're not busy.*/
1168     if (handle->state == (uint8_t)kDSPI_Busy)
1169     {
1170         return kStatus_DSPI_Busy;
1171     }
1172 
1173     handle->state = (uint8_t)kDSPI_Busy;
1174 
1175     uint32_t instance = DSPI_GetInstance(base);
1176     uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT);
1177     handle->bitsPerFrame =
1178         (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U;
1179 
1180     /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer
1181      * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame
1182      */
1183     if (transfer->dataSize > DSPI_EDMA_MAX_TRANSFER_SIZE(base, (handle->bitsPerFrame)))
1184     {
1185         handle->state = (uint8_t)kDSPI_Idle;
1186         return kStatus_DSPI_OutOfRange;
1187     }
1188 
1189     /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */
1190     if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U))
1191     {
1192         handle->state = (uint8_t)kDSPI_Idle;
1193         return kStatus_InvalidArgument;
1194     }
1195 
1196     EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]);
1197 
1198     /* Store transfer information */
1199     handle->txData                    = transfer->txData;
1200     handle->rxData                    = transfer->rxData;
1201     handle->remainingSendByteCount    = transfer->dataSize;
1202     handle->remainingReceiveByteCount = transfer->dataSize;
1203     handle->totalByteCount            = transfer->dataSize;
1204 
1205     uint32_t wordToSend    = 0;
1206     uint8_t dummyData      = DSPI_GetDummyDataInstance(base);
1207     uint8_t dataAlreadyFed = 0;
1208     uint8_t dataFedMax     = 2;
1209 
1210     uint32_t rxAddr = DSPI_GetRxRegisterAddress(base);
1211     uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base);
1212 
1213     edma_transfer_config_t transferConfigA;
1214     edma_transfer_config_t transferConfigC;
1215 
1216     DSPI_StopTransfer(base);
1217 
1218     DSPI_FlushFifo(base, true, true);
1219     DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
1220 
1221     DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
1222 
1223     DSPI_StartTransfer(base);
1224 
1225     /*if dspi has separate dma request , need not prepare data first .
1226     else (dspi has shared dma request) , send first 2 data into fifo if there is fifo or send first 1 data to
1227     slaveGetTxRegister if there is no fifo*/
1228     if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
1229     {
1230         /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to
1231          * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel.
1232          */
1233         /* If bits/frame is greater than one byte */
1234         if (handle->bitsPerFrame > 8U)
1235         {
1236             while ((uint32_t)kDSPI_TxFifoFillRequestFlag ==
1237                    (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
1238             {
1239                 if (NULL != handle->txData)
1240                 {
1241                     wordToSend = *(handle->txData);
1242                     ++handle->txData; /* Increment to next data byte */
1243 
1244                     wordToSend |= (unsigned)(*(handle->txData)) << 8U;
1245                     ++handle->txData; /* Increment to next data byte */
1246                 }
1247                 else
1248                 {
1249                     wordToSend = ((uint32_t)dummyData << 8U) | dummyData;
1250                 }
1251                 handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */
1252                 base->PUSHR_SLAVE = wordToSend;
1253 
1254                 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
1255                 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1256 
1257                 dataAlreadyFed += 2U;
1258 
1259                 /* Exit loop if send count is zero, else update local variables for next loop */
1260                 if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U)))
1261                 {
1262                     break;
1263                 }
1264             } /* End of TX FIFO fill while loop */
1265         }
1266         else /* Optimized for bits/frame less than or equal to one byte. */
1267         {
1268             while ((uint32_t)kDSPI_TxFifoFillRequestFlag ==
1269                    (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
1270             {
1271                 if (NULL != handle->txData)
1272                 {
1273                     wordToSend = *(handle->txData);
1274                     /* Increment to next data word*/
1275                     ++handle->txData;
1276                 }
1277                 else
1278                 {
1279                     wordToSend = dummyData;
1280                 }
1281 
1282                 base->PUSHR_SLAVE = wordToSend;
1283 
1284                 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
1285                 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1286                 /* Decrement remainingSendByteCount*/
1287                 --handle->remainingSendByteCount;
1288 
1289                 dataAlreadyFed++;
1290 
1291                 /* Exit loop if send count is zero, else update local variables for next loop */
1292                 if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax))
1293                 {
1294                     break;
1295                 }
1296             } /* End of TX FIFO fill while loop */
1297         }
1298     }
1299 
1300     /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/
1301     if (handle->remainingReceiveByteCount > 0U)
1302     {
1303         EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
1304 
1305         transferConfigA.srcAddr   = (uint32_t)rxAddr;
1306         transferConfigA.srcOffset = 0;
1307 
1308         if (NULL != handle->rxData)
1309         {
1310             transferConfigA.destAddr   = (uint32_t) & (handle->rxData[0]);
1311             transferConfigA.destOffset = 1;
1312         }
1313         else
1314         {
1315             transferConfigA.destAddr   = (uint32_t) & (handle->rxBuffIfNull);
1316             transferConfigA.destOffset = 0;
1317         }
1318 
1319         transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes;
1320 
1321         if (handle->bitsPerFrame <= 8U)
1322         {
1323             transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes;
1324             transferConfigA.minorLoopBytes  = 1;
1325             transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount;
1326         }
1327         else
1328         {
1329             transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes;
1330             transferConfigA.minorLoopBytes  = 2;
1331             transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U;
1332         }
1333 
1334         /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
1335         handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes);
1336 
1337         EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
1338                                (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL);
1339         EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
1340                                      (uint32_t)kEDMA_MajorInterruptEnable);
1341     }
1342 
1343     if (handle->remainingSendByteCount > 0U)
1344     {
1345         /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/
1346         EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
1347 
1348         transferConfigC.destAddr   = (uint32_t)txAddr;
1349         transferConfigC.destOffset = 0;
1350 
1351         if (NULL != handle->txData)
1352         {
1353             transferConfigC.srcAddr   = (uint32_t)(&(handle->txData[0]));
1354             transferConfigC.srcOffset = 1;
1355         }
1356         else
1357         {
1358             transferConfigC.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
1359             transferConfigC.srcOffset = 0;
1360             if (handle->bitsPerFrame <= 8U)
1361             {
1362                 handle->txBuffIfNull = dummyData;
1363             }
1364             else
1365             {
1366                 handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData;
1367             }
1368         }
1369 
1370         transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes;
1371 
1372         if (handle->bitsPerFrame <= 8U)
1373         {
1374             transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes;
1375             transferConfigC.minorLoopBytes   = 1;
1376             transferConfigC.majorLoopCounts  = handle->remainingSendByteCount;
1377         }
1378         else
1379         {
1380             transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes;
1381             transferConfigC.minorLoopBytes   = 2;
1382             transferConfigC.majorLoopCounts  = handle->remainingSendByteCount / 2U;
1383         }
1384 
1385         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1386                                (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL);
1387 
1388         EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
1389     }
1390 
1391     EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
1392 
1393     /*Set channel priority*/
1394     uint8_t channelPriorityLow  = handle->edmaRxRegToRxDataHandle->channel;
1395     uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel;
1396     uint8_t t                   = 0;
1397 
1398     if (channelPriorityLow > channelPriorityHigh)
1399     {
1400         t                   = channelPriorityLow;
1401         channelPriorityLow  = channelPriorityHigh;
1402         channelPriorityHigh = t;
1403     }
1404 
1405     edma_channel_Preemption_config_t preemption_config_t;
1406     preemption_config_t.enableChannelPreemption = true;
1407     preemption_config_t.enablePreemptAbility    = true;
1408     preemption_config_t.channelPriority         = channelPriorityLow;
1409 
1410     if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
1411     {
1412         EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
1413                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
1414 
1415         preemption_config_t.channelPriority = channelPriorityHigh;
1416         EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1417                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
1418     }
1419     else
1420     {
1421         EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1422                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
1423 
1424         preemption_config_t.channelPriority = channelPriorityHigh;
1425         EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
1426                                         (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t);
1427     }
1428 
1429     /*Set the channel link.
1430     For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_C.
1431     For DSPI instances with separate RX and TX DMA requests:
1432     Rx DMA request -> channel_A
1433     Tx DMA request -> channel_C */
1434     if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
1435     {
1436         if (handle->remainingSendByteCount > 0U)
1437         {
1438             EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
1439                                 kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel);
1440         }
1441         DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable);
1442     }
1443     else
1444     {
1445         DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
1446     }
1447 
1448     return kStatus_Success;
1449 }
1450 
EDMA_DspiSlaveCallback(edma_handle_t * edmaHandle,void * g_dspiEdmaPrivateHandle,bool transferDone,uint32_t tcds)1451 static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle,
1452                                    void *g_dspiEdmaPrivateHandle,
1453                                    bool transferDone,
1454                                    uint32_t tcds)
1455 {
1456     assert(NULL != edmaHandle);
1457     assert(NULL != g_dspiEdmaPrivateHandle);
1458 
1459     dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle;
1460 
1461     dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle;
1462 
1463     DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
1464 
1465     dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle;
1466 
1467     if (NULL != dspiEdmaPrivateHandle->handle->callback)
1468     {
1469         dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle,
1470                                                 kStatus_Success, dspiEdmaPrivateHandle->handle->userData);
1471     }
1472 }
1473 
1474 /*!
1475  * brief DSPI slave aborts a transfer which is using eDMA.
1476  *
1477  * This function aborts a transfer which is using eDMA.
1478  *
1479  * param base DSPI peripheral base address.
1480  * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
1481  */
DSPI_SlaveTransferAbortEDMA(SPI_Type * base,dspi_slave_edma_handle_t * handle)1482 void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle)
1483 {
1484     assert(NULL != handle);
1485 
1486     DSPI_StopTransfer(base);
1487 
1488     DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable);
1489 
1490     EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
1491     EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
1492 
1493     handle->state = (uint8_t)kDSPI_Idle;
1494 }
1495 
1496 /*!
1497  * brief Gets the slave eDMA transfer count.
1498  *
1499  * This function gets the slave eDMA transfer count.
1500  *
1501  * param base DSPI peripheral base address.
1502  * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state.
1503  * param count A number of bytes transferred so far by the non-blocking transaction.
1504  * return status of status_t.
1505  */
DSPI_SlaveTransferGetCountEDMA(SPI_Type * base,dspi_slave_edma_handle_t * handle,size_t * count)1506 status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count)
1507 {
1508     assert(NULL != handle);
1509 
1510     if (NULL == count)
1511     {
1512         return kStatus_InvalidArgument;
1513     }
1514 
1515     /* Catch when there is not an active transfer. */
1516     if (handle->state != (uint8_t)kDSPI_Busy)
1517     {
1518         *count = 0;
1519         return kStatus_NoTransferInProgress;
1520     }
1521 
1522     size_t bytes;
1523 
1524     bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
1525                                                                        handle->edmaRxRegToRxDataHandle->channel);
1526 
1527     *count = handle->totalByteCount - bytes;
1528 
1529     return kStatus_Success;
1530 }
1531