status_t DSPI_MasterTransferBlocking()

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;
}