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