FTDI Community

General Category => Discussion - Software => Topic started by: a4711 on September 27, 2022, 06:34:18 PM

Title: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: a4711 on September 27, 2022, 06:34:18 PM
I am observing an issue when calling FT4222_I2CMaster_GetStatus() after FT4222_I2CMaster_Write().

I am doing this:

Code: [Select]
FT4222_STATUS stat = FT4222_I2CMaster_Write(data_handle, slaveAddress_, data, size, &bytesWritten);
if (stat != FT4222_OK)
    throw std::runtime_error("Error writing data over FT4222");
uint8_t flags = 0;
do {
    for (uint32_t retries = 3; retries > 0; --retries) {
        stat = FT4222_I2CMaster_GetStatus(data_handle, &flags);
        if (stat == FT4222_OK)
            break;
        // Add an arbitrary wait time
        Sleep(100);
    }
    if (stat != FT4222_OK)
        throw std::runtime_error("Error reading status from FT4222");
    if (I2CM_DATA_NACK(flags) || I2CM_ADDRESS_NACK(flags))
        throw std::runtime_error("The peripheral did not acknowledge the message as expected");
} while (!I2CM_IDLE(flags));

I read the status after the write operation because FT4222_I2CMaster_Write() returns before the FT4222 has written all data. I need to verify that the transaction completed.

After about 90 minutes of heavy traffic I am sometimes observing that the SCL line is stuck low and flags reports 0x40 (bus busy) forever. I can confirm that the peripheral is not the problem. The SCL line remains low even when I disconnect the peripheral in that situation. It seems that the FT422 is the problem. In that case, the last message being sent is corrupted: The address is wrong and hence the peripheral device does not acknowledge the message.

Now I found this information in the errata sheet https://ftdichip.com/wp-content/uploads/2022/03/TN_161_FT4222H-Errata-Technical-Note.pdf (https://ftdichip.com/wp-content/uploads/2022/03/TN_161_FT4222H-Errata-Technical-Note.pdf):

Quote
Issue:
An error would happen when i2c master is writing data and FT4222_I2CMaster_GetStatus is being called
at the same time.

Workaround:
Call FT4222_I2CMaster_GetStatus after the end of i2c transmission.

The wording in the errata sheet is confusing. In above code snippet I call FT4222_I2CMaster_GetStatus() after FT4222_I2CMaster_Write(). But I also know that FT4222_I2CMaster_Write() may return while the transmission on the bus is ongoing which is not explicitly described in the application note.
Could you therefore please answer the following questions:


Thank you in advance.
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: FTDI Community on October 04, 2022, 10:25:42 AM
Hello,

Yes this errata may affect your operation.

FT4222_I2CMaster_Write is not a synchronous function. It stores the i2c command and data into the USB buffer.
There is a firmware bug and it happens on i2c data transaction and querying status at the same time.
Even these two actions are executed at the same time. The error rate is very low.
That is why you can run the test case for a long time but finally fails.

See the following code modifications.
You can see the bold section:

FT4222_STATUS stat = FT4222_I2CMaster_Write(data_handle, slaveAddress_, data, size, &bytesWritten);
if (stat != FT4222_OK)
    throw std::runtime_error("Error writing data over FT4222");
uint8_t flags = 0;
do {
    for (uint32_t retries = 3; retries > 0; --retries) {
        // Wait for the i2c transmission done, the waiting time depend on the i2c transaction time
        // for example:
        // 100Kbps to transfer 10 bytes , wait 8(bit) * 10us (1bit time)* 10 (bytes) = 800 us
        // 1Mbps to transfer 10 bytes , wait 8(bit) * 1us (1bit time)* 10 (bytes) = 80 us

        Sleep(1);

        stat = FT4222_I2CMaster_GetStatus(data_handle, &flags);
        if (stat == FT4222_OK)
            break;

    }
    if (stat != FT4222_OK)
        throw std::runtime_error("Error reading status from FT4222");
    if (I2CM_DATA_NACK(flags) || I2CM_ADDRESS_NACK(flags))
        throw std::runtime_error("The peripheral did not acknowledge the message as expected");
} while (!I2CM_IDLE(flags));

Best Regards,
FTDI Community
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: a4711 on October 10, 2022, 07:39:24 AM
Thank you for the reply. Please consider to update the wording in the errata sheet and mention the affected libFT4222 APIs explicitly.
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: allenhuffman on October 26, 2022, 07:07:26 PM
Thank you for the reply. Please consider to update the wording in the errata sheet and mention the affected libFT4222 APIs explicitly.

Having just ran in to this on our project, yes, please.
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: allenhuffman on October 27, 2022, 05:44:35 PM
Since there is a separate byte for the address, and since there are 9 pulses for each byte (ack/nak bit), a formula probably needs to take that in to consideration. Something like:

Code: [Select]
#define I2C_KHZ 400

ms = ((8+1) /*bits*/ * (1000/(I2C_KHZ)) /*us*/ * (bytesTransferred+1)) / 1000;

if (ms < 1) ms = 1;

Sleep (ms);

When looking at the FTDI Master (Windows 11) in a Salae capture, I also see gaps between each byte that range from 10us to 14us, so I added some worst-case extra bits (6 for my case) to that to cover it:

ms = ((8+1+6) ....etc...

I am not sure what the FTDI driver does that causes those gaps, but I expect the reason they vary in length is due to Windows not being a realtime OS.  Perhaps the gaps are even larger when using more CPU time or running more stuff.  That would throw all these calculations off.

There really should be a way to query the driver and find out if it's done writing.
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: FTDI Community on October 28, 2022, 04:15:37 PM
Hello,

This will be included in the LibFT422 release notes in future releases.

I will also check if anything can be done in the driver or library to help improve this.

Best Regards,
FTDI Community
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: allenhuffman on November 03, 2022, 01:47:35 PM
Hello,

This will be included in the LibFT422 release notes in future releases.

I will also check if anything can be done in the driver or library to help improve this.

Best Regards,
FTDI Community

Thank you. A simple blocking option (don't return until all bytes have been sent) would be great.
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: FTDI Community on November 04, 2022, 03:54:56 PM
Hello,

The feedback from our R&D team is that there is nothing that can be done with the library.

The issue is not related to the driver but the I2C IP.

Adding a delay is the only solution.

Best Regards,
FTDI Community
Title: Re: I2C data is corrupt when FT4222_I2CMaster_GetStatus is being called
Post by: allenhuffman on April 11, 2023, 09:26:35 PM
The feedback from our R&D team is that there is nothing that can be done with the library.

The issue is not related to the driver but the I2C IP.

Adding a delay is the only solution.

FYI to others who find this topic:  Calculating the delay is problematic when the output (under Windows, at least) has inconsistent gaps between each byte. In my testing today, I've seen some as small as 7 uS and as long as 63 uS. (See attachment.)  You really do end up Sleeping way too long to cover "worst case", and even then be sure to error check in case the data corruption does occur.