File indexing completed on 2025-05-11 08:23:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fsl_sai_edma.h"
0010
0011
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.sai_edma"
0014 #endif
0015
0016
0017
0018
0019
0020 #define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)(address) + 32UL) & ~0x1FU)
0021
0022 static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS;
0023
0024 #define SAI_CHANNEL_MAP_MODULO(channel) (channel == 2U ? kEDMA_Modulo8bytes : kEDMA_Modulo16bytes)
0025
0026
0027 typedef struct sai_edma_private_handle
0028 {
0029 I2S_Type *base;
0030 sai_edma_handle_t *handle;
0031 } sai_edma_private_handle_t;
0032
0033
0034 enum
0035 {
0036 kSAI_Busy = 0x0U,
0037 kSAI_BusyLoopTransfer,
0038 kSAI_Idle,
0039 };
0040
0041
0042 static sai_edma_private_handle_t s_edmaPrivateHandle[ARRAY_SIZE(s_saiBases)][2];
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 static uint32_t SAI_GetInstance(I2S_Type *base);
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 static void SAI_TxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds);
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static void SAI_RxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds);
0073
0074
0075
0076
0077 static uint32_t SAI_GetInstance(I2S_Type *base)
0078 {
0079 uint32_t instance;
0080
0081
0082 for (instance = 0; instance < ARRAY_SIZE(s_saiBases); instance++)
0083 {
0084 if (s_saiBases[instance] == base)
0085 {
0086 break;
0087 }
0088 }
0089
0090 assert(instance < ARRAY_SIZE(s_saiBases));
0091
0092 return instance;
0093 }
0094
0095 static void SAI_TxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds)
0096 {
0097 sai_edma_private_handle_t *privHandle = (sai_edma_private_handle_t *)userData;
0098 sai_edma_handle_t *saiHandle = privHandle->handle;
0099 status_t status = kStatus_SAI_TxBusy;
0100
0101 if (saiHandle->state != (uint32_t)kSAI_BusyLoopTransfer)
0102 {
0103 if (saiHandle->queueDriver + tcds > (uint32_t)SAI_XFER_QUEUE_SIZE)
0104 {
0105 (void)memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0,
0106 sizeof(sai_transfer_t) * ((uint32_t)SAI_XFER_QUEUE_SIZE - saiHandle->queueDriver));
0107 (void)memset(&saiHandle->saiQueue[0U], 0,
0108 sizeof(sai_transfer_t) * (saiHandle->queueDriver + tcds - (uint32_t)SAI_XFER_QUEUE_SIZE));
0109 }
0110 else
0111 {
0112 (void)memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0, sizeof(sai_transfer_t) * tcds);
0113 }
0114 saiHandle->queueDriver = (uint8_t)((saiHandle->queueDriver + tcds) % (uint32_t)SAI_XFER_QUEUE_SIZE);
0115
0116
0117 if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL)
0118 {
0119
0120 SAI_TxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false);
0121 EDMA_AbortTransfer(handle);
0122 status = kStatus_SAI_TxIdle;
0123 }
0124 }
0125
0126
0127 if (saiHandle->callback != NULL)
0128 {
0129 (saiHandle->callback)(privHandle->base, saiHandle, status, saiHandle->userData);
0130 }
0131 }
0132
0133 static void SAI_RxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds)
0134 {
0135 sai_edma_private_handle_t *privHandle = (sai_edma_private_handle_t *)userData;
0136 sai_edma_handle_t *saiHandle = privHandle->handle;
0137 status_t status = kStatus_SAI_RxBusy;
0138
0139 if (saiHandle->state != (uint32_t)kSAI_BusyLoopTransfer)
0140 {
0141 if (saiHandle->queueDriver + tcds > (uint32_t)SAI_XFER_QUEUE_SIZE)
0142 {
0143 (void)memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0,
0144 sizeof(sai_transfer_t) * ((uint32_t)SAI_XFER_QUEUE_SIZE - saiHandle->queueDriver));
0145 (void)memset(&saiHandle->saiQueue[0U], 0,
0146 sizeof(sai_transfer_t) * (saiHandle->queueDriver + tcds - (uint32_t)SAI_XFER_QUEUE_SIZE));
0147 }
0148 else
0149 {
0150 (void)memset(&saiHandle->saiQueue[saiHandle->queueDriver], 0, sizeof(sai_transfer_t) * tcds);
0151 }
0152 saiHandle->queueDriver = (uint8_t)((saiHandle->queueDriver + tcds) % (uint32_t)SAI_XFER_QUEUE_SIZE);
0153
0154
0155 if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL)
0156 {
0157
0158 SAI_RxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false);
0159 EDMA_AbortTransfer(handle);
0160 status = kStatus_SAI_RxIdle;
0161 }
0162 }
0163
0164
0165 if (saiHandle->callback != NULL)
0166 {
0167 (saiHandle->callback)(privHandle->base, saiHandle, status, saiHandle->userData);
0168 }
0169 }
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 void SAI_TransferTxCreateHandleEDMA(
0185 I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *txDmaHandle)
0186 {
0187 assert((handle != NULL) && (txDmaHandle != NULL));
0188
0189 uint32_t instance = SAI_GetInstance(base);
0190
0191
0192 (void)memset(handle, 0, sizeof(*handle));
0193
0194
0195 handle->dmaHandle = txDmaHandle;
0196 handle->callback = callback;
0197 handle->userData = userData;
0198
0199
0200 handle->state = (uint32_t)kSAI_Idle;
0201
0202 s_edmaPrivateHandle[instance][0].base = base;
0203 s_edmaPrivateHandle[instance][0].handle = handle;
0204
0205
0206 EDMA_InstallTCDMemory(txDmaHandle, (edma_tcd_t *)(STCD_ADDR(handle->tcd)), SAI_XFER_QUEUE_SIZE);
0207
0208
0209 EDMA_SetCallback(txDmaHandle, SAI_TxEDMACallback, &s_edmaPrivateHandle[instance][0]);
0210 }
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 void SAI_TransferRxCreateHandleEDMA(
0226 I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *rxDmaHandle)
0227 {
0228 assert((handle != NULL) && (rxDmaHandle != NULL));
0229
0230 uint32_t instance = SAI_GetInstance(base);
0231
0232
0233 (void)memset(handle, 0, sizeof(*handle));
0234
0235
0236 handle->dmaHandle = rxDmaHandle;
0237 handle->callback = callback;
0238 handle->userData = userData;
0239
0240
0241 handle->state = (uint32_t)kSAI_Idle;
0242
0243 s_edmaPrivateHandle[instance][1].base = base;
0244 s_edmaPrivateHandle[instance][1].handle = handle;
0245
0246
0247 EDMA_InstallTCDMemory(rxDmaHandle, STCD_ADDR(handle->tcd), SAI_XFER_QUEUE_SIZE);
0248
0249
0250 EDMA_SetCallback(rxDmaHandle, SAI_RxEDMACallback, &s_edmaPrivateHandle[instance][1]);
0251 }
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 void SAI_TransferTxSetFormatEDMA(I2S_Type *base,
0271 sai_edma_handle_t *handle,
0272 sai_transfer_format_t *format,
0273 uint32_t mclkSourceClockHz,
0274 uint32_t bclkSourceClockHz)
0275 {
0276 assert((handle != NULL) && (format != NULL));
0277
0278
0279 SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
0280
0281
0282 if (format->bitWidth == 24U)
0283 {
0284 handle->bytesPerFrame = 4U;
0285 }
0286 else
0287 {
0288 handle->bytesPerFrame = (uint8_t)(format->bitWidth / 8U);
0289 }
0290
0291
0292 handle->channel = format->channel;
0293
0294
0295 base->TCR3 &= ~I2S_TCR3_TCE_MASK;
0296 #if defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO)
0297 handle->count = (uint8_t)((uint32_t)FSL_FEATURE_SAI_FIFO_COUNTn(base) - format->watermark);
0298 #else
0299 handle->count = 1U;
0300 #endif
0301 }
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322 void SAI_TransferTxSetConfigEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transceiver_t *saiConfig)
0323 {
0324 assert((handle != NULL) && (saiConfig != NULL));
0325
0326
0327 SAI_TxSetConfig(base, saiConfig);
0328
0329 #if defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE
0330
0331 assert(
0332 (saiConfig->channelNums <= 1U) ||
0333 ((saiConfig->channelNums > 1U) && ((saiConfig->fifo.fifoCombine == kSAI_FifoCombineModeEnabledOnWrite) ||
0334 (saiConfig->fifo.fifoCombine == kSAI_FifoCombineModeEnabledOnReadWrite))));
0335 #endif
0336
0337
0338 if (saiConfig->serialData.dataWordLength == 24U)
0339 {
0340 handle->bytesPerFrame = 4U;
0341 }
0342 else
0343 {
0344 handle->bytesPerFrame = saiConfig->serialData.dataWordLength / 8U;
0345 }
0346
0347 handle->channel = saiConfig->startChannel;
0348 handle->channelMask = saiConfig->channelMask;
0349 handle->channelNums = saiConfig->channelNums;
0350
0351
0352 base->TCR3 &= ~I2S_TCR3_TCE_MASK;
0353 #if defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO)
0354 handle->count = (uint8_t)((uint32_t)FSL_FEATURE_SAI_FIFO_COUNTn(base) - saiConfig->fifo.fifoWatermark);
0355 #else
0356 handle->count = 1U;
0357 #endif
0358 }
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 void SAI_TransferRxSetFormatEDMA(I2S_Type *base,
0378 sai_edma_handle_t *handle,
0379 sai_transfer_format_t *format,
0380 uint32_t mclkSourceClockHz,
0381 uint32_t bclkSourceClockHz)
0382 {
0383 assert((handle != NULL) && (format != NULL));
0384
0385
0386 SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
0387
0388
0389 if (format->bitWidth == 24U)
0390 {
0391 handle->bytesPerFrame = 4U;
0392 }
0393 else
0394 {
0395 handle->bytesPerFrame = (uint8_t)(format->bitWidth / 8U);
0396 }
0397
0398
0399 handle->channel = format->channel;
0400
0401
0402 base->RCR3 &= ~I2S_RCR3_RCE_MASK;
0403 #if defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO)
0404 handle->count = format->watermark;
0405 #else
0406 handle->count = 1U;
0407 #endif
0408 }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429 void SAI_TransferRxSetConfigEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transceiver_t *saiConfig)
0430 {
0431 assert((handle != NULL) && (saiConfig != NULL));
0432
0433
0434 SAI_RxSetConfig(base, saiConfig);
0435
0436 #if defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE
0437
0438 assert(
0439 (saiConfig->channelNums <= 1U) ||
0440 ((saiConfig->channelNums > 1U) && ((saiConfig->fifo.fifoCombine == kSAI_FifoCombineModeEnabledOnRead) ||
0441 (saiConfig->fifo.fifoCombine == kSAI_FifoCombineModeEnabledOnReadWrite))));
0442 #endif
0443
0444
0445 if (saiConfig->serialData.dataWordLength == 24U)
0446 {
0447 handle->bytesPerFrame = 4U;
0448 }
0449 else
0450 {
0451 handle->bytesPerFrame = saiConfig->serialData.dataWordLength / 8U;
0452 }
0453
0454
0455 handle->channel = saiConfig->startChannel;
0456 handle->channelMask = saiConfig->channelMask;
0457 handle->channelNums = saiConfig->channelNums;
0458
0459 base->RCR3 &= ~I2S_RCR3_RCE_MASK;
0460 #if defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO)
0461 handle->count = saiConfig->fifo.fifoWatermark;
0462 #else
0463 handle->count = 1U;
0464 #endif
0465 }
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer)
0487 {
0488 assert((handle != NULL) && (xfer != NULL));
0489
0490 edma_transfer_config_t config = {0};
0491 uint32_t destAddr = SAI_TxGetDataRegisterAddress(base, handle->channel);
0492 uint32_t destOffset = 0U;
0493
0494
0495 if ((xfer->data == NULL) || (xfer->dataSize == 0U))
0496 {
0497 return kStatus_InvalidArgument;
0498 }
0499
0500 if (handle->saiQueue[handle->queueUser].data != NULL)
0501 {
0502 return kStatus_SAI_QueueFull;
0503 }
0504
0505
0506 handle->state = (uint32_t)kSAI_Busy;
0507
0508
0509 handle->transferSize[handle->queueUser] = xfer->dataSize;
0510 handle->saiQueue[handle->queueUser].data = xfer->data;
0511 handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
0512 handle->queueUser = (handle->queueUser + 1U) % (uint8_t)SAI_XFER_QUEUE_SIZE;
0513
0514 #if !(defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
0515 if (handle->channelNums > 1U)
0516 {
0517 destOffset = sizeof(uint32_t);
0518 }
0519 #endif
0520
0521
0522 EDMA_PrepareTransferConfig(&config, xfer->data, (uint32_t)handle->bytesPerFrame, (int16_t)handle->bytesPerFrame,
0523 (uint32_t *)destAddr, (uint32_t)handle->bytesPerFrame, (int16_t)destOffset,
0524 (uint32_t)handle->count * handle->bytesPerFrame, xfer->dataSize);
0525
0526
0527 handle->nbytes = handle->count * handle->bytesPerFrame;
0528
0529 if (EDMA_SubmitTransfer(handle->dmaHandle, &config) != kStatus_Success)
0530 {
0531 return kStatus_SAI_QueueFull;
0532 }
0533
0534 #if !(defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
0535 if (handle->channelNums > 1U)
0536 {
0537 if ((handle->channelNums % 2U) != 0U)
0538 {
0539 return kStatus_InvalidArgument;
0540 }
0541
0542 EDMA_SetModulo(handle->dmaHandle->base, handle->dmaHandle->channel, kEDMA_ModuloDisable,
0543 SAI_CHANNEL_MAP_MODULO(handle->channelNums));
0544 }
0545 #endif
0546
0547 EDMA_StartTransfer(handle->dmaHandle);
0548
0549
0550 SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
0551
0552
0553 SAI_TxEnable(base, true);
0554
0555
0556 base->TCR3 |= I2S_TCR3_TCE(handle->channelMask);
0557
0558 return kStatus_Success;
0559 }
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer)
0581 {
0582 assert((handle != NULL) && (xfer != NULL));
0583
0584 edma_transfer_config_t config = {0};
0585 uint32_t srcAddr = SAI_RxGetDataRegisterAddress(base, handle->channel);
0586 uint32_t srcOffset = 0U;
0587
0588
0589 if ((xfer->data == NULL) || (xfer->dataSize == 0U))
0590 {
0591 return kStatus_InvalidArgument;
0592 }
0593
0594 if (handle->saiQueue[handle->queueUser].data != NULL)
0595 {
0596 return kStatus_SAI_QueueFull;
0597 }
0598
0599
0600 handle->state = (uint32_t)kSAI_Busy;
0601
0602
0603 handle->transferSize[handle->queueUser] = xfer->dataSize;
0604 handle->saiQueue[handle->queueUser].data = xfer->data;
0605 handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
0606 handle->queueUser = (handle->queueUser + 1U) % (uint8_t)SAI_XFER_QUEUE_SIZE;
0607
0608 #if !(defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
0609 if (handle->channelNums > 1U)
0610 {
0611 srcOffset = sizeof(uint32_t);
0612 }
0613 #endif
0614
0615
0616 EDMA_PrepareTransferConfig(&config, (uint32_t *)srcAddr, (uint32_t)handle->bytesPerFrame, (int16_t)srcOffset,
0617 xfer->data, (uint32_t)handle->bytesPerFrame, (int16_t)handle->bytesPerFrame,
0618 (uint32_t)handle->count * handle->bytesPerFrame, xfer->dataSize);
0619
0620 handle->nbytes = handle->count * handle->bytesPerFrame;
0621
0622 if (EDMA_SubmitTransfer(handle->dmaHandle, &config) != kStatus_Success)
0623 {
0624 return kStatus_SAI_QueueFull;
0625 }
0626
0627 #if !(defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE)
0628 if (handle->channelNums > 1U)
0629 {
0630 if ((handle->channelNums % 2U) != 0U)
0631 {
0632 return kStatus_InvalidArgument;
0633 }
0634
0635 EDMA_SetModulo(handle->dmaHandle->base, handle->dmaHandle->channel, SAI_CHANNEL_MAP_MODULO(handle->channelNums),
0636 kEDMA_ModuloDisable);
0637 }
0638 #endif
0639
0640 EDMA_StartTransfer(handle->dmaHandle);
0641
0642
0643 SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
0644
0645
0646 base->RCR3 |= I2S_RCR3_RCE(handle->channelMask);
0647
0648
0649 SAI_RxEnable(base, true);
0650
0651 return kStatus_Success;
0652 }
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671 status_t SAI_TransferSendLoopEDMA(I2S_Type *base,
0672 sai_edma_handle_t *handle,
0673 sai_transfer_t *xfer,
0674 uint32_t loopTransferCount)
0675 {
0676 assert((handle != NULL) && (xfer != NULL));
0677
0678 edma_transfer_config_t config = {0};
0679 uint32_t destAddr = SAI_TxGetDataRegisterAddress(base, handle->channel);
0680 sai_transfer_t *transfer = xfer;
0681 edma_tcd_t *currentTCD = STCD_ADDR(handle->tcd);
0682 uint32_t tcdIndex = 0U;
0683
0684
0685 handle->state = (uint32_t)kSAI_Busy;
0686
0687 for (uint32_t i = 0U; i < loopTransferCount; i++)
0688 {
0689 transfer = &xfer[i];
0690
0691 if ((transfer->data == NULL) || (transfer->dataSize == 0U) || (tcdIndex >= (uint32_t)SAI_XFER_QUEUE_SIZE))
0692 {
0693 return kStatus_InvalidArgument;
0694 }
0695
0696
0697 handle->transferSize[tcdIndex] = transfer->dataSize;
0698 handle->saiQueue[tcdIndex].data = transfer->data;
0699 handle->saiQueue[tcdIndex].dataSize = transfer->dataSize;
0700
0701
0702 EDMA_PrepareTransfer(&config, transfer->data, handle->bytesPerFrame, (uint32_t *)destAddr,
0703 handle->bytesPerFrame, (uint32_t)handle->count * handle->bytesPerFrame, transfer->dataSize,
0704 kEDMA_MemoryToPeripheral);
0705
0706 if (i == (loopTransferCount - 1U))
0707 {
0708 EDMA_TcdSetTransferConfig(¤tTCD[tcdIndex], &config, ¤tTCD[0U]);
0709 EDMA_TcdEnableInterrupts(¤tTCD[tcdIndex], (uint32_t)kEDMA_MajorInterruptEnable);
0710 handle->state = (uint32_t)kSAI_BusyLoopTransfer;
0711 break;
0712 }
0713 else
0714 {
0715 EDMA_TcdSetTransferConfig(¤tTCD[tcdIndex], &config, ¤tTCD[tcdIndex + 1U]);
0716 EDMA_TcdEnableInterrupts(¤tTCD[tcdIndex], (uint32_t)kEDMA_MajorInterruptEnable);
0717 }
0718
0719 tcdIndex = tcdIndex + 1U;
0720 }
0721
0722 EDMA_InstallTCD(handle->dmaHandle->base, handle->dmaHandle->channel, ¤tTCD[0]);
0723
0724 EDMA_StartTransfer(handle->dmaHandle);
0725
0726
0727 SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
0728
0729
0730 SAI_TxEnable(base, true);
0731
0732
0733 base->TCR3 |= I2S_TCR3_TCE(1UL << handle->channel);
0734
0735 return kStatus_Success;
0736 }
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755 status_t SAI_TransferReceiveLoopEDMA(I2S_Type *base,
0756 sai_edma_handle_t *handle,
0757 sai_transfer_t *xfer,
0758 uint32_t loopTransferCount)
0759 {
0760 assert((handle != NULL) && (xfer != NULL));
0761
0762 edma_transfer_config_t config = {0};
0763 uint32_t srcAddr = SAI_RxGetDataRegisterAddress(base, handle->channel);
0764 sai_transfer_t *transfer = xfer;
0765 edma_tcd_t *currentTCD = STCD_ADDR(handle->tcd);
0766 uint32_t tcdIndex = 0U;
0767
0768
0769 handle->state = (uint32_t)kSAI_Busy;
0770
0771 for (uint32_t i = 0U; i < loopTransferCount; i++)
0772 {
0773 transfer = &xfer[i];
0774
0775 if ((tcdIndex >= (uint32_t)SAI_XFER_QUEUE_SIZE) || (xfer->data == NULL) || (xfer->dataSize == 0U))
0776 {
0777 return kStatus_InvalidArgument;
0778 }
0779
0780
0781 handle->transferSize[tcdIndex] = transfer->dataSize;
0782 handle->saiQueue[tcdIndex].data = transfer->data;
0783 handle->saiQueue[tcdIndex].dataSize = transfer->dataSize;
0784
0785
0786 EDMA_PrepareTransfer(&config, (uint32_t *)srcAddr, handle->bytesPerFrame, transfer->data, handle->bytesPerFrame,
0787 (uint32_t)handle->count * handle->bytesPerFrame, transfer->dataSize,
0788 kEDMA_PeripheralToMemory);
0789
0790 if (i == (loopTransferCount - 1U))
0791 {
0792 EDMA_TcdSetTransferConfig(¤tTCD[tcdIndex], &config, ¤tTCD[0U]);
0793 EDMA_TcdEnableInterrupts(¤tTCD[tcdIndex], (uint32_t)kEDMA_MajorInterruptEnable);
0794 handle->state = (uint32_t)kSAI_BusyLoopTransfer;
0795 break;
0796 }
0797 else
0798 {
0799 EDMA_TcdSetTransferConfig(¤tTCD[tcdIndex], &config, ¤tTCD[tcdIndex + 1U]);
0800 EDMA_TcdEnableInterrupts(¤tTCD[tcdIndex], (uint32_t)kEDMA_MajorInterruptEnable);
0801 }
0802
0803 tcdIndex = tcdIndex + 1U;
0804 }
0805
0806 EDMA_InstallTCD(handle->dmaHandle->base, handle->dmaHandle->channel, ¤tTCD[0]);
0807
0808 EDMA_StartTransfer(handle->dmaHandle);
0809
0810 SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, true);
0811
0812
0813 base->RCR3 |= I2S_RCR3_RCE(1UL << handle->channel);
0814
0815
0816 SAI_RxEnable(base, true);
0817
0818 return kStatus_Success;
0819 }
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830 void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle)
0831 {
0832 assert(handle != NULL);
0833
0834
0835 EDMA_AbortTransfer(handle->dmaHandle);
0836
0837
0838 base->TCR3 &= ~I2S_TCR3_TCE_MASK;
0839
0840
0841 SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false);
0842
0843
0844 SAI_TxEnable(base, false);
0845
0846
0847 if ((base->TCSR & I2S_TCSR_TE_MASK) == 0UL)
0848 {
0849 base->TCSR |= (I2S_TCSR_FR_MASK | I2S_TCSR_SR_MASK);
0850 base->TCSR &= ~I2S_TCSR_SR_MASK;
0851 }
0852
0853
0854 (void)memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
0855 handle->queueDriver = (handle->queueDriver + 1U) % (uint8_t)SAI_XFER_QUEUE_SIZE;
0856
0857
0858 handle->state = (uint32_t)kSAI_Idle;
0859 }
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870 void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle)
0871 {
0872 assert(handle != NULL);
0873
0874
0875 EDMA_AbortTransfer(handle->dmaHandle);
0876
0877
0878 base->RCR3 &= ~I2S_RCR3_RCE_MASK;
0879
0880
0881 SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false);
0882
0883
0884 SAI_RxEnable(base, false);
0885
0886
0887 if ((base->RCSR & I2S_RCSR_RE_MASK) == 0UL)
0888 {
0889 base->RCSR |= (I2S_RCSR_FR_MASK | I2S_RCSR_SR_MASK);
0890 base->RCSR &= ~I2S_RCSR_SR_MASK;
0891 }
0892
0893
0894 (void)memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
0895 handle->queueDriver = (handle->queueDriver + 1U) % (uint8_t)SAI_XFER_QUEUE_SIZE;
0896
0897
0898 handle->state = (uint32_t)kSAI_Idle;
0899 }
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910 void SAI_TransferTerminateSendEDMA(I2S_Type *base, sai_edma_handle_t *handle)
0911 {
0912 assert(handle != NULL);
0913
0914
0915 SAI_TransferAbortSendEDMA(base, handle);
0916
0917
0918 (void)memset(handle->tcd, 0, sizeof(handle->tcd));
0919 (void)memset(handle->saiQueue, 0, sizeof(handle->saiQueue));
0920 (void)memset(handle->transferSize, 0, sizeof(handle->transferSize));
0921
0922 handle->queueUser = 0U;
0923 handle->queueDriver = 0U;
0924 }
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935 void SAI_TransferTerminateReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle)
0936 {
0937 assert(handle != NULL);
0938
0939
0940 SAI_TransferAbortReceiveEDMA(base, handle);
0941
0942
0943 (void)memset(handle->tcd, 0, sizeof(handle->tcd));
0944 (void)memset(handle->saiQueue, 0, sizeof(handle->saiQueue));
0945 (void)memset(handle->transferSize, 0, sizeof(handle->transferSize));
0946
0947 handle->queueUser = 0U;
0948 handle->queueDriver = 0U;
0949 }
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960 status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count)
0961 {
0962 assert(handle != NULL);
0963
0964 status_t status = kStatus_Success;
0965
0966 if (handle->state != (uint32_t)kSAI_Busy)
0967 {
0968 status = kStatus_NoTransferInProgress;
0969 }
0970 else
0971 {
0972 *count = (handle->transferSize[handle->queueDriver] -
0973 (uint32_t)handle->nbytes *
0974 EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
0975 }
0976
0977 return status;
0978 }
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989 status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count)
0990 {
0991 assert(handle != NULL);
0992
0993 status_t status = kStatus_Success;
0994
0995 if (handle->state != (uint32_t)kSAI_Busy)
0996 {
0997 status = kStatus_NoTransferInProgress;
0998 }
0999 else
1000 {
1001 *count = (handle->transferSize[handle->queueDriver] -
1002 (uint32_t)handle->nbytes *
1003 EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
1004 }
1005
1006 return status;
1007 }
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 uint32_t SAI_TransferGetValidTransferSlotsEDMA(I2S_Type *base, sai_edma_handle_t *handle)
1021 {
1022 uint32_t validSlot = 0U;
1023
1024 for (uint32_t i = 0U; i < (uint32_t)SAI_XFER_QUEUE_SIZE; i++)
1025 {
1026 if (handle->saiQueue[i].data == NULL)
1027 {
1028 validSlot++;
1029 }
1030 }
1031
1032 return validSlot;
1033 }