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

Show Posts

You can view here all posts made by this member. Note that you can only see posts made in areas to which you currently have access.

Messages - allenhuffman

Pages: [1] 2
1
Discussion - Software / Re: FT260 - Pauses in I2C comunication.
« on: August 26, 2021, 08:28:50 PM »
This may not help, but...

Using the FT4222, we noticed timing gaps between groups of data (I seem to recall odd spacing every 3 bytes).

Somewhere (support? random internet searching?) we were told to look at the SetClock speed and set it to SYS_CLK_24.

FT4222_SetClock (ftHandle, clock);

I do not know if this changed anything.

2
We make use of LibFT4222.dll for I2C Master communication on a Windows PC.

I would like to make our error detection much more robust. For example, I want to be able to detect issues such as:
  • USB cable disconnected.
  • I2C bus lock up.
  • ? ? ?
I get back an FT4222_STATUS from all read/write operations, but I am not real sure which errors are "best practice" to try to detect and handle.  I expect we can put in things like:

If we think I2C bus is locked, try an FT4222_I2CMaster_ResetBus().

If we think the USB connection is bad, un-init, close and try to re-open and init.

Library functions such as FT_CyclePort() may also be useful.

Could someone point me to some documention on "best practices" for a robust I2C system?

Thanks, much.

3
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.

4
During some early testing, I noticed that Write worked even if nothing was on the other side (no address ACK). Today, I am doing the write, and if it returns OK, I am checking controller status looking to see if the write was acknowledged.

But, I also saw the errata saying reading that register while a write was in progress could corrupt data.

5
Thanks. I am still trying to work through best practices. In this case, nothing could be done, but I often find the
c program gets stuck doing an FTDI library call. You can’t kill it with task manager, and have to reboot Windows, or unplug the USB cable. It releases when that is done.

How can I detect if a bus is stuck?

6
*** UPDATE ***

I switched over to GPIO mode and notice I can toggle the data line, but not clock.  At this point, I believe one of the devices on my bus is holding it low and this "unstick trick" will not work for me.

I have learned about FT4222_UnInitialize() which lets me open the device, initialize it for GPIO, unitialize it, the initialize it for I2C. I did not know about that, back then, or I would have tried this trick before the library had ResetBus.

My test code:

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
            Sleep (1);
            ft4222Status = FT4222_GPIO_Write(ftHandle, GPIO_PORT0, 0); // Clock pin
            Sleep (1);
         }
         Sleep (1);
         
         FT4222_UnInitialize(ftHandle);           
    }
    FT_Close (ftHandle);

7
FTDI added FT4222_I2CMaster_ResetBus() in the 1.4.4 release (I believe).  It is supposed to send 9 I2C clock pulses to unstick the I2C bus. I recall testing this when I first received this version, and saw it work.

But today, I am noticing it is not sending clock pulses.  Attached is a screen shot of the Saleae capture.

To verify my Saleae was working, I swapped my two input probes and saw the pulses move to the other input.

My code is very simple and is doing this:

Code: [Select]
    ftStatus = FT_OpenEx ("MyDeviceNameHere", FT_OPEN_BY_DESCRIPTION,
                          &ftdiInfoPtr->ftHandle);
   
    if (ftStatus == FT_OK)
    {
        ResetDevice ();
        // Need to wait for the FTDI device to complete the reset.
        Sleep (ONE_THOUSAND);

        // Set the device timeouts.
        ftStatus = FT_SetTimeouts (ftdiInfoPtr->ftHandle,
                                   FT_DEFAULT_RX_TIMEOUT,
                                   FT_DEFAULT_TX_TIMEOUT);

        // Initialize the I2C master.
        if (ftStatus == FT_OK)
        {
            // Initialize the FTDI device chosen.
            ft4222Status = I2CMasterInit (ftdiInfoPtr->ftHandle, I2C_SPECIAL_FAST_CLK);

            // Initialization is done.
            if (ft4222Status == FT4222_OK)
            {
                for (int idx=0; idx < 10; idx++)
                {
                    // Send nine clock pulses to reset a stuck Slave device.
                    ft4222Status = I2CMasterResetBus (ftdiInfoPtr->ftHandle);
                    Sleep (1);
                }

We have wrappers for the different functions, so I2CMasterResetBus is just:

Code: [Select]
FT4222_STATUS I2CMasterResetBus (FT_HANDLE ftHandle)
{
    return FT4222_I2CMaster_ResetBus (ftHandle);
}

And ResetDevice() is just calling FT_ResetDevice ();

Anyone used this? It's new, and wasn't even documented at first (beyond header file entries).

Thanks, much.

8
I do not think it was actually resolved in 1.4.3, but it definitely works in 1.4.4.

9
Discussion - Software / Re: FT4222 and PC as an I2C slave example?
« on: April 30, 2020, 04:35:47 PM »
This problem went away after two days of messing with it. Even using the default address of 0x40 was not working. Then it started. "SWT" (Strange Windows Thing?). An I have a fairly clean fresh install of Windows 10 from about a month ago, and I reboot my system every morning at the start of the day. Dunno!

10
I have a C# wrapper for the LibFT4222 and D2XX DLLs. The PC is acting as an I2C slave, and we have another project where the PC is the master.

I am trying to add recovery code to detect if the I2C connection is lost due to a USB cable unplug. Currently, we have close/reopen manually.

I have a loop that checks for data using FT4222_I2CSlave_GetRxStatus() and does a read if the expected bytes are available, then I do a FT4222_I2CSlave_Read().

I have noticed that the status returned from FT4222_I2CSlave_GetRxStatus continues to be FT4222_OK even if I unplug the USB cable.

I am trying to find a clue in these two manuals for how to detect a lost connection:

https://www.ftdichip.com/Support/Documents/ProgramGuides/D2XX_Programmer's_Guide(FT_000071).pdf
https://www.ftdichip.com/Support/Documents/AppNotes/AN_329_User_Guide_for_LibFT4222.pdf

My app also talks to a GPIB interface to a signal generator and have detection code for that working as expected. It returns an error when the device is turned off or unplugged.

Thanks for any pointers to what I need to be looking for in the manual.

11
I am using a C# wrapper for the FTDI I2C DLL. My program is acting as a Slave device. I have noticed that when the screen saver kicks in, I stop getting data.

The other DLL I am using (GPIB interface to a signal generator) keeps chugging along just fine. Only the I2C stops reading. The reads from the I2C is based on a Windows 10 timer. The control on the GPIB device is based on another timer. Since I can tell the GPIB timer is still working, I don't think it's a timer issue.

Has anyone else encountered this?

12
Discussion - Hardware / UMFT4222EV not sending/received I2C (Win 10)
« on: April 24, 2020, 12:41:27 AM »
I have two UMFT4222EV modules that used to work great, but now I can't get either to receive or send I2C using the same code that worked great a few months ago.

The only thing I can think that changed was a fresh reinstall of Windows since then.

My test app lists all the FTDI devices (FT4222 A and B, twice, since I tried plugging both in to make them talk). It can get clock speed and address and everything looks fine.

But nothing is coming out -- I've hooked it up to a logical analyzer and also a scope. Nothing on Clock/Data.

I've tried removing the driver and reinstalling. It's bound to be a "strange windows thing."

Anyone encountered this?



13
Looks like this is fixed in 1.4.3 (but we haven't tried it yet):

Release version
1.4.3 (Mar 19, 2020)
Maintenance release.

Release Fixes

•   Support Chip version “A”, “B”, “C” and “D”.
o   Fix issue. FT4222_I2CMaster_WriteEx does not return correct sizeTransferred.

14
Discussion - Software / FT4222 and PC as an I2C slave example?
« on: April 23, 2020, 05:46:21 PM »
We use FTDI I2C Master in a PC host program, but today I am trying to get a PC program to act as a slave so our embedded device can send some status information.

I am using a custom C# wrapper I wrote for the FT4222 I2C things. We use it successfully in an application running as a Master.

We are using the previous 1.4.2 release of the DLL package (I just noticed the 1.4.3 release today, which fixes a bug we'd encountered).

My code loop is very simple, but I get nothing back from it. I have used an analyzer and seen that there is I2C traffic with the correct address, but nothing makes it to my program. I expect I am missing something simple. My loop looks like this:

Code: [Select]
I2C i2c = new I2C(); // my wrapper

i2c.OpenByName("FT4222 A");

i2c.SlaveInit();
i2c.SlaveSetAddress((byte)0x40); // let's hard-code 40, which is the default.

Console.WriteLine("Slave address: 0x{0:x2} ({0})", i2c.SlaveGetAddress());

do
{
if (i2c.SlaveGetRxStatus() == 0) continue;

messageBuffer = i2c.SlaveRead(4);

for (int idx = 0; idx < 4; idx++)
{
Console.Write("{0:x2} ", messageBuffer[idx]);
}
Console.WriteLine();

} while (true);

GetRxStatus() always returns 0, but I do see my embedded device is writing out an I2C sequence to address 0x40 with four bytes after it. They are not being ACKed, so I don't think I have things set up properly for Slave.

Based on the examples in the PDF manual, and the i2c_slave.cpp sample code, it seems pretty straight forward.

Am I missing a step?

Thanks to whoever has the eyes to spot my mistake.

15
For our particular situation, the ChipReset seems to let us recover.

We have captured abnormalities in the I2C clock signal that starts happening before our hang. There will be an extra gap between the first clock pulse, and the repeats for the following bytes until it hangs. We've also been experimenting with different SetClock() values and see how the gaps change between bytes. We seem to have better luck at 24MHz.

Pages: [1] 2