FTDI Community

Please login or register.

Login with username, password and session length.
Advanced Search  

News:

Welcome to the FTDI Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ FTDI Support


New Bridgetek Community is now open

Please note that we have created the Bridgetek Community to discuss all Bridgetek products e.g. EVE, MCU.

Please follow this link and create a new user account to get started.

Bridgetek Community

Author Topic: FT4222 I2C and detecting a stuck I2C bus (clock stretching), I2C bus reset  (Read 8217 times)

allenhuffman

  • Newbie
  • *
  • Posts: 48
  • Mostly harmless.
    • View Profile
    • Sub-Etha Software

We use Windows and the FT4222 driver to talk to a variety of boards over I2C. Over the years, we have seen many issues with I2C bus locks and have tried to mitigate them in software/firmware.

I thought I'd ask here if folks had any elegant solutions for detecting an I2C bus lock and attempting recovery.

The last release of the library (1.4.4) added FT4222_I2CMaster_ResetBus(); and finally allowed sending the 9 clock pulses to try to unstick a stuck I2C slave device. Before this function was added, we tried doing it manually but found you could not access the GPIO pins when in I2C mode.

I believe we may have been able to just uninitialized from I2C and initialize in GPIO mode to do this:

Code: [Select]
FT_HANDLE ftHandle = NULL;

ftStatus = FT_OpenEx ("PrecisePower B", FT_OPEN_BY_DESCRIPTION,
                      &ftHandle);

if (ftStatus == FT_OK)
{
     GPIO_Dir gpioDir[4] = { GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT, GPIO_OUTPUT };
     
     ft4222Status = FT4222_GPIO_Init(ftHandle, gpioDir);

     //disable suspend out , enable gpio 2
     ft4222Status = FT4222_SetSuspendOut(ftdiInfoPtr->ftHandle, false);
     
     //disable interrupt , enable gpio 3
     ft4222Status = FT4222_SetWakeUpInterrupt(ftdiInfoPtr->ftHandle, false);
     
     // set gpio0/gpio1/gpio2/gpio3 output level high
     for (int pulse=0; pulse<9; pulse++)
     {
        ft4222Status = FT4222_GPIO_Write(ftHandle, GPIO_PORT0, 1); // Clock pin
        ft4222Status = FT4222_GPIO_Write(ftHandle, GPIO_PORT0, 0); // Clock pin
     }
     Sleep (1);
     
     FT4222_UnInitialize(ftHandle);

    // Re-init as I2C and use it...           
}
FT_Close (ftHandle);

(Untested; not sure the timing from within Windows toggling that pin on/off would do the trick.)

I wondered if anyone had any clever ways of detecting an I2C stuck bus condition (like when a slave device is using clock stretching, and the master doesn't do a read).

I'll do another post about our experiments with ACK/NACK.

Cheers.
Logged