Electronic – FT232HL FTDI consecutive SPI bytes delay problem

ftdilatencyserialspiusb

I have a problem with the FT232HL FTDI ic.

Windows application send data to the chip via USB and the chip send the data out with one SPI channel.

I did check with a logic analyser, the bytes are correctly sent out and the SPI clock match the settings. However, between each byte, there is a 64uS delay so it means that no matter how high is the SPI clock, the data transfer takes minutes instead of seconds.

I imagined maybe playing with the channelConf.LatencyTimer would help, but it shows no difference no matter the value used (10, 128, 255), delay remain 64uS between consecutive bytes.

There must be something to fix because there are numerous examples of people reaching high transfer rates. Also, delay between bytes should be a setting somewhere.

I've used sample code provided with sample-dynamic.c
The byte stream is sent with a single call to p_SPI_Write() with total length of 2048 bytes. I've tried other length (256, 8192, etc) no change.
Here is the configuration used:

channelConf.ClockRate = 5000*1000; 
channelConf.LatencyTimer= 10; 
channelConf.configOptions = SPI_CONFIG_OPTION_MODE0| SPI_CONFIG_OPTION_CS_DBUS3/*|*/ ;
channelConf.Pin = 0x00000000; /* FinalVal-FinalDir-InitVal-InitDir (for dir: 0=in, 1=out) */

OS: windows7 X64
Compiler: GCC
Library and code from: http://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm

FYI: I've contacted FTDI support, they asked me to update the libraries to latest one (which I did), then they would not provide further support.

Any help appreciated.
Thank you.

Best Answer

I usually work with the FT2232H chip, but I dug out an FT232HQ chip out just so I could check out this issue you were having. It's the same chip as the FT232HL chip you have, just in a QFN package instead of a QFP.

I tried to recreate the problem you describe, but I wasn't able to exactly. This is what it looked like on my logic analyzer when I output 6 bytes at once at a clock rate of 5MHz. There is is a small delay between bytes, but nowhere near as large as 64us.

Example 5MHz Multibyte Transmission

Here are some things to check.

  • Latency timer really shouldn't matter because that is simply a timeout before USB will send an incomplete packet. I have it set to 255, but often for timing sensitive stuff, I have it lower (2 -10)
  • Try a slower clockrate first just to test and make sure the device is communicating correctly (I assume you did, I'm just adding this in case someone else hasn't tried that yet).
  • The pin directions don't matter except for GPIO since they get overwritten by the SPI lib.
  • Instead of p_SPI_Write(), use SPI_Write(). If you make a single call, add the appropriate chip select enable and disable flags (see below). If you make multiple calls, make sure to add the chip select flags to the first and last calls in the series.
  • Make sure you pass the number of bytes to transmit, and set the SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES flag.
  • If this is a custom board design, or you bought a discount FT232H adapter board, make sure it has the correct system clock frequency. That delay between bytes is based on how long it takes the chip to move the next byte from its internal buffer to the output shift registers. If the chip is clocked slowly, then this will show at the higher frequencies as a larger gap between bytes. Note that for SPI it doesn't matter if the clock is stretched a little bit here and there since it is based on the edges of the clock signal (read on one edge, propagate on the other). Probe the crystal or CMOS crystal chip and make sure it is getting 12MHz.

Here is some quick example code on how to send multiple data bytes in case it helps.

uint32 sizeToTransfer = 0;
uint32 sizeTransfered = -1;
uint8 buffer[256]; //Must be large enough for what you are sending.
FT_STATUS status;

//add data
buffer[sizeToTransfer++] = 0x20; //First data byte (can be what you need)
/*
 * More bytes added....
 */
buffer[sizeToTransfer++] = 0x00; //Last data byte (can be what you need)

status = SPI_Write(*handle, buffer, sizeToTransfer, &sizeTransfered,
    SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES |
    SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE |
    SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);

//Don't forget to check status. It should equal FT_OK if everything went well