1 /*
2 * Copyright 2017 - 2021 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_sai_sdma.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.sai_sdma"
14 #endif
15
16 /*******************************************************************************
17 * Definitations
18 ******************************************************************************/
19 /*<! Structure definition for uart_sdma_private_handle_t. The structure is private. */
20 typedef struct _sai_sdma_private_handle
21 {
22 I2S_Type *base;
23 sai_sdma_handle_t *handle;
24 } sai_sdma_private_handle_t;
25
26 /*!@brief _sai_sdma_transfer_state */
27 enum
28 {
29 kSAI_Busy = 0x0U, /*!< SAI is busy */
30 kSAI_Idle, /*!< Transfer is done. */
31 };
32
33 static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS;
34
35 /*<! Private handle only used for internally. */
36 static sai_sdma_private_handle_t s_sdmaPrivateHandle[ARRAY_SIZE(s_saiBases)][2];
37
38 /*******************************************************************************
39 * Prototypes
40 ******************************************************************************/
41 /*!
42 * @brief Get the instance number for SAI.
43 *
44 * @param base SAI base pointer.
45 */
46 static uint32_t SAI_GetInstance(I2S_Type *base);
47
48 /*!
49 * @brief SAI SDMA callback for send.
50 *
51 * @param handle pointer to sai_sdma_handle_t structure which stores the transfer state.
52 * @param userData Parameter for user callback.
53 * @param done If the DMA transfer finished.
54 * @param tcds The TCD index.
55 */
56 static void SAI_TxSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex);
57
58 /*!
59 * @brief SAI SDMA callback for receive.
60 *
61 * @param handle pointer to sai_sdma_handle_t structure which stores the transfer state.
62 * @param userData Parameter for user callback.
63 * @param done If the DMA transfer finished.
64 * @param tcds The TCD index.
65 */
66 static void SAI_RxSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex);
67
68 /*******************************************************************************
69 * Code
70 ******************************************************************************/
SAI_GetInstance(I2S_Type * base)71 static uint32_t SAI_GetInstance(I2S_Type *base)
72 {
73 uint32_t instance;
74
75 /* Find the instance index from base address mappings. */
76 for (instance = 0; instance < ARRAY_SIZE(s_saiBases); instance++)
77 {
78 if (s_saiBases[instance] == base)
79 {
80 break;
81 }
82 }
83
84 assert(instance < ARRAY_SIZE(s_saiBases));
85
86 return instance;
87 }
88
SAI_TxSDMACallback(sdma_handle_t * handle,void * userData,bool transferDone,uint32_t bdIndex)89 static void SAI_TxSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex)
90 {
91 sai_sdma_private_handle_t *privHandle = (sai_sdma_private_handle_t *)userData;
92 sai_sdma_handle_t *saiHandle = privHandle->handle;
93
94 /* If finished a block, call the callback function */
95 (void)memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0, sizeof(sai_transfer_t));
96 saiHandle->queueDriver = (saiHandle->queueDriver + 1U) % SAI_XFER_QUEUE_SIZE;
97 /* Stop SDMA transfer */
98 SDMA_StopChannel(handle->base, handle->channel);
99 if (saiHandle->callback != NULL)
100 {
101 (saiHandle->callback)(privHandle->base, saiHandle, kStatus_SAI_TxIdle, saiHandle->userData);
102 }
103
104 /* If all data finished, just stop the transfer */
105 if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL)
106 {
107 /* Disable dma */
108 SDMA_AbortTransfer(handle);
109 /* Disable DMA enable bit */
110 SAI_TxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false);
111 /* Set the handle state */
112 saiHandle->state = (uint32_t)kSAI_Idle;
113 }
114 }
115
SAI_RxSDMACallback(sdma_handle_t * handle,void * userData,bool transferDone,uint32_t bdIndex)116 static void SAI_RxSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex)
117 {
118 sai_sdma_private_handle_t *privHandle = (sai_sdma_private_handle_t *)userData;
119 sai_sdma_handle_t *saiHandle = privHandle->handle;
120
121 /* If finished a block, call the callback function */
122 (void)memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0, sizeof(sai_transfer_t));
123 saiHandle->queueDriver = (saiHandle->queueDriver + 1U) % SAI_XFER_QUEUE_SIZE;
124 if (saiHandle->callback != NULL)
125 {
126 (saiHandle->callback)(privHandle->base, saiHandle, kStatus_SAI_RxIdle, saiHandle->userData);
127 }
128
129 /* If all data finished, just stop the transfer */
130 if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL)
131 {
132 /* Disable dma */
133 SDMA_AbortTransfer(handle);
134 /* Disable DMA enable bit */
135 SAI_RxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false);
136 /* Set the handle state */
137 saiHandle->state = (uint32_t)kSAI_Idle;
138 }
139 }
140
141 /*!
142 * brief Initializes the SAI SDMA handle.
143 *
144 * This function initializes the SAI master DMA handle, which can be used for other SAI master transactional APIs.
145 * Usually, for a specified SAI instance, call this API once to get the initialized handle.
146 *
147 * param base SAI base pointer.
148 * param handle SAI SDMA handle pointer.
149 * param base SAI peripheral base address.
150 * param callback Pointer to user callback function.
151 * param userData User parameter passed to the callback function.
152 * param dmaHandle SDMA handle pointer, this handle shall be static allocated by users.
153 */
SAI_TransferTxCreateHandleSDMA(I2S_Type * base,sai_sdma_handle_t * handle,sai_sdma_callback_t callback,void * userData,sdma_handle_t * dmaHandle,uint32_t eventSource)154 void SAI_TransferTxCreateHandleSDMA(I2S_Type *base,
155 sai_sdma_handle_t *handle,
156 sai_sdma_callback_t callback,
157 void *userData,
158 sdma_handle_t *dmaHandle,
159 uint32_t eventSource)
160 {
161 assert((handle != NULL) && (dmaHandle != NULL));
162
163 uint32_t instance = SAI_GetInstance(base);
164
165 /* Zero the handle */
166 (void)memset(handle, 0, sizeof(*handle));
167
168 /* Set sai base to handle */
169 handle->dmaHandle = dmaHandle;
170 handle->callback = callback;
171 handle->userData = userData;
172 handle->eventSource = eventSource;
173
174 /* Set SAI state to idle */
175 handle->state = (uint32_t)kSAI_Idle;
176
177 s_sdmaPrivateHandle[instance][0].base = base;
178 s_sdmaPrivateHandle[instance][0].handle = handle;
179
180 SDMA_InstallBDMemory(dmaHandle, handle->bdPool, SAI_XFER_QUEUE_SIZE);
181
182 /* Install callback for Tx dma channel */
183 SDMA_SetCallback(dmaHandle, SAI_TxSDMACallback, &s_sdmaPrivateHandle[instance][0]);
184 }
185
186 /*!
187 * brief Initializes the SAI Rx SDMA handle.
188 *
189 * This function initializes the SAI slave DMA handle, which can be used for other SAI master transactional APIs.
190 * Usually, for a specified SAI instance, call this API once to get the initialized handle.
191 *
192 * param base SAI base pointer.
193 * param handle SAI SDMA handle pointer.
194 * param base SAI peripheral base address.
195 * param callback Pointer to user callback function.
196 * param userData User parameter passed to the callback function.
197 * param dmaHandle SDMA handle pointer, this handle shall be static allocated by users.
198 */
SAI_TransferRxCreateHandleSDMA(I2S_Type * base,sai_sdma_handle_t * handle,sai_sdma_callback_t callback,void * userData,sdma_handle_t * dmaHandle,uint32_t eventSource)199 void SAI_TransferRxCreateHandleSDMA(I2S_Type *base,
200 sai_sdma_handle_t *handle,
201 sai_sdma_callback_t callback,
202 void *userData,
203 sdma_handle_t *dmaHandle,
204 uint32_t eventSource)
205 {
206 assert((handle != NULL) && (dmaHandle != NULL));
207
208 uint32_t instance = SAI_GetInstance(base);
209
210 /* Zero the handle */
211 (void)memset(handle, 0, sizeof(*handle));
212
213 /* Set sai base to handle */
214 handle->dmaHandle = dmaHandle;
215 handle->callback = callback;
216 handle->userData = userData;
217 handle->eventSource = eventSource;
218
219 /* Set SAI state to idle */
220 handle->state = (uint32_t)kSAI_Idle;
221
222 s_sdmaPrivateHandle[instance][1].base = base;
223 s_sdmaPrivateHandle[instance][1].handle = handle;
224
225 SDMA_InstallBDMemory(dmaHandle, handle->bdPool, SAI_XFER_QUEUE_SIZE);
226
227 /* Install callback for Tx dma channel */
228 SDMA_SetCallback(dmaHandle, SAI_RxSDMACallback, &s_sdmaPrivateHandle[instance][1]);
229 }
230
231 /*!
232 * brief Configures the SAI Tx audio.
233 *
234 * param base SAI base pointer.
235 * param handle SAI SDMA handle pointer.
236 * param saiConfig sai configurations
237 */
SAI_TransferTxSetConfigSDMA(I2S_Type * base,sai_sdma_handle_t * handle,sai_transceiver_t * saiConfig)238 void SAI_TransferTxSetConfigSDMA(I2S_Type *base, sai_sdma_handle_t *handle, sai_transceiver_t *saiConfig)
239 {
240 assert((handle != NULL) && (saiConfig != NULL));
241
242 /* Configure the audio format to SAI registers */
243 SAI_TxSetConfig(base, saiConfig);
244
245 handle->bytesPerFrame = saiConfig->serialData.dataWordLength / 8U;
246
247 /* Update the data channel SAI used */
248 handle->channel = saiConfig->startChannel;
249
250 if (saiConfig->channelNums == 0U)
251 {
252 saiConfig->channelNums = 1U;
253 }
254 handle->channelNums = saiConfig->channelNums;
255 handle->channelMask = saiConfig->channelMask;
256 if (saiConfig->channelNums > 1U)
257 {
258 /* fifo address offset, 4U is the address offset between each fifo */
259 handle->fifoOffset = ((saiConfig->endChannel - saiConfig->startChannel) * 4U) / (saiConfig->channelNums - 1U);
260 }
261 else
262 {
263 handle->fifoOffset = 0U;
264 }
265
266 #if defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO)
267 handle->count = ((uint32_t)FSL_FEATURE_SAI_FIFO_COUNTn(base) - (uint32_t)saiConfig->fifo.fifoWatermark) *
268 (uint32_t)saiConfig->channelNums;
269 #else
270 handle->count = 1U * saiConfig->channelNums;
271 #endif /* FSL_FEATURE_SAI_HAS_FIFO */
272
273 /* Clear the channel enable bits until do a send/receive */
274 base->TCR3 &= ~I2S_TCR3_TCE_MASK;
275 }
276
277 /*!
278 * brief Configures the SAI Rx audio.
279 *
280 * param base SAI base pointer.
281 * param handle SAI SDMA handle pointer.
282 * param saiConig sai configurations.
283 */
SAI_TransferRxSetConfigSDMA(I2S_Type * base,sai_sdma_handle_t * handle,sai_transceiver_t * saiConfig)284 void SAI_TransferRxSetConfigSDMA(I2S_Type *base, sai_sdma_handle_t *handle, sai_transceiver_t *saiConfig)
285 {
286 assert((handle != NULL) && (saiConfig != NULL));
287
288 /* Configure the audio format to SAI registers */
289 SAI_RxSetConfig(base, saiConfig);
290
291 handle->bytesPerFrame = saiConfig->serialData.dataWordLength / 8U;
292
293 /* configurations for multififo */
294 if (saiConfig->channelNums == 0U)
295 {
296 saiConfig->channelNums = 1U;
297 }
298
299 handle->channelNums = saiConfig->channelNums;
300 handle->channelMask = saiConfig->channelMask;
301
302 if (saiConfig->channelNums > 1U)
303 {
304 /* fifo address offset, 4U is the address offset between each fifo */
305 handle->fifoOffset = ((saiConfig->endChannel - saiConfig->startChannel) * 4U) / (saiConfig->channelNums - 1U);
306 }
307 else
308 {
309 handle->fifoOffset = 0U;
310 }
311 /* Update the data channel SAI used */
312 handle->channel = saiConfig->startChannel;
313
314 #if defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO)
315 handle->count = (uint32_t)saiConfig->fifo.fifoWatermark * (uint32_t)saiConfig->channelNums;
316 #else
317 handle->count = 1U * saiConfig->channelNums;
318 #endif /* FSL_FEATURE_SAI_HAS_FIFO */
319
320 /* Clear the channel enable bits until do a send/receive */
321 base->RCR3 &= ~I2S_RCR3_RCE_MASK;
322 }
323
324 /*!
325 * brief Performs a non-blocking SAI transfer using DMA.
326 *
327 * note This interface returns immediately after the transfer initiates. Call
328 * SAI_GetTransferStatus to poll the transfer status and check whether the SAI transfer is finished.
329 *
330 * param base SAI base pointer.
331 * param handle SAI SDMA handle pointer.
332 * param xfer Pointer to the DMA transfer structure.
333 * retval kStatus_Success Start a SAI SDMA send successfully.
334 * retval kStatus_InvalidArgument The input argument is invalid.
335 * retval kStatus_TxBusy SAI is busy sending data.
336 */
SAI_TransferSendSDMA(I2S_Type * base,sai_sdma_handle_t * handle,sai_transfer_t * xfer)337 status_t SAI_TransferSendSDMA(I2S_Type *base, sai_sdma_handle_t *handle, sai_transfer_t *xfer)
338 {
339 assert((handle != NULL) && (xfer != NULL));
340 assert((xfer->dataSize % (handle->bytesPerFrame)) == 0U);
341
342 sdma_transfer_config_t config = {0};
343 uint32_t destAddr = SAI_TxGetDataRegisterAddress(base, handle->channel);
344 sdma_handle_t *dmaHandle = handle->dmaHandle;
345 sdma_peripheral_t perType = kSDMA_PeripheralNormal;
346
347 /* Check if input parameter invalid */
348 if ((xfer->data == NULL) || (xfer->dataSize == 0U) || ((handle->channelNums > 1U) && (handle->fifoOffset == 0U)) ||
349 ((handle->channelNums > 1U) &&
350 ((uint16_t)handle->count * handle->bytesPerFrame > (uint16_t)kSDMA_MultiFifoWatermarkLevelMask)) ||
351 ((xfer->dataSize % (handle->bytesPerFrame)) != 0U))
352 {
353 return kStatus_InvalidArgument;
354 }
355
356 if (handle->saiQueue[handle->queueUser].data != NULL)
357 {
358 return kStatus_SAI_QueueFull;
359 }
360
361 /* Change the state of handle */
362 handle->transferSize[handle->queueUser] = xfer->dataSize;
363 handle->saiQueue[handle->queueUser].data = xfer->data;
364 handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
365
366 #if defined(FSL_FEATURE_SOC_SPBA_COUNT) && (FSL_FEATURE_SOC_SPBA_COUNT > 0)
367 bool isSpba = SDMA_IsPeripheralInSPBA((uint32_t)base);
368 /* Judge if the instance is located in SPBA */
369 if (isSpba)
370 {
371 perType = kSDMA_PeripheralNormal_SP;
372 }
373 #endif /* FSL_FEATURE_SOC_SPBA_COUNT */
374
375 /* if channel numbers > 1U, should enable multififo */
376 if (handle->channelNums > 1U)
377 {
378 perType = kSDMA_PeripheralMultiFifoSaiTX;
379 /* multi fifo configurations */
380 SDMA_SetMultiFifoConfig(&config, handle->channelNums, (uint32_t)handle->fifoOffset / sizeof(uint32_t) - 1UL);
381 }
382
383 /* Prepare sdma configure */
384 SDMA_PrepareTransfer(&config, (uint32_t)xfer->data, destAddr, handle->bytesPerFrame, handle->bytesPerFrame,
385 (uint32_t)handle->count * handle->bytesPerFrame, xfer->dataSize, handle->eventSource, perType,
386 kSDMA_MemoryToPeripheral);
387
388 if (handle->queueUser == SAI_XFER_QUEUE_SIZE - 1U)
389 {
390 SDMA_ConfigBufferDescriptor(&dmaHandle->BDPool[handle->queueUser], (uint32_t)(xfer->data), destAddr,
391 config.destTransferSize, xfer->dataSize, true, true, true,
392 kSDMA_MemoryToPeripheral);
393 }
394 else
395 {
396 SDMA_ConfigBufferDescriptor(&dmaHandle->BDPool[handle->queueUser], (uint32_t)(xfer->data), destAddr,
397 config.destTransferSize, xfer->dataSize, true, true, false,
398 kSDMA_MemoryToPeripheral);
399 }
400
401 handle->queueUser = (handle->queueUser + 1U) % SAI_XFER_QUEUE_SIZE;
402
403 if (handle->state != (uint32_t)kSAI_Busy)
404 {
405 SDMA_SubmitTransfer(handle->dmaHandle, &config);
406
407 /* Start DMA transfer */
408 SDMA_StartTransfer(handle->dmaHandle);
409
410 /* Enable DMA enable bit */
411 SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
412
413 /* Enable SAI Tx clock */
414 SAI_TxEnable(base, true);
415
416 /* Enable the channel FIFO */
417 base->TCR3 |= I2S_TCR3_TCE(handle->channelMask);
418 }
419 handle->state = (uint32_t)kSAI_Busy;
420
421 return kStatus_Success;
422 }
423
424 /*!
425 * brief Performs a non-blocking SAI receive using SDMA.
426 *
427 * note This interface returns immediately after the transfer initiates. Call
428 * the SAI_GetReceiveRemainingBytes to poll the transfer status and check whether the SAI transfer is finished.
429 *
430 * param base SAI base pointer
431 * param handle SAI SDMA handle pointer.
432 * param xfer Pointer to DMA transfer structure.
433 * retval kStatus_Success Start a SAI SDMA receive successfully.
434 * retval kStatus_InvalidArgument The input argument is invalid.
435 * retval kStatus_RxBusy SAI is busy receiving data.
436 */
SAI_TransferReceiveSDMA(I2S_Type * base,sai_sdma_handle_t * handle,sai_transfer_t * xfer)437 status_t SAI_TransferReceiveSDMA(I2S_Type *base, sai_sdma_handle_t *handle, sai_transfer_t *xfer)
438 {
439 assert((handle != NULL) && (xfer != NULL));
440 assert((xfer->dataSize % (handle->bytesPerFrame)) == 0U);
441
442 sdma_transfer_config_t config = {0};
443 sdma_handle_t *dmaHandle = handle->dmaHandle;
444 uint32_t srcAddr = SAI_RxGetDataRegisterAddress(base, handle->channel);
445 sdma_peripheral_t perType = kSDMA_PeripheralNormal;
446
447 /* Check if input parameter invalid */
448 if ((xfer->data == NULL) || (xfer->dataSize == 0U) || ((handle->channelNums > 1U) && (handle->fifoOffset == 0U)) ||
449 ((handle->channelNums > 1U) &&
450 ((uint16_t)handle->count * handle->bytesPerFrame > (uint16_t)kSDMA_MultiFifoWatermarkLevelMask)) ||
451 ((xfer->dataSize % (handle->bytesPerFrame)) != 0U))
452 {
453 return kStatus_InvalidArgument;
454 }
455
456 if (handle->saiQueue[handle->queueUser].data != NULL)
457 {
458 return kStatus_SAI_QueueFull;
459 }
460
461 /* Update queue state */
462 handle->transferSize[handle->queueUser] = xfer->dataSize;
463 handle->saiQueue[handle->queueUser].data = xfer->data;
464 handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
465
466 #if defined(FSL_FEATURE_SOC_SPBA_COUNT) && (FSL_FEATURE_SOC_SPBA_COUNT > 0)
467 bool isSpba = SDMA_IsPeripheralInSPBA((uint32_t)base);
468 /* Judge if the instance is located in SPBA */
469 if (isSpba)
470 {
471 perType = kSDMA_PeripheralNormal_SP;
472 }
473 #endif /* FSL_FEATURE_SOC_SPBA_COUNT */
474
475 /* if channel numbers > 1U, should enable multififo */
476 if (handle->channelNums > 1U)
477 {
478 perType = kSDMA_PeripheralMultiFifoSaiRX;
479 /* multi fifo configurations */
480 SDMA_SetMultiFifoConfig(&config, handle->channelNums, (uint32_t)handle->fifoOffset / sizeof(uint32_t) - 1UL);
481 }
482
483 /* Prepare sdma configure */
484 SDMA_PrepareTransfer(&config, srcAddr, (uint32_t)xfer->data, handle->bytesPerFrame, handle->bytesPerFrame,
485 (uint32_t)handle->count * handle->bytesPerFrame, xfer->dataSize, handle->eventSource, perType,
486 kSDMA_PeripheralToMemory);
487
488 if (handle->queueUser == SAI_XFER_QUEUE_SIZE - 1U)
489 {
490 SDMA_ConfigBufferDescriptor(&dmaHandle->BDPool[handle->queueUser], srcAddr, (uint32_t)xfer->data,
491 config.destTransferSize, xfer->dataSize, true, true, true,
492 kSDMA_PeripheralToMemory);
493 }
494 else
495 {
496 SDMA_ConfigBufferDescriptor(&dmaHandle->BDPool[handle->queueUser], srcAddr, (uint32_t)xfer->data,
497 config.destTransferSize, xfer->dataSize, true, true, false,
498 kSDMA_PeripheralToMemory);
499 }
500
501 handle->queueUser = (handle->queueUser + 1U) % SAI_XFER_QUEUE_SIZE;
502
503 if (handle->state != (uint32_t)kSAI_Busy)
504 {
505 SDMA_SubmitTransfer(handle->dmaHandle, &config);
506
507 /* Start DMA transfer */
508 SDMA_StartTransfer(handle->dmaHandle);
509
510 /* Enable DMA enable bit */
511 SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
512
513 /* Enable SAI Rx clock */
514 SAI_RxEnable(base, true);
515
516 /* Enable the channel FIFO */
517 base->RCR3 |= I2S_RCR3_RCE(handle->channelMask);
518 }
519
520 handle->state = (uint32_t)kSAI_Busy;
521
522 return kStatus_Success;
523 }
524
525 /*!
526 * brief Aborts a SAI transfer using SDMA.
527 *
528 * param base SAI base pointer.
529 * param handle SAI SDMA handle pointer.
530 */
SAI_TransferAbortSendSDMA(I2S_Type * base,sai_sdma_handle_t * handle)531 void SAI_TransferAbortSendSDMA(I2S_Type *base, sai_sdma_handle_t *handle)
532 {
533 assert(handle != NULL);
534
535 /* Disable dma */
536 SDMA_AbortTransfer(handle->dmaHandle);
537
538 /* Disable the channel FIFO */
539 base->TCR3 &= ~I2S_TCR3_TCE_MASK;
540
541 /* Disable DMA enable bit */
542 SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false);
543
544 /* Reset the FIFO pointer, at the same time clear all error flags if set */
545 base->TCSR |= (I2S_TCSR_FR_MASK | I2S_TCSR_SR_MASK);
546 base->TCSR &= ~I2S_TCSR_SR_MASK;
547
548 /* Disable Tx */
549 SAI_TxEnable(base, false);
550
551 /* Handle the queue index */
552 (void)memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
553 handle->queueDriver = (handle->queueDriver + 1U) % (uint8_t)SAI_XFER_QUEUE_SIZE;
554
555 /* Set the handle state */
556 handle->state = (uint32_t)kSAI_Idle;
557 }
558
559 /*!
560 * brief Terminate all the SAI sdma send transfer.
561 *
562 * param base SAI base pointer.
563 * param handle SAI SDMA handle pointer.
564 */
SAI_TransferTerminateSendSDMA(I2S_Type * base,sai_sdma_handle_t * handle)565 void SAI_TransferTerminateSendSDMA(I2S_Type *base, sai_sdma_handle_t *handle)
566 {
567 assert(handle != NULL);
568
569 /* abort current transfer */
570 SAI_TransferAbortSendSDMA(base, handle);
571
572 /* Clear all the internal information */
573 (void)memset(handle->bdPool, 0, sizeof(handle->bdPool));
574 (void)memset(handle->saiQueue, 0, sizeof(handle->saiQueue));
575 (void)memset(handle->transferSize, 0, sizeof(handle->transferSize));
576
577 handle->queueUser = 0U;
578 handle->queueDriver = 0U;
579
580 /* Reset the internal state of bd pool */
581 SDMA_InstallBDMemory(handle->dmaHandle, handle->bdPool, handle->dmaHandle->bdCount);
582 }
583
584 /*!
585 * brief Aborts a SAI receive using SDMA.
586 *
587 * param base SAI base pointer
588 * param handle SAI SDMA handle pointer.
589 */
SAI_TransferAbortReceiveSDMA(I2S_Type * base,sai_sdma_handle_t * handle)590 void SAI_TransferAbortReceiveSDMA(I2S_Type *base, sai_sdma_handle_t *handle)
591 {
592 assert(handle != NULL);
593
594 /* Disable dma */
595 SDMA_AbortTransfer(handle->dmaHandle);
596
597 /* Disable the channel FIFO */
598 base->RCR3 &= ~I2S_RCR3_RCE_MASK;
599
600 /* Disable DMA enable bit */
601 SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false);
602
603 /* Disable Rx */
604 SAI_RxEnable(base, false);
605
606 /* Reset the FIFO pointer, at the same time clear all error flags if set */
607 base->RCSR |= (I2S_RCSR_FR_MASK | I2S_RCSR_SR_MASK);
608 base->RCSR &= ~I2S_RCSR_SR_MASK;
609
610 /* Handle the queue index */
611 (void)memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
612 handle->queueDriver = (handle->queueDriver + 1U) % (uint8_t)SAI_XFER_QUEUE_SIZE;
613
614 /* Set the handle state */
615 handle->state = (uint32_t)kSAI_Idle;
616 }
617
618 /*!
619 * brief Terminate all the SAI sdma receive transfer.
620 *
621 * param base SAI base pointer.
622 * param handle SAI SDMA handle pointer.
623 */
SAI_TransferTerminateReceiveSDMA(I2S_Type * base,sai_sdma_handle_t * handle)624 void SAI_TransferTerminateReceiveSDMA(I2S_Type *base, sai_sdma_handle_t *handle)
625 {
626 assert(handle != NULL);
627
628 /* abort current transfer */
629 SAI_TransferAbortReceiveSDMA(base, handle);
630
631 /* Clear all the internal information */
632 (void)memset(handle->bdPool, 0, sizeof(handle->bdPool));
633 (void)memset(handle->saiQueue, 0, sizeof(handle->saiQueue));
634 (void)memset(handle->transferSize, 0, sizeof(handle->transferSize));
635
636 handle->queueUser = 0U;
637 handle->queueDriver = 0U;
638
639 /* Reset the internal state of bd pool */
640 SDMA_InstallBDMemory(handle->dmaHandle, handle->bdPool, handle->dmaHandle->bdCount);
641 }
642