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