in hw/mcu/nxp/src/ext/nxp-kinetis-sdk/drivers/fsl_i2c.c [1239:1459]
status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
{
assert(NULL != xfer);
i2c_direction_t direction = xfer->direction;
status_t result = kStatus_Success;
/* Clear all status before transfer. */
I2C_MasterClearStatusFlags(base, (uint32_t)kClearFlags);
#if I2C_RETRY_TIMES != 0U
uint32_t waitTimes = I2C_RETRY_TIMES;
/* Wait until the data register is ready for transmit. */
while ((0U == (base->S & (uint8_t)kI2C_TransferCompleteFlag)) && (0U != waitTimes))
{
waitTimes--;
}
if (0U == waitTimes)
{
return kStatus_I2C_Timeout;
}
#else
/* Wait until the data register is ready for transmit. */
while (0U == (base->S & (uint8_t)kI2C_TransferCompleteFlag))
{
}
#endif
/* Change to send write address when it's a read operation with command. */
if ((xfer->subaddressSize > 0U) && (xfer->direction == kI2C_Read))
{
direction = kI2C_Write;
}
/* Handle no start option, only support write with no start signal. */
if (0U != (xfer->flags & (uint32_t)kI2C_TransferNoStartFlag))
{
if (direction == kI2C_Read)
{
return kStatus_InvalidArgument;
}
}
/* If repeated start is requested, send repeated start. */
else if (0U != (xfer->flags & (uint32_t)kI2C_TransferRepeatedStartFlag))
{
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, direction);
}
else /* For normal transfer, send start. */
{
result = I2C_MasterStart(base, xfer->slaveAddress, direction);
}
if (0U == (xfer->flags & (uint32_t)kI2C_TransferNoStartFlag))
{
/* Return if error. */
if (kStatus_Success != result)
{
return result;
}
#if I2C_RETRY_TIMES != 0U
waitTimes = I2C_RETRY_TIMES;
/* Wait until data transfer complete. */
while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
{
waitTimes--;
}
if (0U == waitTimes)
{
return kStatus_I2C_Timeout;
}
#else
/* Wait until data transfer complete. */
while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
{
}
#endif
/* Check if there's transfer error. */
result = I2C_CheckAndClearError(base, base->S);
/* Return if error. */
if (kStatus_Success != result)
{
if (result == kStatus_I2C_Nak)
{
result = kStatus_I2C_Addr_Nak;
(void)I2C_MasterStop(base);
}
return result;
}
}
/* Send subaddress. */
if (0U != (xfer->subaddressSize))
{
do
{
/* Clear interrupt pending flag. */
base->S = (uint8_t)kI2C_IntPendingFlag;
xfer->subaddressSize--;
base->D = (uint8_t)((xfer->subaddress) >> (8U * xfer->subaddressSize));
#if I2C_RETRY_TIMES != 0U
waitTimes = I2C_RETRY_TIMES;
/* Wait until data transfer complete. */
while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
{
waitTimes--;
}
if (0U == waitTimes)
{
return kStatus_I2C_Timeout;
}
#else
/* Wait until data transfer complete. */
while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
{
}
#endif
/* Check if there's transfer error. */
result = I2C_CheckAndClearError(base, base->S);
if (0 != result)
{
if (result == kStatus_I2C_Nak)
{
(void)I2C_MasterStop(base);
}
return result;
}
} while (xfer->subaddressSize > 0u);
if (xfer->direction == kI2C_Read)
{
/* Clear pending flag. */
base->S = (uint8_t)kI2C_IntPendingFlag;
/* Send repeated start and slave address. */
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
/* Return if error. */
if (kStatus_Success != result)
{
return result;
}
#if I2C_RETRY_TIMES != 0U
waitTimes = I2C_RETRY_TIMES;
/* Wait until data transfer complete. */
while ((0U == (base->S & (uint8_t)kI2C_IntPendingFlag)) && (0U != waitTimes))
{
waitTimes--;
}
if (0U == waitTimes)
{
return kStatus_I2C_Timeout;
}
#else
/* Wait until data transfer complete. */
while (0U == (base->S & (uint8_t)kI2C_IntPendingFlag))
{
}
#endif
/* Check if there's transfer error. */
result = I2C_CheckAndClearError(base, base->S);
if (kStatus_Success != result)
{
if (result == kStatus_I2C_Nak)
{
result = kStatus_I2C_Addr_Nak;
(void)I2C_MasterStop(base);
}
return result;
}
}
}
/* Transmit data. */
if (xfer->direction == kI2C_Write)
{
if (xfer->dataSize > 0U)
{
uint8_t *tmpData = xfer->data;
size_t tmpDataSize = xfer->dataSize;
uint32_t tmpFlags = xfer->flags;
/* Send Data. */
result = I2C_MasterWriteBlocking(base, tmpData, tmpDataSize, tmpFlags);
}
else if (0U == (xfer->flags & (uint32_t)kI2C_TransferNoStopFlag))
{
/* Send stop. */
result = I2C_MasterStop(base);
}
else
{
/* Add this to fix MISRA C2012 rule15.7 issue: Empty else without comment. */
}
}
/* Receive Data. */
if ((xfer->dataSize > 0u) && (xfer->direction == kI2C_Read))
{
uint8_t *tmpData = xfer->data;
size_t tmpDataSize = xfer->dataSize;
uint32_t tmpFlags = xfer->flags;
result = I2C_MasterReadBlocking(base, tmpData, tmpDataSize, tmpFlags);
}
return result;
}