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