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