Hi, I need to communicate between LPC54606 (master) and PCIe switch PI7C9X2G1224GP (slave) via I2C. There's defined a specific sequence for read and write internal registers that I tried to do using I2C_MasterTransferBlocking API or I2C_MasterStart/I2C_MasterStop/I2C_MasterReadBlocking but I have a problem that I2C communication doesn't complete and end with error without data readed back. Write data are acked but when 5 bytes should be read back I see for some reason a write instead of read even I use direction=kI2C_Read, see code of my function below. When I experimented with params I found this behavior changes when I change flags on previous write from kI2C_TransferNoStopFlag to kI2C_TransferDefaultFlag. Then read is sent but slave doesn't return valid data, just five 0xFF bytes ending with arb.err. But according to slave protocol requirements I must not to use stop between so I need to make TransferNoStopFlag working.
Here's the sequence from slave datasheet:
Figure 7-4 SMBus Block Write to Set up Read, and Resulting Read that Returns CFG Register Value
START | Slave Addr Wr | ACK | Cmd Code = BAh | ACK | Byte Count = 4 | ACK | Cmd Byte1 | ACK | Cmd Byte 2 | ACK | Cmd Byte 3 | ACK | Cmd Byte 4 | ACK | STOP
A Block Write to set up Read
START | Slave Addr Wr | ACK | Cmd code = BDh | ACK | (no stop here) START | Slave Adress Rd | ACK | Byte Count = 4 (from slave) | ACK | Data Byte 1 (from slave) | ACK | Data Byte 2 (from slave) | ACK | Data Byte 3 (from slave) | ACK | Data Byte 4 (from slave) | ACK | STOP
My code:
i2c_master_transfer_t xfer; // I2C master transfer structure for I2C_MasterTransferNonBlocking()
uint8_t buffer[6]; // I2C data buffer for transfer (read/write)
status_t err;
if ((I2C_GetStatusFlags(base)&kI2C_MasterPendingFlag)==0) // if master is busy for some unknown reason
{ // restart the I2C master
I2C_MasterEnable(base,false); // otherwise it will hang in an endless loop
I2C_MasterEnable(base,true); // in SDK function I2C_PendingStatusWait()
}
buffer[0]=I2C_PCIESW_BLKWR; // fill command code to Tx buffer, see page 56
buffer[1]=4; // fill Byte count=4 to Tx buffer
buffer[2]=0x04; // fill Command Byte1 to Tx buffer, bit2:0 - 3=write reg, 4=read reg, bit7:3 - reserved
buffer[3]=0x00; // fill Command Byte2 to Tx buffer, bit3:0 - port_select4:1, bit7:4 - reserved
buffer[4]=0xBC; // fill Command Byte3 to Tx buffer, bit7 - port_select0, bit6 - reserved, bit5:2 - Byte enable (0=not modif, 1=modif), bit1:0 - reg_addr11:10
buffer[5]=0x3E; // fill Command Byte4 to Tx buffer, bit7:0 - reg_addr9:2 (reg_addr1:0 are always 0)
memset(&xfer, 0, sizeof(xfer));
xfer.slaveAddress=I2C_PCIESW_SLAVE_ADDR;
xfer.direction=kI2C_Write;
xfer.subaddress=0;
xfer.subaddressSize=0;
xfer.data=buffer;
xfer.dataSize=6;
xfer.flags=kI2C_TransferDefaultFlag;
err=I2C_MasterTransferBlocking(base, &xfer);
uart_printf("err1 %d\n", err);
buffer[0]=I2C_PCIESW_BLKR; // fill read back command code to Tx buffer
xfer.dataSize=1;
// xfer.flags=kI2C_TransferNoStopFlag;
xfer.flags=kI2C_TransferDefaultFlag;
err=I2C_MasterTransferBlocking(base, &xfer);
uart_printf("err2 %d\n", err);
memset(&buffer, 0, sizeof(buffer));
memset(&xfer, 0, sizeof(xfer));
xfer.slaveAddress=I2C_PCIESW_SLAVE_ADDR;
xfer.direction=kI2C_Read;
xfer.subaddress=0;
xfer.subaddressSize=0;
xfer.data=buffer;
xfer.dataSize=5;
xfer.flags=kI2C_TransferDefaultFlag;
err=I2C_MasterTransferBlocking(base, &xfer);
uart_printf("err3 %d\n", err);
Terminal log when flag used: kI2C_TransferNoStopFlag
err1 0
err2 0
err3 2609
00 00 00 00 00
Terminal log when flag used: kI2C_kI2C_TransferDefaultFlag
err1 0
err2 0
err3 2605
FF FF FF FF FF
In the attachment there are oscillograms with I2C analyser decoder that shows there's write address the last part of sequence while there should be read - why? Is it a bug in SDK API func?
The second osc shows sequence with right read but with unwanted stop that may cause read failed.
After all I found that problem was on slave side.
The PCIe switch implements 2 different protocols SMbus and I2C (over the same physical interface/pins). I was trying to send commands according to SMbus packet spec. When I tried to send packet according to I2C spec (it's simpler, eg. doesn't contain length Byte so packet is shorter) it works and all bytes are ACKed as expected. Both read reg and write reg works now.
But I cannot find anywhere in PI7C9X2G1224GP datasheet how is it determined what kind of protocol is used (how slave switches between them), they just describe 2 different protocols and let user try which works, huh, that was the catch...
Here I'm getting a nice read of VID/PID from reg 0:
Thanks for reply.
Is it really needed to reimplement own version of state machine instead of using standard SDK API functions? I'm absolutely OK with blocking mode so I want to keep it simple for now.
Do you have some explanation why the hell the last read command is changed to write? I already tried code with functions I2C_MasterWriteBlocking, I2C_MasterReadBlocking and I2C_MasterStart/I2C_MasterStop but with same result. I analyzed code of I2C_MasterStart that seems to be quite simple and I added a debug print of read back of MSTDAT register to see the value when starting with I2C address. And as expected when write i saw value 0x70 and when read I saw 0x71 but on the scope (analyzed also carefully bit by bit) I see the read turned to write. And this behavior depends on flag of previous call MasterWriteBlocking
if ((err=I2C_MasterWriteBlocking(base, &buffer, 1, kI2C_TransferDefaultFlag))!=kStatus_Success)
// if ((err=I2C_MasterWriteBlocking(base, &buffer, 1, kI2C_TransferNoStopFlag))!=kStatus_Success)
If I use TransferNoStopFlag then read become write, see osci attached.
Also please have a look at the end of SCK sequence (2nd osci) where you can see a low-level pulse that has extemely short width - less than regular SCK pulses - what does it mean?
Hi,
Frankly speaking, I am not clear about your question, how do you know that transfer function changes from read to write? As far as I know that only the address command has the LSB which presents the READ or WRITE command.
For the I2C protocol, the receiver must drive the data pin to LOW as ACK signal at the end of each byte, if the ACK is not received by transmitter if I2C is master writing phase, the master will stop by releasing the SCL/SDA, and both the SCL and SDA will be high, so the I2C will stop.
BR
XiangJun Rong
Yes, the read/write is detemined by LSB of I2S slave address. I called function I2C_MasterStart with parameter kI2C_Read:
I2C_MasterStart(base, I2C_PCIESW_SLAVE_ADDR, kI2C_Read)
but as you can see on oscillogram it was turned to write (LSB=0). I put inside of I2C_MasterStart a debug read back of MSTDAT and when called with kI2C_Read I correctly read 0x71 but on oscillogram I see that 0x70 was shifted out by master instead. This is what I wonder about. And this behavior depends on previous call of I2C_MasterWriteBlocking function and its flag parameter. When kI2C_TransferDefaultFlag is used then I2C_MasterStart(base, I2C_PCIESW_SLAVE_ADDR, kI2C_Read) works as expected (send 0x71) while if kI2C_TransferNoStopFlag is used then following I2C_MasterStart(base, I2C_PCIESW_SLAVE_ADDR, kI2C_Read) send 0x70.
Here's my alternative code that use MasterWrite/ReadBlocking and I2C_MasterStart
At last I wrote the transfer function at register level without using SK API, just register names from header and still getting the same result, I'm lost...
uint8_t buffer[6]; // data buffer for I2C transfer (read/write)
int i;
buffer[0]=I2C_PCIESW_BLKWR; // fill command code to Tx buffer, see page 56
buffer[1]=4; // fill Byte count=4 to Tx buffer
buffer[2]=0x04; // fill Command Byte1 to Tx buffer, bit2:0 - 3=write reg, 4=read reg, bit7:3 - reserved
buffer[3]=0x00; // fill Command Byte2 to Tx buffer, bit3:0 - port_select4:1, bit7:4 - reserved
buffer[4]=0xBC; // fill Command Byte3 to Tx buffer, bit7 - port_select0, bit6 - reserved, bit5:2 - Byte enable (0=not modif, 1=modif), bit1:0 - reg_addr11:10
buffer[5]=0x3E; // fill Command Byte4 to Tx buffer, bit7:0 - reg_addr9:2 (reg_addr1:0 are always 0)
// Master write 1 byte to slave. Address 0x23, Data 0xdd. Polling mode.
base->CFG = I2C_CFG_MSTEN_MASK;
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(0)) // I2C_STAT_MSTST_IDLE
return(-1);
base->MSTDAT = (I2C_PCIESW_SLAVE_ADDR << 1) | 0; // address and 0 for RWn bit
base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK; // send start
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(2)) // I2C_STAT_MSTST_TX
return(-2);
for (i=0; i<6; i++)
{
base->MSTDAT = buffer[i]; // send data
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK; // continue transaction
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(2)) // I2C_STAT_MSTST_TX
{
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK; // send stop
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(0)) // I2C_STAT_MSTST_IDLE
return(-5);
return(-3);
}
}
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK; // send stop
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(0)) // I2C_STAT_MSTST_IDLE
return(-4);
// part 2
base->MSTDAT = (I2C_PCIESW_SLAVE_ADDR << 1) | 0; // address and 0 for RWn bit
base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK; // send start
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(2)) // I2C_STAT_MSTST_TX
return(-6);
base->MSTDAT = I2C_PCIESW_BLKR; // send data
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK; // continue transaction
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(2)) // I2C_STAT_MSTST_TX
{
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK; // send stop
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(0)) // I2C_STAT_MSTST_IDLE
return(-8);
return(-7);
}
// part 3
base->MSTDAT = (I2C_PCIESW_SLAVE_ADDR << 1) | 1; // address and 1 for RWn bit
base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK; // send start
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(1)) // I2C_STAT_MSTST_RX
return(-9);
for (i=0; i<5; i++)
{
buffer[i] = base->MSTDAT; // read data
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK; // continue transaction
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(1)) // I2C_STAT_MSTST_RX
{
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK; // send stop
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(0)) // I2C_STAT_MSTST_IDLE
return(-11);
return(-10);
}
}
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK; // send stop
while(!(base->STAT & I2C_STAT_MSTPENDING_MASK));
if((base->STAT & I2C_STAT_MSTSTATE_MASK) != I2C_STAT_MSTSTATE(0)) // I2C_STAT_MSTST_IDLE
return(-12);
uint8_t buffer[6]; // data buffer for I2C transfer (read/write)
status_t err;
if ((I2C_GetStatusFlags(base)&kI2C_MasterPendingFlag)==0) // if master is busy for some unknown reason
{ // restart the I2C master
I2C_MasterEnable(base,false); // otherwise it will hang in an endless loop
I2C_MasterEnable(base,true); // in SDK function I2C_PendingStatusWait()
}
if ((err=I2C_MasterStart(base, I2C_PCIESW_SLAVE_ADDR, kI2C_Write))!=kStatus_Success) // initiate new master mode transfer by sending the START signal, write mode
return(-1000000-err); // if I2C fail to start due to timeout state reset should be done but API function I2C_MasterReset() does nothing
buffer[0]=I2C_PCIESW_BLKWR; // fill command code to Tx buffer, see page 56
buffer[1]=4; // fill Byte count=4 to Tx buffer
buffer[2]=0x04; // fill Command Byte1 to Tx buffer, bit2:0 - 3=write reg, 4=read reg, bit7:3 - reserved
buffer[3]=0x00; // fill Command Byte2 to Tx buffer, bit3:0 - port_select4:1, bit7:4 - reserved
buffer[4]=0xBC; // fill Command Byte3 to Tx buffer, bit7 - port_select0, bit6 - reserved, bit5:2 - Byte enable (0=not modif, 1=modif), bit1:0 - reg_addr11:10
buffer[5]=0x3E; // fill Command Byte4 to Tx buffer, bit7:0 - reg_addr9:2 (reg_addr1:0 are always 0)
if ((err=I2C_MasterWriteBlocking(base, &buffer, 6, kI2C_TransferDefaultFlag))!=kStatus_Success) // write block (6 Bytes), kI2C_TransferDefaultFlag = transfer starts with a start signal, stops with a stop signal
{
I2C_MasterStop(base); // if error occours, send STOP
return(-2000000-err); // and return immediatelly
}
if ((err=I2C_MasterStart(base, I2C_PCIESW_SLAVE_ADDR, kI2C_Write))!=kStatus_Success) // initiate new master mode transfer by sending the START signal, write mode
{
I2C_MasterStop(base); // if error occours, send STOP
return(-3000000-err); // and return immediatelly
}
buffer[0]=I2C_PCIESW_BLKR; // fill read back command code to Tx buffer
// if ((err=I2C_MasterWriteBlocking(base, &buffer, 1, kI2C_TransferDefaultFlag))!=kStatus_Success) // write block (1 Byte), kI2C_TransferDefaultFlag = transfer starts with a start signal, stops with a stop signal
if ((err=I2C_MasterWriteBlocking(base, &buffer, 1, kI2C_TransferNoStopFlag))!=kStatus_Success) // write block (1 Byte), kI2C_TransferDefaultFlag = transfer starts with a start signal, stops with a stop signal
{
I2C_MasterStop(base); // if error occours, send STOP
return(-4000000-err); // and return immediatelly
}
// here happens the address byte is transmitted with LSB=0 as write instead read as required i kI2C_TransferNoStopFlag is used before
if ((err=I2C_MasterStart(base, I2C_PCIESW_SLAVE_ADDR, kI2C_Read))!=kStatus_Success) // initiate new master mode transfer by sending the START signal, read mode
{
I2C_MasterStop(base); // if error occours, send STOP
return(-5000000-err); // and return immediatelly
}
if ((err=I2C_MasterReadBlocking(base, &buffer, 5, kI2C_TransferDefaultFlag))!=kStatus_Success) // read block (5 Bytes), kI2C_TransferDefaultFlag = transfer starts with a start signal, stops with a stop signal
{
// returns error kStatus_I2C_ArbitrationLost (2605)
I2C_MasterStop(I2C_BP); // if error occours, send STOP
return(-6000000-err); // and return immediatelly
}
*/
uart_printf("%02X %02X %02X %02X %02X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]);
return(0);
Hi, Martin,
I suggest you call the I2C state machine function to implement your I2C sequence such as:
I2C slave address + W + multiple data + repeated Start + I2C slave address +RD+ multiple data
I copy the api function, pls read them and consider how to call them based on your application:
Hope it can help you
BR
Xiangjun Rong
/*!
* @brief Prepares the transfer state machine and fills in the command buffer.
* @param handle Master nonblocking driver handle.
*/
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
{
struct _i2c_master_transfer *transfer;
handle->transfer = *xfer;
transfer = &(handle->transfer);
handle->transferCount = 0;
handle->remainingBytes = transfer->dataSize;
handle->buf = (uint8_t *)transfer->data;
handle->remainingSubaddr = 0;
if ((transfer->flags & (uint32_t)kI2C_TransferNoStartFlag) != 0U)
{
/* Start condition shall be ommited, switch directly to next phase */
if (transfer->dataSize == 0U)
{
handle->state = (uint8_t)kStopState;
}
else if (handle->transfer.direction == kI2C_Write)
{
handle->state = (uint8_t)kTransmitDataState;
}
else if (handle->transfer.direction == kI2C_Read)
{
handle->state = (uint8_t)kReceiveDataBeginState;
}
else
{
return kStatus_I2C_InvalidParameter;
}
}
else
{
if (transfer->subaddressSize != 0U)
{
int i;
uint32_t subaddress;
if (transfer->subaddressSize > sizeof(handle->subaddrBuf))
{
return kStatus_I2C_InvalidParameter;
}
/* Prepare subaddress transmit buffer, most significant byte is stored at the lowest address */
subaddress = xfer->subaddress;
for (i = (int)xfer->subaddressSize - 1; i >= 0; i--)
{
handle->subaddrBuf[i] = (uint8_t)subaddress & 0xffU;
subaddress >>= 8;
}
handle->remainingSubaddr = transfer->subaddressSize;
}
handle->state = (uint8_t)kStartState;
}
return kStatus_Success;
}
/*!
* @brief Execute states until FIFOs are exhausted.
* @param handle Master nonblocking driver handle.
* @param[out] isDone Set to true if the transfer has completed.
* @retval #kStatus_Success
* @retval #kStatus_I2C_ArbitrationLost
* @retval #kStatus_I2C_Nak
*/
static status_t I2C_RunTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, bool *isDone)
{
uint32_t status;
uint32_t master_state;
struct _i2c_master_transfer *transfer;
status_t err;
transfer = &(handle->transfer);
bool ignoreNak = ((handle->state == (uint8_t)kStopState) && (handle->remainingBytes == 0U)) ||
((handle->state == (uint8_t)kWaitForCompletionState) && (handle->remainingBytes == 0U));
*isDone = false;
status = I2C_GetStatusFlags(base);
if ((status & I2C_STAT_MSTARBLOSS_MASK) != 0U)
{
I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK);
return kStatus_I2C_ArbitrationLost;
}
if ((status & I2C_STAT_MSTSTSTPERR_MASK) != 0U)
{
I2C_MasterClearStatusFlags(base, I2C_STAT_MSTSTSTPERR_MASK);
return kStatus_I2C_StartStopError;
}
if ((status & I2C_STAT_MSTPENDING_MASK) == 0U)
{
return kStatus_I2C_Busy;
}
/* Get the state of the I2C module */
master_state = (status & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
if (((master_state == (uint32_t)I2C_STAT_MSTCODE_NACKADR) ||
(master_state == (uint32_t)I2C_STAT_MSTCODE_NACKDAT)) &&
(ignoreNak != true))
{
/* Slave NACKed last byte, issue stop and return error */
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
handle->state = (uint8_t)kWaitForCompletionState;
return kStatus_I2C_Nak;
}
err = kStatus_Success;
switch (handle->state)
{
case (uint8_t)kStartState:
if (handle->remainingSubaddr != 0U)
{
/* Subaddress takes precedence over the data transfer, direction is always "write" in this case */
base->MSTDAT = (uint32_t)transfer->slaveAddress << 1U;
handle->state = (uint8_t)kTransmitSubaddrState;
}
else if (transfer->direction == kI2C_Write)
{
base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
handle->state = (handle->remainingBytes != 0U) ? (uint8_t)kTransmitDataState : (uint8_t)kStopState;
}
else
{
base->MSTDAT = ((uint32_t)transfer->slaveAddress << 1) | 1u;
handle->state = (handle->remainingBytes != 0U) ? (uint8_t)kReceiveDataState : (uint8_t)kStopState;
}
/* Send start condition */
base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
break;
case (uint8_t)kTransmitSubaddrState:
if (master_state != (uint32_t)I2C_STAT_MSTCODE_TXREADY)
{
return kStatus_I2C_UnexpectedState;
}
/* Most significant subaddress byte comes first */
base->MSTDAT = handle->subaddrBuf[handle->transfer.subaddressSize - handle->remainingSubaddr];
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
if (--(handle->remainingSubaddr) != 0U)
{
/* There are still subaddress bytes to be transmitted */
break;
}
if (handle->remainingBytes != 0U)
{
/* There is data to be transferred, if there is write to read turnaround it is necessary to perform
* repeated start */
handle->state = (transfer->direction == kI2C_Read) ? (uint8_t)kStartState : (uint8_t)kTransmitDataState;
}
else
{
/* No more data, schedule stop condition */
handle->state = (uint8_t)kStopState;
}
break;
case (uint8_t)kTransmitDataState:
if (master_state != (uint32_t)I2C_STAT_MSTCODE_TXREADY)
{
return kStatus_I2C_UnexpectedState;
}
base->MSTDAT = *(handle->buf)++;
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
if (--handle->remainingBytes == 0U)
{
/* No more data, schedule stop condition */
handle->state = (uint8_t)kStopState;
}
handle->transferCount++;
break;
case (uint8_t)kReceiveDataBeginState:
if (master_state != (uint32_t)I2C_STAT_MSTCODE_RXREADY)
{
return kStatus_I2C_UnexpectedState;
}
(void)base->MSTDAT;
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
handle->state = (uint8_t)kReceiveDataState;
break;
case (uint8_t)kReceiveDataState:
if (master_state != (uint32_t)I2C_STAT_MSTCODE_RXREADY)
{
return kStatus_I2C_UnexpectedState;
}
*(handle->buf)++ = (uint8_t)base->MSTDAT;
if (--handle->remainingBytes != 0U)
{
base->MSTCTL = I2C_MSTCTL_MSTCONTINUE_MASK;
}
else
{
/* No more data expected, issue NACK and STOP right away */
if (0U == (transfer->flags & (uint32_t)kI2C_TransferNoStopFlag))
{
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
}
handle->state = (uint8_t)kWaitForCompletionState;
}
handle->transferCount++;
break;
case (uint8_t)kStopState:
if ((transfer->flags & (uint32_t)kI2C_TransferNoStopFlag) != 0U)
{
/* Stop condition is omitted, we are done */
*isDone = true;
handle->state = (uint8_t)kIdleState;
break;
}
/* Send stop condition */
base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
handle->state = (uint8_t)kWaitForCompletionState;
break;
case (uint8_t)kWaitForCompletionState:
*isDone = true;
handle->state = (uint8_t)kIdleState;
break;
case (uint8_t)kIdleState:
default:
/* State machine shall not be invoked again once it enters the idle state */
err = kStatus_I2C_UnexpectedState;
break;
}
return err;
}