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