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 - a4711

Pages: [1]
1
It is becoming more and more common to install a 64 Bit OS on a Raspberry. Libft4222 is available for ARMv8 32 Bit architecture, but not for 64 Bit (aarch64). When will you publish it or when will you publish the source code of LibFT4222 so that we can compile it on any architecture?

Thanks.

2
Thank you for the reply. Please consider to update the wording in the errata sheet and mention the affected libFT4222 APIs explicitly.

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

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:

  • Is above code affected by the problem described in the errata?
  • If yes, how do I determine the end of the i2c transmission so that I can immediately verify success/fail of the transaction? Feel free to take and change my code from above.

Thank you in advance.

4
Discussion - Software / How to properly use FT4222_ChipReset()?
« on: September 20, 2022, 07:19:13 PM »
After about 60-90 minutes heavy I2C traffic I run into the situation that the FT4222 holds the SCL line (yes the clock line, not SDA) low and FT4222_I2CMaster_GetStatus() keeps reporting 0x4e as status flags (error condition, bus busy, slave address not acknowledged, data not acknowledged). Further read/write transactions always fail. It's indeed the FT4222 that keeps pulling the SCL line low, because the SCL line remains low even when disconnecting the slave but keeping the pull-ups connected.

Though closing and reopening the FT_Handle does make it work again, the GPIO interrupt timing is not as expected. Only disconnecting/reconnecting the USB cable resets the original behavior.

As a workaround I would like to perform FT4222_ChipReset() right after opening the driver handle, but the function is not working as expected and it's also unclear what the function exactly does. I call FT4222_ChipReset() after FT_open() as shown in the application note. Calling FT4222_I2CMaster_Init() right after that returns FT4222_DEVICE_NOT_SUPPORTED.

I would like to have an advice how to properly use FT4222_ChipReset(), especially what to do after the function call. Is some delay needed? Do I need to close and re-open the driver instance? The example in the application note is not sufficient and indicates that I can just call this function after FT_Open() and before other things.

Thanks.

5
Discussion - Drivers / Relinkable object files for libft4222
« on: November 23, 2021, 10:15:08 PM »
Since libft4222 links to ftd2xx which links statically to libusb (L-GPL), I would like to link libft4222 to different version of libusb. I am kindly requesting access to relinkable object files for libft4222 similar to how you distribute ftd2xx.

Thanks.

6
Thank you for your suggestion. I confirm that the CPU load is now a bit lower, but it is still higher than I would expect.

Could you explain the consequence of setting the timeout to 0?

Thanks.

7
Quote
In the mean time, have you tried running the example as is? Just to see if the hardware is functioning properly?

My original code is much more complex. Therefore I thought I would strip it down and fit it into the "official" example.
 
Just copy-paste this function into the example file i2cm.c and run it on Linux and include <unistd.h>. On Windows you will have to replace usleep by Sleep. It works on my end. If you could run it on a Raspberry Pi you could see how high the CPU load is. But the gaps are visible on any platform I have checked.

8
Thank You for your reply.

Quote
Set the latency timer to a value appropriate for the application. Note that a low latency timer
value may result in many short incoming USB packets rather than a single large packet, thus
diminishing performance.

The latency timer is set to 16 ms (the default). Changing the value has only a very small effect on the gaps and and absolutely no effect on the CPU load on Linux.

Quote
you should also refer to section 5.3 of the FT4222 datasheet: https://ftdichip.com/wp-content/uploads/2020/07/DS_FT4222H.pdf
This section outlines the I2C bus interface.

I do not understand how this relates to the problem I am reporting here.

Quote
also which example are you referring to? the one shown in the LibFT4222 user guide or the one included in the library download?

From the library download. To illustrate my problem I modified the contained I2C example like this:

Code: [Select]
static int exercise4222(DWORD locationId)
{
    int                  success = 0;
    FT_STATUS            ftStatus;
    FT_HANDLE            ftHandle = (FT_HANDLE)NULL;
    FT4222_STATUS        ft4222Status;
    FT4222_Version       ft4222Version;
    const uint16         slaveAddr = 0x58;
    uint16               bytesToRead ;
    uint16               bytesRead = 0;
    uint16               bytesToWrite;
    uint16               bytesWritten = 0;
    char                *writeBuffer;
    uint8_t              pageBuffer[BYTES_PER_PAGE + 1];
    int                  page;


    ftStatus = FT_OpenEx((PVOID)(uintptr_t)locationId,
                         FT_OPEN_BY_LOCATION,
                         &ftHandle);
    if (ftStatus != FT_OK)
    {
        printf("FT_OpenEx failed (error %d)\n",
               (int)ftStatus);
        goto exit;
    }

    ft4222Status = FT4222_GetVersion(ftHandle,
                                     &ft4222Version);
    if (FT4222_OK != ft4222Status)
    {
        printf("FT4222_GetVersion failed (error %d)\n",
               (int)ft4222Status);
        goto exit;
    }

    printf("Chip version: %08X, LibFT4222 version: %08X\n",
           (unsigned int)ft4222Version.chipVersion,
           (unsigned int)ft4222Version.dllVersion);

    // Configure the FT4222 as an I2C Master
    ft4222Status = FT4222_I2CMaster_Init(ftHandle, 400);
    if (FT4222_OK != ft4222Status)
    {
        printf("FT4222_I2CMaster_Init failed (error %d)!\n",
               ft4222Status);
        goto exit;
    }

    // Reset the I2CM registers to a known state.
    ft4222Status = FT4222_I2CMaster_Reset(ftHandle);
    if (FT4222_OK != ft4222Status)
    {
        printf("FT4222_I2CMaster_Reset failed (error %d)!\n",
               ft4222Status);
        goto exit;
    }

    for (;;) {

        // Sequential read from slave EEPROM's current word address.
        uint8_t content[512];
        bytesToRead = sizeof(content);
        ft4222Status = FT4222_I2CMaster_Read(ftHandle,
                                             slaveAddr,
                                             content,
                                             bytesToRead,
                                             &bytesRead);
        if (FT4222_OK != ft4222Status)
        {
            printf("FT4222_I2CMaster_Read failed (error %d)\n",
                   (int)ft4222Status);
            goto exit;
        }

        if (bytesRead != bytesToRead)
        {
            printf("FT4222_I2CMaster_Read read %u of %u bytes.\n",
                   bytesRead,
                   bytesToRead);
            goto exit;
        }

        usleep(100000);
    }

    success = 1;

exit:
    if (ftHandle != (FT_HANDLE)NULL)
    {
        (void)FT4222_UnInitialize(ftHandle);
        (void)FT_Close(ftHandle);
    }

    return success;
}

It reads out 512 byte chunks in a loop with 100ms sleep in between transfers.

  • There are still gaps between 8µs and 17µs between each byte
  • The CPU load on a RPi3b is >50% which is unexpectedly high. On a RPi0 it is even higher due to the slower CPU.

I found the following note in the errata (3.1.2):
Quote
The FT4222H doesn’t support the latency timer feature and causes the USB scheduler to be busy and
uses too much CPU resource.

This looks exactly like what I am seeing, but I have chip revision D.

Can you reproduce this issue? How to solve it?

9
Discussion - Drivers / FT4222: Very high CPU load and gaps between bytes
« on: November 06, 2021, 06:41:40 AM »
We are using a FT4222 with libFT4222 1.4.4.44 to communicate to an I2C peripheral at 400 KHz. Our communication involves a mix of writes and reads, but mainly we are reading out chunks of 128-256 bytes. We are facing two problems:
  • The CPU load caused by libft4222 is extremely high. On a Raspberry Pi Zero this is becoming a bottleneck.
  • There a gaps between bytes on all platforms.

Here you can see the gaps:

As you can see, there is no gap between address byte and the first data byte, but every subsequent byte. On a modern x86 processor and Windows the gaps are at least 8µs long, on a Raspberry PI3 and Linux they are 17µs large. One byte takes about 23µs which means we are wasting 40% of our bandwidth. On a FT232H we don't see these kind of gaps and the CPU load is much better.

We are using the FT4222_I2CMaster_Read() function as shown in the example, nothing else.

  • How can we avoid having such gaps in the transfer?
  • How can we achieve a lower CPU load?

Pages: [1]