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