1 /*
2 * Copyright 2019-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_flexspi_dma.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.flexspi_dma"
17 #endif
18
19 /*<! Structure definition for flexspi_dma_private_handle_t. The structure is private. */
20 typedef struct _flexspi_dma_private_handle
21 {
22 FLEXSPI_Type *base;
23 flexspi_dma_handle_t *handle;
24 } flexspi_dma_private_handle_t;
25
26 /* FLEXSPI DMA transfer handle, _flexspi_dma_tansfer_states. */
27 enum
28 {
29 kFLEXSPI_Idle, /* FLEXSPI Bus idle. */
30 kFLEXSPI_Busy /* FLEXSPI Bus busy. */
31 };
32
33 /*******************************************************************************
34 * Variables
35 ******************************************************************************/
36
37 /*! @brief Pointers to flexspi bases for each instance. */
38 static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
39
40 /*<! Private handle only used for internally. */
41 static flexspi_dma_private_handle_t s_dmaPrivateHandle[ARRAY_SIZE(s_flexspiBases)];
42
43 #if defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES
44 /*<! Private DMA descriptor array used for internally to fix FLEXSPI+DMA ERRATA.
45 FLEXSPI.1: Using FLEXSPI register interface, TX buffer fill / RX buffer drain by DMA
46 with a single DMA descriptor cannot be performed. The link array consumes about
47 2K RAM consumption support FLEXSPI TX watermark starting from 8 bytes.*/
48 #define FLEXSPI_DMA_DES_COUNT 128U
49 #else
50 /*<! Private DMA descriptor array to support transfer size not multiple of watermark level byts.
51 The link array consumes 16 bytes consumption.*/
52 #define FLEXSPI_DMA_DES_COUNT 1U
53 #endif
54
55 #if defined(__ICCARM__)
56 #pragma data_alignment = FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE
57 static dma_descriptor_t s_flexspiDes[FLEXSPI_DMA_DES_COUNT];
58 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
59 __attribute__((
60 aligned(FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE))) static dma_descriptor_t s_flexspiDes[FLEXSPI_DMA_DES_COUNT];
61 #elif defined(__GNUC__)
62 __attribute__((
63 aligned(FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE))) static dma_descriptor_t s_flexspiDes[FLEXSPI_DMA_DES_COUNT];
64 #endif
65 /*******************************************************************************
66 * Prototypes
67 ******************************************************************************/
68
69 /*!
70 * @brief FLEXSPI DMA transfer finished callback function.
71 *
72 * This function is called when FLEXSPI DMA transfer finished. It disables the FLEXSPI
73 * TX/RX DMA request and sends status to FLEXSPI callback.
74 *
75 * @param handle The DMA handle.
76 * @param param Callback function parameter.
77 */
78 static void FLEXSPI_TransferDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
79
80 /*!
81 * @brief FLEXSPI Write DMA data.
82 *
83 * This function is called in FLEXSPI DMA transfer. It configures Write DMA and prepare DMA data transfer.
84 *
85 * @param base FLEXSPI peripheral base address.
86 * @param handle The DMA handle.
87 * @param data pointer to data buffer which stores the transmit data
88 * @param dataSize size for transmit data buffer .
89 */
90 static status_t FLEXSPI_WriteDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize);
91
92 /*!
93 * @brief FLEXSPI Read DMA data.
94 *
95 * This function is called in FLEXSPI DMA transfer. It configures Read DMA and prepare DMA data transfer.
96 *
97 * @param base FLEXSPI peripheral base address.
98 * @param handle The DMA handle.
99 * @param data pointer to data buffer which stores the receive data
100 * @param dataSize size for receive data buffer .
101 */
102 static status_t FLEXSPI_ReadDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize);
103 /*******************************************************************************
104 * Code
105 ******************************************************************************/
106 #if !(defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES)
FLEXSPI_CalculatePower(uint8_t value)107 static uint8_t FLEXSPI_CalculatePower(uint8_t value)
108 {
109 uint8_t power = 0;
110 while (value >> 1 != 0U)
111 {
112 power++;
113 value = value >> 1;
114 }
115
116 return power;
117 }
118 #endif
119
FLEXSPI_TransferDMACallback(dma_handle_t * handle,void * param,bool transferDone,uint32_t tcds)120 static void FLEXSPI_TransferDMACallback(dma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
121 {
122 flexspi_dma_private_handle_t *flexspiPrivateHandle = (flexspi_dma_private_handle_t *)param;
123
124 /* Avoid warning for unused parameters. */
125 handle = handle;
126 tcds = tcds;
127
128 if (transferDone)
129 {
130 /* Wait for bus idle. */
131 while (!FLEXSPI_GetBusIdleStatus(flexspiPrivateHandle->base))
132 {
133 }
134 /* Disable transfer. */
135 FLEXSPI_TransferAbortDMA(flexspiPrivateHandle->base, flexspiPrivateHandle->handle);
136
137 if (flexspiPrivateHandle->handle->completionCallback != NULL)
138 {
139 flexspiPrivateHandle->handle->completionCallback(flexspiPrivateHandle->base, flexspiPrivateHandle->handle,
140 kStatus_Success, flexspiPrivateHandle->handle->userData);
141 }
142 }
143 }
144
FLEXSPI_WriteDataDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,uint32_t * data,size_t dataSize)145 static status_t FLEXSPI_WriteDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize)
146 {
147 void *txFifoBase = (void *)(uint32_t *)FLEXSPI_GetTxFifoAddress(base);
148 void *nextDesc = NULL;
149 dma_channel_trigger_t dmaTxTriggerConfig;
150 dma_channel_config_t txChannelConfig;
151 uint32_t bytesPerDes;
152 uint8_t desCount;
153 uint8_t remains;
154 uint32_t srcInc;
155 uint32_t dstInc;
156
157 /* Source address interleave size */
158 srcInc = kDMA_AddressInterleave1xWidth;
159 /* Destination address interleave size */
160 dstInc = kDMA_AddressInterleave1xWidth;
161
162 /* Check the xfer->data start address follows the alignment */
163 if (((uint32_t)data & ((uint32_t)handle->nsize - 1U)) != 0U)
164 {
165 return kStatus_InvalidArgument;
166 }
167
168 handle->count =
169 8U * ((uint8_t)(((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U));
170
171 /* Check the handle->count is power of 2 */
172 if (((handle->count) & (handle->count - 1U)) != 0U)
173 {
174 return kStatus_InvalidArgument;
175 }
176
177 #if defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES
178 if (dataSize < handle->count)
179 {
180 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
181 handle->nbytes = (uint8_t)dataSize;
182 }
183 else
184 {
185 /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
186 handle->nbytes = handle->count;
187 }
188
189 handle->transferSize = dataSize;
190 dmaTxTriggerConfig.burst = kDMA_SingleTransfer;
191 dmaTxTriggerConfig.type = kDMA_HighLevelTrigger;
192 dmaTxTriggerConfig.wrap = kDMA_NoWrap;
193
194 /* Configure linked descriptors to start FLEXSPI Tx DMA transfer to provide software workaround for
195 ERRATA FLEXSPI.1: Using FLEXSPI register interface, TX buffer fill / RX buffer drain by DMA with a
196 single DMA descriptor cannot be performed. */
197 desCount = (uint8_t)(dataSize / (uint32_t)handle->nbytes);
198 bytesPerDes = handle->nbytes;
199 remains = (uint8_t)(dataSize - (uint32_t)desCount * (uint32_t)handle->nbytes);
200 if (remains > 0U)
201 {
202 uint32_t width = (uint32_t)kFLEXPSI_DMAnSize1Bytes;
203 DMA_SetupDescriptor(&s_flexspiDes[desCount - 1U],
204 DMA_CHANNEL_XFER(false, true, true, false, width, srcInc, dstInc, remains),
205 (void *)(uint64_t *)((uint32_t)data + desCount * bytesPerDes), txFifoBase, NULL);
206 nextDesc = &s_flexspiDes[desCount - 1U];
207 }
208
209 remains = (uint8_t)bytesPerDes;
210 #else
211 uint32_t dmaTriggerBurst;
212 dmaTxTriggerConfig.type = kDMA_RisingEdgeTrigger;
213 bytesPerDes = dataSize;
214
215 if (dataSize < handle->count)
216 {
217 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
218 handle->nbytes = (uint8_t)(dataSize / (uint32_t)handle->nsize);
219 dmaTxTriggerConfig.wrap = kDMA_NoWrap;
220
221 /* Check the handle->nbytes is power of 2 */
222 if (((handle->nbytes) & (handle->nbytes - 1U)) != 0U)
223 {
224 handle->nbytes = 2U * ((handle->nbytes) & (handle->nbytes - 1U));
225 }
226
227 desCount = 1U;
228 }
229 else
230 {
231 dmaTxTriggerConfig.wrap = kDMA_DstWrap;
232 remains = (uint8_t)(dataSize % (uint32_t)handle->count);
233 if (remains == 0U)
234 {
235 desCount = 1U;
236 }
237 else
238 {
239 desCount = 2U;
240 bytesPerDes = dataSize - remains;
241 if ((remains & 3U) == 0U)
242 {
243 handle->nsize = kFLEXPSI_DMAnSize4Bytes;
244 }
245 else if ((remains & 1U) == 0U)
246 {
247 handle->nsize = kFLEXPSI_DMAnSize2Bytes;
248 }
249 else
250 {
251 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
252 }
253 }
254 /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
255 handle->nbytes = handle->count / (uint8_t)handle->nsize;
256
257 /* Check if dataSize exceeds the maximum transfer count supported by the driver. */
258 if ((dataSize - handle->count + 1U) / ((uint32_t)handle->nsize) > 1024U)
259 {
260 return kStatus_InvalidArgument;
261 }
262 }
263
264 /* xfer->dataSize needs to be larger than 1 due to hardware limitation */
265 if (dataSize / (uint8_t)handle->nsize == 1U)
266 {
267 return kStatus_InvalidArgument;
268 }
269
270 dmaTriggerBurst = DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(FLEXSPI_CalculatePower(handle->nbytes));
271 dmaTxTriggerConfig.burst = (dma_trigger_burst_t)dmaTriggerBurst;
272 handle->transferSize = dataSize;
273 #endif
274
275 for (uint8_t i = desCount - 1U; i > 0U; i--)
276 {
277 DMA_SetupDescriptor(&s_flexspiDes[i - 1U],
278 DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false,
279 false, (uint32_t)handle->nsize, srcInc, dstInc, remains),
280 (void *)(uint64_t *)((uint32_t)data + i * bytesPerDes), txFifoBase, nextDesc);
281 nextDesc = &s_flexspiDes[i - 1U];
282 }
283
284 DMA_PrepareChannelTransfer(
285 &txChannelConfig, (void *)data, txFifoBase,
286 DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false, false,
287 (uint32_t)handle->nsize, srcInc, dstInc, bytesPerDes),
288 kDMA_MemoryToMemory, &dmaTxTriggerConfig, nextDesc);
289
290 (void)DMA_SubmitChannelTransfer(handle->txDmaHandle, &txChannelConfig);
291
292 DMA_SetCallback(handle->txDmaHandle, FLEXSPI_TransferDMACallback, &s_dmaPrivateHandle[FLEXSPI_GetInstance(base)]);
293 DMA_StartTransfer(handle->txDmaHandle);
294
295 /* Enable FLEXSPI TX DMA. */
296 FLEXSPI_EnableTxDMA(base, true);
297
298 /* Start Transfer. */
299 base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
300
301 return kStatus_Success;
302 }
303
FLEXSPI_ReadDataDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,uint32_t * data,size_t dataSize)304 static status_t FLEXSPI_ReadDataDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, uint32_t *data, size_t dataSize)
305 {
306 dma_channel_trigger_t dmaRxTriggerConfig;
307 void *rxFifoBase = (void *)(uint32_t *)FLEXSPI_GetRxFifoAddress(base);
308 void *nextDesc = NULL;
309 dma_channel_config_t rxChannelConfig;
310 uint32_t bytesPerDes;
311 uint8_t remains;
312 uint8_t desCount;
313 uint32_t srcInc;
314 uint32_t dstInc;
315
316 /* Source address interleave size */
317 srcInc = kDMA_AddressInterleave1xWidth;
318 /* Destination address interleave size */
319 dstInc = kDMA_AddressInterleave1xWidth;
320
321 handle->count =
322 8U * (uint8_t)(((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U);
323
324 /* Check the watermark is power of 2U */
325 if ((handle->count & (handle->count - 1U)) != 0U)
326 {
327 return kStatus_InvalidArgument;
328 }
329
330 #if defined(FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES) && FSL_FEATURE_FLEXSPI_DMA_MULTIPLE_DES
331 if (dataSize < handle->count)
332 {
333 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
334 handle->nbytes = (uint8_t)dataSize;
335 }
336 else
337 {
338 /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
339 handle->nbytes = handle->count;
340 }
341
342 dmaRxTriggerConfig.burst = kDMA_SingleTransfer;
343 dmaRxTriggerConfig.type = kDMA_HighLevelTrigger;
344 dmaRxTriggerConfig.wrap = kDMA_NoWrap;
345
346 /* Configure linked descriptors to start FLEXSPI Tx DMA transfer to provide software workaround for
347 ERRATA FLEXSPI.1: Using FLEXSPI register interface, TX buffer fill / RX buffer drain by DMA with a
348 single DMA descriptor cannot be performed. */
349 desCount = (uint8_t)(dataSize / (uint32_t)handle->nbytes);
350 bytesPerDes = handle->nbytes;
351 remains = (uint8_t)(dataSize - (uint32_t)desCount * (uint32_t)handle->nbytes);
352
353 if (remains > 0U)
354 {
355 uint32_t width = (uint32_t)kFLEXPSI_DMAnSize1Bytes;
356 DMA_SetupDescriptor(&s_flexspiDes[desCount - 1U],
357 DMA_CHANNEL_XFER(false, true, true, false, width, srcInc, dstInc, remains), rxFifoBase,
358 (void *)(uint64_t *)((uint32_t)data + desCount * bytesPerDes), NULL);
359 nextDesc = &s_flexspiDes[desCount - 1U];
360 }
361 remains = (uint8_t)bytesPerDes;
362
363 #else
364 uint32_t dmaTriggerBurst;
365 dmaRxTriggerConfig.type = kDMA_RisingEdgeTrigger;
366 bytesPerDes = dataSize;
367
368 if (dataSize < handle->count)
369 {
370 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
371 handle->nbytes = (uint8_t)(dataSize / (uint32_t)handle->nsize);
372 dmaRxTriggerConfig.wrap = kDMA_NoWrap;
373 /* Check the handle->nbytes is power of 2 */
374 if (((handle->nbytes) & (handle->nbytes - 1U)) != 0U)
375 {
376 handle->nbytes = 2U * ((handle->nbytes) & (handle->nbytes - 1U));
377 }
378 desCount = 1U;
379 }
380 else
381 {
382 dmaRxTriggerConfig.wrap = kDMA_SrcWrap;
383 remains = (uint8_t)(dataSize % (uint32_t)handle->count);
384 if (remains == 0U)
385 {
386 desCount = 1U;
387 }
388 else
389 {
390 desCount = 2U;
391 bytesPerDes = dataSize - remains;
392 if ((remains & 3U) == 0U)
393 {
394 handle->nsize = kFLEXPSI_DMAnSize4Bytes;
395 }
396 else if ((remains & 1U) == 0U)
397 {
398 handle->nsize = kFLEXPSI_DMAnSize2Bytes;
399 }
400 else
401 {
402 handle->nsize = kFLEXPSI_DMAnSize1Bytes;
403 }
404 }
405 /* Store the initially configured dma minor byte transfer count into the FLEXSPI handle */
406 handle->nbytes = handle->count / (uint8_t)handle->nsize;
407
408 /* Check dataSize exceeds the maximum transfer count supported by the driver. */
409 if ((dataSize - handle->count + 1U) / ((uint32_t)handle->nsize) > 1024U)
410 {
411 return kStatus_InvalidArgument;
412 }
413 }
414
415 dmaTriggerBurst =
416 DMA_CHANNEL_CFG_TRIGBURST(1U) | DMA_CHANNEL_CFG_BURSTPOWER(FLEXSPI_CalculatePower(handle->nbytes));
417 dmaRxTriggerConfig.burst = (dma_trigger_burst_t)(dmaTriggerBurst);
418 #endif
419
420 for (uint8_t i = desCount - 1U; i > 0U; i--)
421 {
422 DMA_SetupDescriptor(&s_flexspiDes[i - 1U],
423 DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false,
424 false, (uint32_t)handle->nsize, srcInc, dstInc, remains),
425 rxFifoBase, (void *)(uint64_t *)((uint32_t)data + i * bytesPerDes), nextDesc);
426 nextDesc = &s_flexspiDes[i - 1U];
427 }
428
429 DMA_PrepareChannelTransfer(
430 &rxChannelConfig, rxFifoBase, (void *)data,
431 DMA_CHANNEL_XFER((nextDesc == NULL) ? false : true, true, (nextDesc == NULL) ? true : false, false,
432 (uint32_t)handle->nsize, srcInc, dstInc, bytesPerDes),
433 kDMA_MemoryToMemory, &dmaRxTriggerConfig, nextDesc);
434
435 (void)DMA_SubmitChannelTransfer(handle->rxDmaHandle, &rxChannelConfig);
436
437 DMA_SetCallback(handle->rxDmaHandle, FLEXSPI_TransferDMACallback, &s_dmaPrivateHandle[FLEXSPI_GetInstance(base)]);
438 DMA_StartTransfer(handle->rxDmaHandle);
439
440 /* Enable FLEXSPI RX DMA. */
441 FLEXSPI_EnableRxDMA(base, true);
442
443 /* Start Transfer. */
444 base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
445
446 return kStatus_Success;
447 }
448
449 /*!
450 * brief Initializes the FLEXSPI handle for transfer which is used in transactional functions and set the callback.
451 *
452 * param base FLEXSPI peripheral base address
453 * param handle Pointer to flexspi_dma_handle_t structure
454 * param callback FLEXSPI callback, NULL means no callback.
455 * param userData User callback function data.
456 * param txDmaHandle User requested DMA handle for TX DMA transfer.
457 * param rxDmaHandle User requested DMA handle for RX DMA transfer.
458 */
FLEXSPI_TransferCreateHandleDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,flexspi_dma_callback_t callback,void * userData,dma_handle_t * txDmaHandle,dma_handle_t * rxDmaHandle)459 void FLEXSPI_TransferCreateHandleDMA(FLEXSPI_Type *base,
460 flexspi_dma_handle_t *handle,
461 flexspi_dma_callback_t callback,
462 void *userData,
463 dma_handle_t *txDmaHandle,
464 dma_handle_t *rxDmaHandle)
465 {
466 assert(handle);
467
468 uint32_t instance = FLEXSPI_GetInstance(base);
469
470 s_dmaPrivateHandle[instance].base = base;
471 s_dmaPrivateHandle[instance].handle = handle;
472
473 (void)memset(handle, 0, sizeof(*handle));
474
475 handle->state = kFLEXSPI_Idle;
476 handle->txDmaHandle = txDmaHandle;
477 handle->rxDmaHandle = rxDmaHandle;
478 handle->nsize = kFLEXPSI_DMAnSize4Bytes;
479
480 handle->completionCallback = callback;
481 handle->userData = userData;
482 }
483
484 /*!
485 * brief Update FLEXSPI DMA transfer source data transfer size(SSIZE) and destination data transfer size(DSIZE).
486 *
487 * param base FLEXSPI peripheral base address
488 * param handle Pointer to flexspi_dma_handle_t structure
489 * param nsize FLEXSPI DMA transfer data transfer size(SSIZE/DSIZE), by default the size is
490 * kFLEXPSI_DMAnSize1Bytes(one byte).
491 * see flexspi_dma_transfer_nsize_t .
492 */
FLEXSPI_TransferUpdateSizeDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,flexspi_dma_transfer_nsize_t nsize)493 void FLEXSPI_TransferUpdateSizeDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, flexspi_dma_transfer_nsize_t nsize)
494 {
495 handle->nsize = nsize;
496 }
497
498 /*!
499 * brief Transfers FLEXSPI data using an dma non-blocking method.
500 *
501 * This function writes/receives data to/from the FLEXSPI transmit/receive FIFO. This function is non-blocking.
502 * param base FLEXSPI peripheral base address.
503 * param handle Pointer to flexspi_dma_handle_t structure
504 * param xfer FLEXSPI transfer structure.
505 * retval kStatus_FLEXSPI_Busy FLEXSPI is busy transfer.
506 * retval kStatus_InvalidArgument The watermark configuration is invalid, the watermark should be power of
507 2 to do successfully DMA transfer.
508 * retval kStatus_Success FLEXSPI successfully start dma transfer.
509 */
FLEXSPI_TransferDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,flexspi_transfer_t * xfer)510 status_t FLEXSPI_TransferDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, flexspi_transfer_t *xfer)
511 {
512 uint32_t configValue = 0;
513 status_t result = kStatus_Success;
514
515 assert(handle);
516 assert(xfer);
517
518 /* Check if the FLEXSPI bus is idle - if not return busy status. */
519 if (handle->state != (uint32_t)kFLEXSPI_Idle)
520 {
521 result = kStatus_FLEXSPI_Busy;
522 }
523 else
524 {
525 handle->transferSize = xfer->dataSize;
526
527 /* Clear sequence pointer before sending data to external devices. */
528 base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
529
530 /* Clear former pending status before start this transfer. */
531 base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
532 FLEXSPI_INTR_IPCMDGE_MASK;
533
534 /* Configure base address. */
535 base->IPCR0 = xfer->deviceAddress;
536
537 /* Reset fifos. */
538 base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
539 base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
540
541 /* Configure data size. */
542 if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
543 {
544 configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
545 }
546
547 /* Configure sequence ID. */
548 configValue |= FLEXSPI_IPCR1_ISEQID(xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
549 base->IPCR1 = configValue;
550
551 if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
552 {
553 handle->state = kFLEXSPI_Busy;
554 result = FLEXSPI_WriteDataDMA(base, handle, xfer->data, xfer->dataSize);
555 }
556 else if (xfer->cmdType == kFLEXSPI_Read)
557 {
558 handle->state = kFLEXSPI_Busy;
559 result = FLEXSPI_ReadDataDMA(base, handle, xfer->data, xfer->dataSize);
560 }
561 else
562 {
563 /* Start Transfer. */
564 base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
565 /* Wait for bus idle. */
566 while (!FLEXSPI_GetBusIdleStatus(base))
567 {
568 }
569 result = FLEXSPI_CheckAndClearError(base, base->INTR);
570
571 handle->state = kFLEXSPI_Idle;
572
573 if (handle->completionCallback != NULL)
574 {
575 handle->completionCallback(base, handle, result, handle->userData);
576 }
577 }
578 }
579
580 return result;
581 }
582
583 /*!
584 * brief Aborts the transfer data using dma.
585 *
586 * This function aborts the transfer data using dma.
587 *
588 * param base FLEXSPI peripheral base address.
589 * param handle Pointer to flexspi_dma_handle_t structure
590 */
FLEXSPI_TransferAbortDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle)591 void FLEXSPI_TransferAbortDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle)
592 {
593 assert(handle != NULL);
594
595 if ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXDMAEN_MASK) != 0x00U)
596 {
597 FLEXSPI_EnableTxDMA(base, false);
598 DMA_AbortTransfer(handle->txDmaHandle);
599 }
600
601 if ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXDMAEN_MASK) != 0x00U)
602 {
603 FLEXSPI_EnableRxDMA(base, false);
604 DMA_AbortTransfer(handle->rxDmaHandle);
605 }
606
607 handle->state = kFLEXSPI_Idle;
608 }
609
FLEXSPI_TransferGetTransferCountDMA(FLEXSPI_Type * base,flexspi_dma_handle_t * handle,size_t * count)610 status_t FLEXSPI_TransferGetTransferCountDMA(FLEXSPI_Type *base, flexspi_dma_handle_t *handle, size_t *count)
611 {
612 assert(handle);
613 assert(count);
614
615 status_t result = kStatus_Success;
616
617 if (handle->state != (uint32_t)kFLEXSPI_Busy)
618 {
619 result = kStatus_NoTransferInProgress;
620 }
621 else
622 {
623 if ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXDMAEN_MASK) != 0x00U)
624 {
625 *count =
626 (handle->transferSize - DMA_GetRemainingBytes(handle->rxDmaHandle->base, handle->rxDmaHandle->channel));
627 }
628 else if ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXDMAEN_MASK) != 0x00U)
629 {
630 *count =
631 (handle->transferSize - DMA_GetRemainingBytes(handle->txDmaHandle->base, handle->txDmaHandle->channel));
632 }
633 else
634 {
635 ; /* Intentional empty for MISRA C-2012 rule 15.7. */
636 }
637 }
638
639 return result;
640 }
641