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