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