in hw/mcu/nxp/src/ext/nxp-kinetis-sdk/drivers/fsl_dspi.c [885:1150]
status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer)
{
assert(NULL != transfer);
uint16_t wordToSend = 0;
uint16_t wordReceived = 0;
uint8_t dummyData = DSPI_GetDummyDataInstance(base);
uint8_t bitsPerFrame;
uint32_t command;
uint32_t lastCommand;
uint8_t *txData;
uint8_t *rxData;
uint32_t remainingSendByteCount;
uint32_t remainingReceiveByteCount;
uint32_t fifoSize;
uint32_t tmpMCR = 0;
dspi_command_data_config_t commandStruct;
/* If the transfer count is zero, then return immediately.*/
if (transfer->dataSize == 0U)
{
return kStatus_InvalidArgument;
}
DSPI_StopTransfer(base);
DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable);
DSPI_FlushFifo(base, true, true);
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
/*Calculate the command and lastCommand*/
commandStruct.whichPcs =
(uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
commandStruct.isEndOfQueue = false;
commandStruct.clearTransferCount = false;
commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
command = DSPI_MasterGetFormattedCommand(&(commandStruct));
commandStruct.isEndOfQueue = true;
commandStruct.isPcsContinuous =
(0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
/*Calculate the bitsPerFrame*/
bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U);
txData = transfer->txData;
rxData = transfer->rxData;
remainingSendByteCount = transfer->dataSize;
remainingReceiveByteCount = transfer->dataSize;
tmpMCR = base->MCR;
if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK)))
{
fifoSize = 1U;
}
else
{
fifoSize = (uint32_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
}
DSPI_StartTransfer(base);
if (bitsPerFrame <= 8U)
{
while (remainingSendByteCount > 0U)
{
if (remainingSendByteCount == 1U)
{
while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
{
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
}
if (txData != NULL)
{
base->PUSHR = (*txData) | (lastCommand);
txData++;
}
else
{
base->PUSHR = (lastCommand) | (dummyData);
}
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
remainingSendByteCount--;
while (remainingReceiveByteCount > 0U)
{
if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
(DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
{
if (rxData != NULL)
{
/* Read data from POPR*/
*(rxData) = (uint8_t)DSPI_ReadData(base);
rxData++;
}
else
{
(void)DSPI_ReadData(base);
}
remainingReceiveByteCount--;
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
}
}
}
else
{
/*Wait until Tx Fifo is not full*/
while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
{
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
}
if (txData != NULL)
{
base->PUSHR = command | (uint16_t)(*txData);
txData++;
}
else
{
base->PUSHR = command | dummyData;
}
remainingSendByteCount--;
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize)
{
if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
(DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
{
if (rxData != NULL)
{
*(rxData) = (uint8_t)DSPI_ReadData(base);
rxData++;
}
else
{
(void)DSPI_ReadData(base);
}
remainingReceiveByteCount--;
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
}
}
}
}
}
else
{
while (remainingSendByteCount > 0U)
{
if (remainingSendByteCount <= 2U)
{
while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
{
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
}
if (txData != NULL)
{
wordToSend = *(txData);
++txData;
if (remainingSendByteCount > 1U)
{
wordToSend |= (uint16_t)(*(txData)) << 8U;
++txData;
}
}
else
{
wordToSend = dummyData;
}
base->PUSHR = lastCommand | wordToSend;
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
remainingSendByteCount = 0;
while (remainingReceiveByteCount > 0U)
{
if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
(DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
{
wordReceived = (uint16_t)DSPI_ReadData(base);
if (remainingReceiveByteCount != 1U)
{
if (rxData != NULL)
{
*(rxData) = (uint8_t)wordReceived;
++rxData;
*(rxData) = (uint8_t)(wordReceived >> 8U);
++rxData;
}
remainingReceiveByteCount -= 2U;
}
else
{
if (rxData != NULL)
{
*(rxData) = (uint8_t)wordReceived;
++rxData;
}
remainingReceiveByteCount--;
}
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
}
}
}
else
{
/*Wait until Tx Fifo is not full*/
while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
{
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
}
if (txData != NULL)
{
wordToSend = *(txData);
++txData;
wordToSend |= (uint16_t)(*(txData)) << 8U;
++txData;
}
else
{
wordToSend = dummyData;
}
base->PUSHR = command | wordToSend;
remainingSendByteCount -= 2U;
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize)
{
if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
(DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
{
wordReceived = (uint16_t)DSPI_ReadData(base);
if (rxData != NULL)
{
*rxData = (uint8_t)wordReceived;
++rxData;
*rxData = (uint8_t)(wordReceived >> 8U);
++rxData;
}
remainingReceiveByteCount -= 2U;
DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
}
}
}
}
}
return kStatus_Success;
}