static status_t FLEXIO_I2C_MasterTransferRunStateMachine()

in hw/mcu/nxp/src/ext/nxp-kinetis-sdk/drivers/fsl_flexio_i2c_master.c [151:441]


static status_t FLEXIO_I2C_MasterTransferRunStateMachine(FLEXIO_I2C_Type *base,
                                                         flexio_i2c_master_handle_t *handle,
                                                         uint32_t statusFlags)
{
#if I2C_RETRY_TIMES
    uint32_t waitTimes = I2C_RETRY_TIMES;
#endif

    if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) != 0U)
    {
        /* Clear receive nak flag. */
        FLEXIO_ClearShifterErrorFlags(base->flexioBase, 1UL << base->shifterIndex[1]);

        if ((!((handle->state == (uint8_t)kFLEXIO_I2C_SendData) && (handle->transfer.dataSize == 0U))) &&
            (!(((handle->state == (uint8_t)kFLEXIO_I2C_ReceiveData) ||
                (handle->state == (uint8_t)kFLEXIO_I2C_ReceiveDataBegin)) &&
               (handle->transfer.dataSize == 1U))))
        {
            (void)FLEXIO_I2C_MasterReadByte(base);

            FLEXIO_I2C_MasterAbortStop(base);

            /* Delay one clk cycle to ensure the bus is idle. */
            SDK_DelayAtLeastUs(1000000UL / base->baudrate, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);

            handle->state = (uint8_t)kFLEXIO_I2C_Idle;

            return kStatus_FLEXIO_I2C_Nak;
        }
    }

    if (((statusFlags & (uint8_t)kFLEXIO_I2C_RxFullFlag) != 0U) && (handle->state != (uint8_t)kFLEXIO_I2C_ReceiveData))
    {
        (void)FLEXIO_I2C_MasterReadByte(base);
    }

    switch (handle->state)
    {
        /* Initial state, i2c start state. */
        case (uint8_t)kFLEXIO_I2C_Start:
            /* Send address byte first. */
            if (handle->needRestart)
            {
                FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Write);
            }
            else
            {
                FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, handle->transfer.direction);
            }
            if (handle->transfer.subaddressSize == 0U)
            {
                if (handle->transfer.direction == kFLEXIO_I2C_Write)
                {
                    /* Next state, send data. */
                    handle->state = (uint8_t)kFLEXIO_I2C_SendData;
                }
                else
                {
                    /* Next state, receive data begin. */
                    handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
                }
            }
            else
            {
                /* Next state, send command byte. */
                handle->state = (uint8_t)kFLEXIO_I2C_SendCommand;
            }
            break;

        /* Check address only needed for transfer with subaddress */
        case (uint8_t)kFLEXIO_I2C_SendCommand:
            if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
            {
                if (handle->transfer.subaddressSize > 0U)
                {
                    handle->transfer.subaddressSize--;
                    FLEXIO_I2C_MasterWriteByte(
                        base, ((handle->transfer.subaddress) >> (8U * handle->transfer.subaddressSize)));

                    if (handle->transfer.subaddressSize == 0U)
                    {
                        /* Load re-start in advance. */
                        if (handle->transfer.direction == kFLEXIO_I2C_Read)
                        {
#if I2C_RETRY_TIMES
                            while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) &
                                           (1UL << base->shifterIndex[0]))) &&
                                   (0U != --waitTimes))
                            {
                            }
                            if (0U == waitTimes)
                            {
                                return kStatus_FLEXIO_I2C_Timeout;
                            }
#else
                            while (0U ==
                                   (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
                            {
                            }
#endif
                            FLEXIO_I2C_MasterRepeatedStart(base);
                        }
                    }
                }
                else
                {
                    if (handle->transfer.direction == kFLEXIO_I2C_Write)
                    {
                        /* Send first byte of data. */
                        if (handle->transfer.dataSize > 0U)
                        {
                            /* Next state, send data. */
                            handle->state = (uint8_t)kFLEXIO_I2C_SendData;

                            FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);
                            handle->transfer.data++;
                            handle->transfer.dataSize--;
                        }
                        else
                        {
                            FLEXIO_I2C_MasterStop(base);

#if I2C_RETRY_TIMES
                            while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
                                   (0U != --waitTimes))
                            {
                            }
                            if (0U == waitTimes)
                            {
                                return kStatus_FLEXIO_I2C_Timeout;
                            }
#else
                            while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
                            {
                            }
#endif
                            (void)FLEXIO_I2C_MasterReadByte(base);

                            handle->state = (uint8_t)kFLEXIO_I2C_Idle;
                        }
                    }
                    else
                    {
                        (void)FLEXIO_I2C_MasterSetTransferCount(base, (uint16_t)(handle->transfer.dataSize + 1U));
                        FLEXIO_I2C_MasterStart(base, handle->transfer.slaveAddress, kFLEXIO_I2C_Read);

                        /* Next state, receive data begin. */
                        handle->state = (uint8_t)kFLEXIO_I2C_ReceiveDataBegin;
                    }
                }
            }
            break;

        /* Send command byte. */
        case (uint8_t)kFLEXIO_I2C_SendData:
            if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
            {
                /* Send one byte of data. */
                if (handle->transfer.dataSize > 0U)
                {
                    FLEXIO_I2C_MasterWriteByte(base, *handle->transfer.data);

                    handle->transfer.data++;
                    handle->transfer.dataSize--;
                }
                else
                {
                    FLEXIO_I2C_MasterStop(base);

#if I2C_RETRY_TIMES
                    while ((0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag)) &&
                           (0U != --waitTimes))
                    {
                    }
                    if (0U == waitTimes)
                    {
                        return kStatus_FLEXIO_I2C_Timeout;
                    }
#else
                    while (0U == (FLEXIO_I2C_MasterGetStatusFlags(base) & (uint32_t)kFLEXIO_I2C_RxFullFlag))
                    {
                    }
#endif
                    (void)FLEXIO_I2C_MasterReadByte(base);

                    handle->state = (uint8_t)kFLEXIO_I2C_Idle;
                }
            }
            break;

        case (uint8_t)kFLEXIO_I2C_ReceiveDataBegin:
            if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
            {
                handle->state = (uint8_t)kFLEXIO_I2C_ReceiveData;
                /* Send nak at the last receive byte. */
                if (handle->transfer.dataSize == 1U)
                {
                    FLEXIO_I2C_MasterEnableAck(base, false);
#if I2C_RETRY_TIMES
                    while ((0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
                           (0U != --waitTimes))
                    {
                    }
                    if (0U == waitTimes)
                    {
                        return kStatus_FLEXIO_I2C_Timeout;
                    }
#else
                    while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
                    {
                    }
#endif
                    FLEXIO_I2C_MasterStop(base);
                }
                else
                {
                    FLEXIO_I2C_MasterEnableAck(base, true);
                }
            }
            else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
            {
                /* Read one byte of data. */
                FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
            }
            else
            {
                ; /* Avoid MISRA 2012 rule 15.7 */
            }
            break;

        case (uint8_t)kFLEXIO_I2C_ReceiveData:
            if ((statusFlags & (uint32_t)kFLEXIO_I2C_RxFullFlag) != 0U)
            {
                *handle->transfer.data = FLEXIO_I2C_MasterReadByte(base);
                handle->transfer.data++;
                if (0U != handle->transfer.dataSize--)
                {
                    if (handle->transfer.dataSize == 0U)
                    {
                        FLEXIO_I2C_MasterDisableInterrupts(base, (uint32_t)kFLEXIO_I2C_RxFullInterruptEnable);
                        handle->state = (uint8_t)kFLEXIO_I2C_Idle;
                        /* Return nak if ReceiveNakFlag is not set */
                        if ((statusFlags & (uint32_t)kFLEXIO_I2C_ReceiveNakFlag) == 0U)
                        {
                            return kStatus_FLEXIO_I2C_Nak;
                        }
                    }

                    /* Send nak at the last receive byte. */
                    if (handle->transfer.dataSize == 1U)
                    {
                        FLEXIO_I2C_MasterEnableAck(base, false);
#if I2C_RETRY_TIMES
                        while (
                            (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0]))) &&
                            (0U != --waitTimes))
                        {
                        }
                        if (0U == waitTimes)
                        {
                            return kStatus_FLEXIO_I2C_Timeout;
                        }
#else
                        while (0U == (FLEXIO_GetShifterStatusFlags(base->flexioBase) & (1UL << base->shifterIndex[0])))
                        {
                        }
#endif
                        FLEXIO_I2C_MasterStop(base);
                    }
                }
            }
            else if ((statusFlags & (uint32_t)kFLEXIO_I2C_TxEmptyFlag) != 0U)
            {
                if (handle->transfer.dataSize > 1U)
                {
                    FLEXIO_I2C_MasterWriteByte(base, 0xFFFFFFFFU);
                }
            }
            else
            {
                ; /* Avoid MISRA 2012 rule 15.7 */
            }
            break;

        default:
            /* Add comment to avoid MISRA violation */
            break;
    }

    return kStatus_Success;
}