1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lpspi_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.lpspi_edma"
18 #endif
19 
20 /*!
21  * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private.
22  */
23 typedef struct _lpspi_master_edma_private_handle
24 {
25     LPSPI_Type *base;                   /*!< LPSPI peripheral base address. */
26     lpspi_master_edma_handle_t *handle; /*!< lpspi_master_edma_handle_t handle */
27 } lpspi_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 _lpspi_slave_edma_private_handle
33 {
34     LPSPI_Type *base;                  /*!< LPSPI peripheral base address. */
35     lpspi_slave_edma_handle_t *handle; /*!< lpspi_slave_edma_handle_t handle */
36 } lpspi_slave_edma_private_handle_t;
37 
38 /***********************************************************************************************************************
39  * Prototypes
40  ***********************************************************************************************************************/
41 
42 /*!
43  * @brief EDMA_LpspiMasterCallback after the LPSPI master transfer completed by using EDMA.
44  * This is not a public API.
45  */
46 static void EDMA_LpspiMasterCallback(edma_handle_t *edmaHandle,
47                                      void *g_lpspiEdmaPrivateHandle,
48                                      bool transferDone,
49                                      uint32_t tcds);
50 
51 /*!
52  * @brief EDMA_LpspiSlaveCallback after the LPSPI slave transfer completed by using EDMA.
53  * This is not a public API.
54  */
55 static void EDMA_LpspiSlaveCallback(edma_handle_t *edmaHandle,
56                                     void *g_lpspiEdmaPrivateHandle,
57                                     bool transferDone,
58                                     uint32_t tcds);
59 
60 static void LPSPI_SeparateEdmaReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap);
61 
62 /***********************************************************************************************************************
63  * Variables
64  ***********************************************************************************************************************/
65 /*! @brief Pointers to lpspi bases for each instance. */
66 static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
67 
68 /*! @brief Pointers to lpspi edma handles for each instance. */
69 static lpspi_master_edma_private_handle_t s_lpspiMasterEdmaPrivateHandle[ARRAY_SIZE(s_lpspiBases)];
70 static lpspi_slave_edma_private_handle_t s_lpspiSlaveEdmaPrivateHandle[ARRAY_SIZE(s_lpspiBases)];
71 
72 /***********************************************************************************************************************
73  * Code
74  ***********************************************************************************************************************/
LPSPI_SeparateEdmaReadData(uint8_t * rxData,uint32_t readData,uint32_t bytesEachRead,bool isByteSwap)75 static void LPSPI_SeparateEdmaReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap)
76 {
77     assert(rxData);
78 
79     switch (bytesEachRead)
80     {
81         case 1:
82             if (!isByteSwap)
83             {
84                 *rxData = (uint8_t)readData;
85                 ++rxData;
86             }
87             else
88             {
89                 *rxData = (uint8_t)(readData >> 24);
90                 ++rxData;
91             }
92             break;
93 
94         case 2:
95             if (!isByteSwap)
96             {
97                 *rxData = (uint8_t)readData;
98                 ++rxData;
99                 *rxData = (uint8_t)(readData >> 8);
100                 ++rxData;
101             }
102             else
103             {
104                 *rxData = (uint8_t)(readData >> 16);
105                 ++rxData;
106                 *rxData = (uint8_t)(readData >> 24);
107                 ++rxData;
108             }
109             break;
110 
111         case 4:
112 
113             *rxData = (uint8_t)readData;
114             ++rxData;
115             *rxData = (uint8_t)(readData >> 8);
116             ++rxData;
117             *rxData = (uint8_t)(readData >> 16);
118             ++rxData;
119             *rxData = (uint8_t)(readData >> 24);
120             ++rxData;
121 
122             break;
123 
124         default:
125             assert(false);
126             break;
127     }
128 }
129 
130 /*!
131  * brief Initializes the LPSPI master eDMA handle.
132  *
133  * This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs.  Usually, for a
134  * specified LPSPI instance, call this API once to get the initialized handle.
135  *
136  * Note that the LPSPI eDMA has a separated (Rx and Rx as two sources) or shared (Rx  and Tx are the same source) DMA
137  * request source.
138  * (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
139  * Tx DMAMUX source for edmaIntermediaryToTxRegHandle.
140  * (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle.
141  *
142  * param base LPSPI peripheral base address.
143  * param handle LPSPI handle pointer to lpspi_master_edma_handle_t.
144  * param callback LPSPI callback.
145  * param userData callback function parameter.
146  * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
147  * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
148  */
LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,lpspi_master_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaRxRegToRxDataHandle,edma_handle_t * edmaTxDataToTxRegHandle)149 void LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type *base,
150                                           lpspi_master_edma_handle_t *handle,
151                                           lpspi_master_edma_transfer_callback_t callback,
152                                           void *userData,
153                                           edma_handle_t *edmaRxRegToRxDataHandle,
154                                           edma_handle_t *edmaTxDataToTxRegHandle)
155 {
156     assert(handle);
157     assert(edmaRxRegToRxDataHandle);
158     assert(edmaTxDataToTxRegHandle);
159 
160     /* Zero the handle. */
161     (void)memset(handle, 0, sizeof(*handle));
162 
163     uint32_t instance = LPSPI_GetInstance(base);
164 
165     s_lpspiMasterEdmaPrivateHandle[instance].base   = base;
166     s_lpspiMasterEdmaPrivateHandle[instance].handle = handle;
167 
168     handle->callback = callback;
169     handle->userData = userData;
170 
171     handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
172     handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
173 }
174 
175 /*!
176  * brief LPSPI master transfer data using eDMA.
177  *
178  * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
179  * is transferred, the callback function is called.
180  *
181  * Note:
182  * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
183  * For bytesPerFrame greater than 4:
184  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
185  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
186  *
187  * param base LPSPI peripheral base address.
188  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
189  * param transfer pointer to lpspi_transfer_t structure.
190  * return status of status_t.
191  */
LPSPI_MasterTransferEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,lpspi_transfer_t * transfer)192 status_t LPSPI_MasterTransferEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer)
193 {
194     assert(handle);
195     assert(transfer);
196 
197     uint32_t bitsPerFrame  = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1U;
198     uint32_t bytesPerFrame = (bitsPerFrame + 7U) / 8U;
199     uint32_t temp          = 0U;
200     bool isByteSwap;
201     bool isPcsContinuous;
202 
203     if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
204     {
205         return kStatus_InvalidArgument;
206     }
207 
208     /*And since the dma transfer can not support 3 bytes .*/
209     if ((bytesPerFrame % 4U) == 3U)
210     {
211         return kStatus_InvalidArgument;
212     }
213 
214     /* Check that we're not busy.*/
215     if (handle->state == (uint8_t)kLPSPI_Busy)
216     {
217         return kStatus_LPSPI_Busy;
218     }
219 
220     handle->state = (uint8_t)kLPSPI_Busy;
221 
222     uint32_t instance = LPSPI_GetInstance(base);
223     uint32_t rxAddr   = LPSPI_GetRxRegisterAddress(base);
224     uint32_t txAddr   = LPSPI_GetTxRegisterAddress(base);
225 
226     uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
227 
228     /*Because DMA is fast enough , so set the RX and TX watermarks to 0 .*/
229     uint8_t txWatermark = 0;
230     uint8_t rxWatermark = 0;
231 
232     /*Used for byte swap*/
233     uint32_t dif = 0;
234 
235     uint8_t bytesLastWrite = 0;
236 
237     bool isThereExtraTxBytes = false;
238 
239     uint8_t dummyData = g_lpspiDummyData[instance];
240 
241     edma_transfer_config_t transferConfigRx;
242     edma_transfer_config_t transferConfigTx;
243 
244     edma_tcd_t *softwareTCD_extraBytes    = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[1]) & (~0x1FU));
245     edma_tcd_t *softwareTCD_pcsContinuous = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[2]) & (~0x1FU));
246 
247     handle->txData               = transfer->txData;
248     handle->rxData               = transfer->rxData;
249     handle->txRemainingByteCount = transfer->dataSize;
250     handle->rxRemainingByteCount = transfer->dataSize;
251     handle->totalByteCount       = transfer->dataSize;
252 
253     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
254     handle->readRegRemainingTimes  = handle->writeRegRemainingTimes;
255 
256     handle->txBuffIfNull =
257         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
258 
259     /*The TX and RX FIFO sizes are always the same*/
260     handle->fifoSize = LPSPI_GetRxFifoSize(base);
261 
262     handle->isPcsContinuous = (bool)(transfer->configFlags & (uint32_t)kLPSPI_MasterPcsContinuous);
263     handle->isByteSwap      = (bool)(transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap);
264     isPcsContinuous         = handle->isPcsContinuous;
265     isByteSwap              = handle->isByteSwap;
266 
267     LPSPI_SetFifoWatermarks(base, txWatermark, rxWatermark);
268 
269     /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
270     LPSPI_Enable(base, false);
271     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
272     /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */
273     temp = base->CFGR1;
274     temp &= LPSPI_CFGR1_PINCFG_MASK;
275     if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut)))
276     {
277         if (NULL == handle->txData)
278         {
279             base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
280         }
281         /* The 3-wire mode can't send and receive data at the same time. */
282         if ((handle->txData != NULL) && (handle->rxData != NULL))
283         {
284             return kStatus_InvalidArgument;
285         }
286     }
287 
288     LPSPI_Enable(base, true);
289 
290     /*Flush FIFO , clear status , disable all the inerrupts.*/
291     LPSPI_FlushFifo(base, true, true);
292     LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
293     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
294 
295     /* For DMA transfer , we'd better not masked the transmit data and receive data in TCR since the transfer flow is
296      * hard to controlled by software.
297      */
298     base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_BYSW_MASK | LPSPI_TCR_PCS_MASK)) |
299                 LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(0U) | LPSPI_TCR_BYSW(isByteSwap) |
300                 LPSPI_TCR_PCS(whichPcs);
301 
302     isThereExtraTxBytes         = false;
303     handle->isThereExtraRxBytes = false;
304 
305     /*Calculate the bytes for write/read the TX/RX register each time*/
306     if (bytesPerFrame <= 4U)
307     {
308         handle->bytesEachWrite = (uint8_t)bytesPerFrame;
309         handle->bytesEachRead  = (uint8_t)bytesPerFrame;
310 
311         handle->bytesLastRead = (uint8_t)bytesPerFrame;
312     }
313     else
314     {
315         handle->bytesEachWrite = 4U;
316         handle->bytesEachRead  = 4U;
317 
318         handle->bytesLastRead = 4U;
319 
320         if ((transfer->dataSize % 4U) != 0U)
321         {
322             bytesLastWrite        = (uint8_t)(transfer->dataSize % 4U);
323             handle->bytesLastRead = bytesLastWrite;
324 
325             isThereExtraTxBytes = true;
326 
327             --handle->writeRegRemainingTimes;
328 
329             --handle->readRegRemainingTimes;
330             handle->isThereExtraRxBytes = true;
331         }
332     }
333 
334     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
335 
336     EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_LpspiMasterCallback,
337                      &s_lpspiMasterEdmaPrivateHandle[instance]);
338 
339     /*Rx*/
340     EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
341 
342     if (handle->rxData != NULL)
343     {
344         transferConfigRx.destAddr   = (uint32_t) & (handle->rxData[0]);
345         transferConfigRx.destOffset = 1;
346     }
347     else
348     {
349         transferConfigRx.destAddr   = (uint32_t) & (handle->rxBuffIfNull);
350         transferConfigRx.destOffset = 0;
351     }
352     transferConfigRx.destTransferSize = kEDMA_TransferSize1Bytes;
353 
354     dif = 0;
355     switch (handle->bytesEachRead)
356     {
357         case (1U):
358             transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
359             transferConfigRx.minorLoopBytes  = 1;
360             if (handle->isByteSwap)
361             {
362                 dif = 3;
363             }
364             break;
365 
366         case (2U):
367             transferConfigRx.srcTransferSize = kEDMA_TransferSize2Bytes;
368             transferConfigRx.minorLoopBytes  = 2;
369             if (handle->isByteSwap)
370             {
371                 dif = 2;
372             }
373             break;
374 
375         case (4U):
376             transferConfigRx.srcTransferSize = kEDMA_TransferSize4Bytes;
377             transferConfigRx.minorLoopBytes  = 4;
378             break;
379 
380         default:
381             transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
382             transferConfigRx.minorLoopBytes  = 1;
383             assert(false);
384             break;
385     }
386 
387     transferConfigRx.srcAddr   = (uint32_t)rxAddr + dif;
388     transferConfigRx.srcOffset = 0;
389 
390     transferConfigRx.majorLoopCounts = handle->readRegRemainingTimes;
391 
392     /* Store the initially configured eDMA minor byte transfer count into the LPSPI handle */
393     handle->nbytes = (uint8_t)transferConfigRx.minorLoopBytes;
394 
395     EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
396                            &transferConfigRx, NULL);
397     EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
398                                  (uint32_t)kEDMA_MajorInterruptEnable);
399 
400     /*Tx*/
401     EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
402 
403     if (isThereExtraTxBytes)
404     {
405         if (handle->txData != NULL)
406         {
407             transferConfigTx.srcAddr   = (uint32_t) & (transfer->txData[transfer->dataSize - bytesLastWrite]);
408             transferConfigTx.srcOffset = 1;
409         }
410         else
411         {
412             transferConfigTx.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
413             transferConfigTx.srcOffset = 0;
414         }
415 
416         transferConfigTx.destOffset = 0;
417 
418         transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
419 
420         dif = 0;
421         switch (bytesLastWrite)
422         {
423             case (1U):
424                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
425                 transferConfigTx.minorLoopBytes   = 1;
426                 if (handle->isByteSwap)
427                 {
428                     dif = 3;
429                 }
430                 break;
431 
432             case (2U):
433                 transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
434                 transferConfigTx.minorLoopBytes   = 2;
435                 if (handle->isByteSwap)
436                 {
437                     dif = 2;
438                 }
439                 break;
440 
441             default:
442                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
443                 transferConfigTx.minorLoopBytes   = 1;
444                 assert(false);
445                 break;
446         }
447 
448         transferConfigTx.destAddr        = (uint32_t)txAddr + dif;
449         transferConfigTx.majorLoopCounts = 1;
450 
451         EDMA_TcdReset(softwareTCD_extraBytes);
452 
453         if (handle->isPcsContinuous)
454         {
455             EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, softwareTCD_pcsContinuous);
456         }
457         else
458         {
459             EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, NULL);
460         }
461     }
462 
463     if (handle->isPcsContinuous)
464     {
465         handle->transmitCommand = base->TCR & ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK);
466 
467         transferConfigTx.srcAddr   = (uint32_t) & (handle->transmitCommand);
468         transferConfigTx.srcOffset = 0;
469 
470         transferConfigTx.destAddr   = (uint32_t) & (base->TCR);
471         transferConfigTx.destOffset = 0;
472 
473         transferConfigTx.srcTransferSize  = kEDMA_TransferSize4Bytes;
474         transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
475         transferConfigTx.minorLoopBytes   = 4;
476         transferConfigTx.majorLoopCounts  = 1;
477 
478         EDMA_TcdReset(softwareTCD_pcsContinuous);
479         EDMA_TcdSetTransferConfig(softwareTCD_pcsContinuous, &transferConfigTx, NULL);
480     }
481 
482     if (handle->txData != NULL)
483     {
484         transferConfigTx.srcAddr   = (uint32_t)(handle->txData);
485         transferConfigTx.srcOffset = 1;
486     }
487     else
488     {
489         transferConfigTx.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
490         transferConfigTx.srcOffset = 0;
491     }
492 
493     transferConfigTx.destOffset = 0;
494 
495     transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
496 
497     dif = 0U;
498     switch (handle->bytesEachRead)
499     {
500         case (1U):
501             transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
502             transferConfigTx.minorLoopBytes   = 1;
503             if (handle->isByteSwap)
504             {
505                 dif = 3;
506             }
507             break;
508 
509         case (2U):
510             transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
511             transferConfigTx.minorLoopBytes   = 2;
512 
513             if (handle->isByteSwap)
514             {
515                 dif = 2;
516             }
517             break;
518 
519         case (4U):
520             transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
521             transferConfigTx.minorLoopBytes   = 4;
522             break;
523 
524         default:
525             transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
526             transferConfigTx.minorLoopBytes   = 1;
527             assert(false);
528             break;
529     }
530 
531     transferConfigTx.destAddr = (uint32_t)txAddr + dif;
532 
533     transferConfigTx.majorLoopCounts = handle->writeRegRemainingTimes;
534 
535     if (isThereExtraTxBytes)
536     {
537         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
538                                &transferConfigTx, softwareTCD_extraBytes);
539     }
540     else if (handle->isPcsContinuous)
541     {
542         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
543                                &transferConfigTx, softwareTCD_pcsContinuous);
544     }
545     else
546     {
547         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
548                                &transferConfigTx, NULL);
549     }
550 
551     EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
552     EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
553 
554     LPSPI_EnableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
555 
556     return kStatus_Success;
557 }
558 
EDMA_LpspiMasterCallback(edma_handle_t * edmaHandle,void * g_lpspiEdmaPrivateHandle,bool transferDone,uint32_t tcds)559 static void EDMA_LpspiMasterCallback(edma_handle_t *edmaHandle,
560                                      void *g_lpspiEdmaPrivateHandle,
561                                      bool transferDone,
562                                      uint32_t tcds)
563 {
564     assert(edmaHandle);
565     assert(g_lpspiEdmaPrivateHandle);
566 
567     uint32_t readData;
568 
569     lpspi_master_edma_private_handle_t *lpspiEdmaPrivateHandle;
570 
571     lpspiEdmaPrivateHandle = (lpspi_master_edma_private_handle_t *)g_lpspiEdmaPrivateHandle;
572 
573     size_t rxRemainingByteCount = lpspiEdmaPrivateHandle->handle->rxRemainingByteCount;
574     uint8_t bytesLastRead       = lpspiEdmaPrivateHandle->handle->bytesLastRead;
575     bool isByteSwap             = lpspiEdmaPrivateHandle->handle->isByteSwap;
576 
577     LPSPI_DisableDMA(lpspiEdmaPrivateHandle->base, (uint32_t)kLPSPI_TxDmaEnable | (uint32_t)kLPSPI_RxDmaEnable);
578 
579     if (lpspiEdmaPrivateHandle->handle->isThereExtraRxBytes)
580     {
581         while (LPSPI_GetRxFifoCount(lpspiEdmaPrivateHandle->base) == 0U)
582         {
583         }
584         readData = LPSPI_ReadData(lpspiEdmaPrivateHandle->base);
585 
586         if (lpspiEdmaPrivateHandle->handle->rxData != NULL)
587         {
588             LPSPI_SeparateEdmaReadData(&(lpspiEdmaPrivateHandle->handle->rxData[rxRemainingByteCount - bytesLastRead]),
589                                        readData, bytesLastRead, isByteSwap);
590         }
591     }
592 
593     lpspiEdmaPrivateHandle->handle->state = (uint8_t)kLPSPI_Idle;
594 
595     if (lpspiEdmaPrivateHandle->handle->callback != NULL)
596     {
597         lpspiEdmaPrivateHandle->handle->callback(lpspiEdmaPrivateHandle->base, lpspiEdmaPrivateHandle->handle,
598                                                  kStatus_Success, lpspiEdmaPrivateHandle->handle->userData);
599     }
600 }
601 
602 /*!
603  * brief LPSPI master aborts a transfer which is using eDMA.
604  *
605  * This function aborts a transfer which is using eDMA.
606  *
607  * param base LPSPI peripheral base address.
608  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
609  */
LPSPI_MasterTransferAbortEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle)610 void LPSPI_MasterTransferAbortEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle)
611 {
612     assert(handle);
613 
614     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
615 
616     EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
617     EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
618 
619     handle->state = (uint8_t)kLPSPI_Idle;
620 }
621 
622 /*!
623  * brief Gets the master eDMA transfer remaining bytes.
624  *
625  * This function gets the master eDMA transfer remaining bytes.
626  *
627  * param base LPSPI peripheral base address.
628  * param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
629  * param count Number of bytes transferred so far by the EDMA transaction.
630  * return status of status_t.
631  */
LPSPI_MasterTransferGetCountEDMA(LPSPI_Type * base,lpspi_master_edma_handle_t * handle,size_t * count)632 status_t LPSPI_MasterTransferGetCountEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, size_t *count)
633 {
634     assert(handle);
635 
636     if (NULL == count)
637     {
638         return kStatus_InvalidArgument;
639     }
640 
641     /* Catch when there is not an active transfer. */
642     if (handle->state != (uint8_t)kLPSPI_Busy)
643     {
644         *count = 0;
645         return kStatus_NoTransferInProgress;
646     }
647 
648     size_t remainingByte;
649 
650     remainingByte =
651         (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
652                                                                    handle->edmaRxRegToRxDataHandle->channel);
653 
654     *count = handle->totalByteCount - remainingByte;
655 
656     return kStatus_Success;
657 }
658 
659 /*!
660  * brief Initializes the LPSPI slave eDMA handle.
661  *
662  * This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs.  Usually, for a
663  * specified LPSPI instance, call this API once to get the initialized handle.
664  *
665  * Note that LPSPI eDMA has a separated (Rx and Tx as two sources) or shared (Rx  and Tx as the same source) DMA request
666  * source.
667  *
668  * (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
669  * Tx DMAMUX source for edmaTxDataToTxRegHandle.
670  * (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle .
671  *
672  * param base LPSPI peripheral base address.
673  * param handle LPSPI handle pointer to lpspi_slave_edma_handle_t.
674  * param callback LPSPI callback.
675  * param userData callback function parameter.
676  * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
677  * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
678  */
LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle,lpspi_slave_edma_transfer_callback_t callback,void * userData,edma_handle_t * edmaRxRegToRxDataHandle,edma_handle_t * edmaTxDataToTxRegHandle)679 void LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type *base,
680                                          lpspi_slave_edma_handle_t *handle,
681                                          lpspi_slave_edma_transfer_callback_t callback,
682                                          void *userData,
683                                          edma_handle_t *edmaRxRegToRxDataHandle,
684                                          edma_handle_t *edmaTxDataToTxRegHandle)
685 {
686     assert(handle);
687     assert(edmaRxRegToRxDataHandle);
688     assert(edmaTxDataToTxRegHandle);
689 
690     /* Zero the handle. */
691     (void)memset(handle, 0, sizeof(*handle));
692 
693     uint32_t instance = LPSPI_GetInstance(base);
694 
695     s_lpspiSlaveEdmaPrivateHandle[instance].base   = base;
696     s_lpspiSlaveEdmaPrivateHandle[instance].handle = handle;
697 
698     handle->callback = callback;
699     handle->userData = userData;
700 
701     handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
702     handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
703 }
704 
705 /*!
706  * brief LPSPI slave transfers data using eDMA.
707  *
708  * This function transfers data using eDMA. This is a non-blocking function, which return right away. When all data
709  * is transferred, the callback function is called.
710  *
711  * Note:
712  * The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
713  * For bytesPerFrame greater than 4:
714  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
715  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
716  *
717  * param base LPSPI peripheral base address.
718  * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
719  * param transfer pointer to lpspi_transfer_t structure.
720  * return status of status_t.
721  */
LPSPI_SlaveTransferEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle,lpspi_transfer_t * transfer)722 status_t LPSPI_SlaveTransferEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, lpspi_transfer_t *transfer)
723 {
724     assert(handle);
725     assert(transfer);
726 
727     uint32_t bitsPerFrame  = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1U;
728     uint32_t bytesPerFrame = (bitsPerFrame + 7U) / 8U;
729     uint32_t temp          = 0U;
730     bool isByteSwap;
731 
732     uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)];
733 
734     if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
735     {
736         return kStatus_InvalidArgument;
737     }
738 
739     /*And since the dma transfer can not support 3 bytes .*/
740     if ((bytesPerFrame % 4U) == 3U)
741     {
742         return kStatus_InvalidArgument;
743     }
744 
745     /* Check that we're not busy.*/
746     if (handle->state == (uint8_t)kLPSPI_Busy)
747     {
748         return kStatus_LPSPI_Busy;
749     }
750 
751     handle->state = (uint8_t)kLPSPI_Busy;
752 
753     uint32_t rxAddr = LPSPI_GetRxRegisterAddress(base);
754     uint32_t txAddr = LPSPI_GetTxRegisterAddress(base);
755 
756     edma_tcd_t *softwareTCD_extraBytes = (edma_tcd_t *)((uint32_t)(&handle->lpspiSoftwareTCD[1]) & (~0x1FU));
757 
758     uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
759 
760     /*Because DMA is fast enough , so set the RX and TX watermarks to 0 .*/
761     uint8_t txWatermark = 0;
762     uint8_t rxWatermark = 0;
763 
764     /*Used for byte swap*/
765     uint32_t dif = 0;
766 
767     uint8_t bytesLastWrite = 0;
768 
769     uint32_t instance = LPSPI_GetInstance(base);
770 
771     edma_transfer_config_t transferConfigRx;
772     edma_transfer_config_t transferConfigTx;
773 
774     bool isThereExtraTxBytes = false;
775 
776     handle->txData               = transfer->txData;
777     handle->rxData               = transfer->rxData;
778     handle->txRemainingByteCount = transfer->dataSize;
779     handle->rxRemainingByteCount = transfer->dataSize;
780     handle->totalByteCount       = transfer->dataSize;
781 
782     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
783     handle->readRegRemainingTimes  = handle->writeRegRemainingTimes;
784 
785     handle->txBuffIfNull =
786         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
787 
788     /*The TX and RX FIFO sizes are always the same*/
789     handle->fifoSize = LPSPI_GetRxFifoSize(base);
790 
791     handle->isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
792     isByteSwap         = handle->isByteSwap;
793 
794     LPSPI_SetFifoWatermarks(base, txWatermark, rxWatermark);
795 
796     /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
797     LPSPI_Enable(base, false);
798     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
799     /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */
800     temp = base->CFGR1;
801     temp &= LPSPI_CFGR1_PINCFG_MASK;
802     if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut)))
803     {
804         if (NULL == handle->txData)
805         {
806             base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
807         }
808         /* The 3-wire mode can't send and receive data at the same time. */
809         if ((handle->txData != NULL) && (handle->rxData != NULL))
810         {
811             return kStatus_InvalidArgument;
812         }
813     }
814 
815     LPSPI_Enable(base, true);
816 
817     /*Flush FIFO , clear status , disable all the inerrupts.*/
818     LPSPI_FlushFifo(base, true, true);
819     LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
820     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
821 
822     /* For DMA transfer , we'd better not masked the transmit data and receive data in TCR since the transfer flow is
823      * hard to controlled by software.
824      */
825     base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_BYSW_MASK)) |
826                 LPSPI_TCR_CONTC(0U) | LPSPI_TCR_BYSW(isByteSwap) | LPSPI_TCR_PCS(whichPcs);
827 
828     isThereExtraTxBytes         = false;
829     handle->isThereExtraRxBytes = false;
830 
831     /*Calculate the bytes for write/read the TX/RX register each time*/
832     if (bytesPerFrame <= 4U)
833     {
834         handle->bytesEachWrite = (uint8_t)bytesPerFrame;
835         handle->bytesEachRead  = (uint8_t)bytesPerFrame;
836 
837         handle->bytesLastRead = (uint8_t)bytesPerFrame;
838     }
839     else
840     {
841         handle->bytesEachWrite = 4U;
842         handle->bytesEachRead  = 4U;
843 
844         handle->bytesLastRead = 4U;
845 
846         if ((transfer->dataSize % 4U) != 0U)
847         {
848             bytesLastWrite        = (uint8_t)(transfer->dataSize % 4U);
849             handle->bytesLastRead = bytesLastWrite;
850 
851             isThereExtraTxBytes = true;
852             --handle->writeRegRemainingTimes;
853 
854             handle->isThereExtraRxBytes = true;
855             --handle->readRegRemainingTimes;
856         }
857     }
858 
859     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
860 
861     EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_LpspiSlaveCallback,
862                      &s_lpspiSlaveEdmaPrivateHandle[instance]);
863 
864     /*Rx*/
865     if (handle->readRegRemainingTimes > 0U)
866     {
867         EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
868 
869         if (handle->rxData != NULL)
870         {
871             transferConfigRx.destAddr   = (uint32_t) & (handle->rxData[0]);
872             transferConfigRx.destOffset = 1;
873         }
874         else
875         {
876             transferConfigRx.destAddr   = (uint32_t) & (handle->rxBuffIfNull);
877             transferConfigRx.destOffset = 0;
878         }
879         transferConfigRx.destTransferSize = kEDMA_TransferSize1Bytes;
880 
881         dif = 0;
882         switch (handle->bytesEachRead)
883         {
884             case (1U):
885                 transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
886                 transferConfigRx.minorLoopBytes  = 1;
887                 if (handle->isByteSwap)
888                 {
889                     dif = 3;
890                 }
891                 break;
892 
893             case (2U):
894                 transferConfigRx.srcTransferSize = kEDMA_TransferSize2Bytes;
895                 transferConfigRx.minorLoopBytes  = 2;
896                 if (handle->isByteSwap)
897                 {
898                     dif = 2;
899                 }
900                 break;
901 
902             case (4U):
903                 transferConfigRx.srcTransferSize = kEDMA_TransferSize4Bytes;
904                 transferConfigRx.minorLoopBytes  = 4;
905                 break;
906 
907             default:
908                 transferConfigRx.srcTransferSize = kEDMA_TransferSize1Bytes;
909                 transferConfigRx.minorLoopBytes  = 1;
910                 assert(false);
911                 break;
912         }
913 
914         transferConfigRx.srcAddr   = (uint32_t)rxAddr + dif;
915         transferConfigRx.srcOffset = 0;
916 
917         transferConfigRx.majorLoopCounts = handle->readRegRemainingTimes;
918 
919         /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
920         handle->nbytes = (uint8_t)transferConfigRx.minorLoopBytes;
921 
922         EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
923                                &transferConfigRx, NULL);
924         EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
925                                      (uint32_t)kEDMA_MajorInterruptEnable);
926     }
927 
928     /*Tx*/
929     EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
930 
931     if (isThereExtraTxBytes)
932     {
933         if (handle->txData != NULL)
934         {
935             transferConfigTx.srcAddr   = (uint32_t) & (transfer->txData[transfer->dataSize - bytesLastWrite]);
936             transferConfigTx.srcOffset = 1;
937         }
938         else
939         {
940             transferConfigTx.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
941             transferConfigTx.srcOffset = 0;
942         }
943 
944         transferConfigTx.destOffset = 0;
945 
946         transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
947 
948         dif = 0;
949         switch (bytesLastWrite)
950         {
951             case (1U):
952                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
953                 transferConfigTx.minorLoopBytes   = 1;
954                 if (handle->isByteSwap)
955                 {
956                     dif = 3;
957                 }
958                 break;
959 
960             case (2U):
961                 transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
962                 transferConfigTx.minorLoopBytes   = 2;
963                 if (handle->isByteSwap)
964                 {
965                     dif = 2;
966                 }
967                 break;
968 
969             default:
970                 transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
971                 transferConfigTx.minorLoopBytes   = 1;
972                 assert(false);
973                 break;
974         }
975 
976         transferConfigTx.destAddr        = (uint32_t)txAddr + dif;
977         transferConfigTx.majorLoopCounts = 1;
978 
979         EDMA_TcdReset(softwareTCD_extraBytes);
980 
981         EDMA_TcdSetTransferConfig(softwareTCD_extraBytes, &transferConfigTx, NULL);
982     }
983 
984     if (handle->txData != NULL)
985     {
986         transferConfigTx.srcAddr   = (uint32_t)(handle->txData);
987         transferConfigTx.srcOffset = 1;
988     }
989     else
990     {
991         transferConfigTx.srcAddr   = (uint32_t)(&handle->txBuffIfNull);
992         transferConfigTx.srcOffset = 0;
993     }
994 
995     transferConfigTx.destOffset = 0;
996 
997     transferConfigTx.srcTransferSize = kEDMA_TransferSize1Bytes;
998 
999     dif = 0;
1000     switch (handle->bytesEachRead)
1001     {
1002         case (1U):
1003             transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
1004             transferConfigTx.minorLoopBytes   = 1;
1005             if (handle->isByteSwap)
1006             {
1007                 dif = 3;
1008             }
1009             break;
1010 
1011         case (2U):
1012             transferConfigTx.destTransferSize = kEDMA_TransferSize2Bytes;
1013             transferConfigTx.minorLoopBytes   = 2;
1014 
1015             if (handle->isByteSwap)
1016             {
1017                 dif = 2;
1018             }
1019             break;
1020 
1021         case (4U):
1022             transferConfigTx.destTransferSize = kEDMA_TransferSize4Bytes;
1023             transferConfigTx.minorLoopBytes   = 4;
1024             break;
1025 
1026         default:
1027             transferConfigTx.destTransferSize = kEDMA_TransferSize1Bytes;
1028             transferConfigTx.minorLoopBytes   = 1;
1029             assert(false);
1030             break;
1031     }
1032 
1033     transferConfigTx.destAddr = (uint32_t)txAddr + dif;
1034 
1035     transferConfigTx.majorLoopCounts = handle->writeRegRemainingTimes;
1036 
1037     if (isThereExtraTxBytes)
1038     {
1039         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1040                                &transferConfigTx, softwareTCD_extraBytes);
1041     }
1042     else
1043     {
1044         EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
1045                                &transferConfigTx, NULL);
1046     }
1047 
1048     EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
1049     EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
1050 
1051     LPSPI_EnableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
1052 
1053     return kStatus_Success;
1054 }
1055 
EDMA_LpspiSlaveCallback(edma_handle_t * edmaHandle,void * g_lpspiEdmaPrivateHandle,bool transferDone,uint32_t tcds)1056 static void EDMA_LpspiSlaveCallback(edma_handle_t *edmaHandle,
1057                                     void *g_lpspiEdmaPrivateHandle,
1058                                     bool transferDone,
1059                                     uint32_t tcds)
1060 {
1061     assert(edmaHandle);
1062     assert(g_lpspiEdmaPrivateHandle);
1063 
1064     uint32_t readData;
1065 
1066     lpspi_slave_edma_private_handle_t *lpspiEdmaPrivateHandle;
1067 
1068     lpspiEdmaPrivateHandle = (lpspi_slave_edma_private_handle_t *)g_lpspiEdmaPrivateHandle;
1069 
1070     size_t rxRemainingByteCount = lpspiEdmaPrivateHandle->handle->rxRemainingByteCount;
1071     uint8_t bytesLastRead       = lpspiEdmaPrivateHandle->handle->bytesLastRead;
1072     bool isByteSwap             = lpspiEdmaPrivateHandle->handle->isByteSwap;
1073 
1074     LPSPI_DisableDMA(lpspiEdmaPrivateHandle->base, (uint32_t)kLPSPI_TxDmaEnable | (uint32_t)kLPSPI_RxDmaEnable);
1075 
1076     if (lpspiEdmaPrivateHandle->handle->isThereExtraRxBytes)
1077     {
1078         while (LPSPI_GetRxFifoCount(lpspiEdmaPrivateHandle->base) == 0U)
1079         {
1080         }
1081         readData = LPSPI_ReadData(lpspiEdmaPrivateHandle->base);
1082 
1083         if (lpspiEdmaPrivateHandle->handle->rxData != NULL)
1084         {
1085             LPSPI_SeparateEdmaReadData(&(lpspiEdmaPrivateHandle->handle->rxData[rxRemainingByteCount - bytesLastRead]),
1086                                        readData, bytesLastRead, isByteSwap);
1087         }
1088     }
1089 
1090     lpspiEdmaPrivateHandle->handle->state = (uint8_t)kLPSPI_Idle;
1091 
1092     if (lpspiEdmaPrivateHandle->handle->callback != NULL)
1093     {
1094         lpspiEdmaPrivateHandle->handle->callback(lpspiEdmaPrivateHandle->base, lpspiEdmaPrivateHandle->handle,
1095                                                  kStatus_Success, lpspiEdmaPrivateHandle->handle->userData);
1096     }
1097 }
1098 
1099 /*!
1100  * brief LPSPI slave aborts a transfer which is using eDMA.
1101  *
1102  * This function aborts a transfer which is using eDMA.
1103  *
1104  * param base LPSPI peripheral base address.
1105  * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
1106  */
LPSPI_SlaveTransferAbortEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle)1107 void LPSPI_SlaveTransferAbortEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle)
1108 {
1109     assert(handle);
1110 
1111     LPSPI_DisableDMA(base, (uint32_t)kLPSPI_RxDmaEnable | (uint32_t)kLPSPI_TxDmaEnable);
1112 
1113     EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
1114     EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
1115 
1116     handle->state = (uint8_t)kLPSPI_Idle;
1117 }
1118 
1119 /*!
1120  * brief Gets the slave eDMA transfer remaining bytes.
1121  *
1122  * This function gets the slave eDMA transfer remaining bytes.
1123  *
1124  * param base LPSPI peripheral base address.
1125  * param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
1126  * param count Number of bytes transferred so far by the eDMA transaction.
1127  * return status of status_t.
1128  */
LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type * base,lpspi_slave_edma_handle_t * handle,size_t * count)1129 status_t LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, size_t *count)
1130 {
1131     assert(handle);
1132 
1133     if (NULL == count)
1134     {
1135         return kStatus_InvalidArgument;
1136     }
1137 
1138     /* Catch when there is not an active transfer. */
1139     if (handle->state != (uint8_t)kLPSPI_Busy)
1140     {
1141         *count = 0;
1142         return kStatus_NoTransferInProgress;
1143     }
1144 
1145     size_t remainingByte;
1146 
1147     remainingByte =
1148         (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
1149                                                                    handle->edmaRxRegToRxDataHandle->channel);
1150 
1151     *count = handle->totalByteCount - remainingByte;
1152 
1153     return kStatus_Success;
1154 }
1155