FTDI Throughput Tweeking

Go To Last Post
32 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have finally got my hands on some embedded FTDI hardware (the 245 FIFO device attached to a microcontroller) and have it attached to my PC.

I have written a simple Windows application on the PC that transmits a 128 byte block of data to the embedded controller, using the FTD2xx DLL.

The embedded controller is sat in a tight loop interrogating the FTDI device, reading the 128 byte block, bitwise inverting it and sending it back to the PC.

The application records the PC time immediately (via Now()) before the transmission and the time as soon as it detects that it has 128 bytes in the receive buffer.

The check for data happens in a timer event, running every millisecond.

So finally I get around to a question...

This "round trip" of the data appears to take normally 10 milliseconds, and sometime 20 and I don't appear to be able to influence this time.

There is definitely SOMETHING that is happening with a 10 millisecond granularity.

I have tried playing with the latency timer - changing it between 1 and 255 milliseconds, but no effect at all.

Does this ring any bells with the folks that have had experience with these FTDI devices?

I can probably live with this throughput if that is what I get, but I could do with better if it is do-able.

Thanks in advance,
Andy

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you strobe SI low after stuffing the 128 bytes into the TX buffer?

I guess no, and I also guess that is where your delay is comming from!?

Bertolt

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, sorry - send immediate is being used.

      if (!LocalTransmitCount)
        {
        // The the frame transmission is complete!

        USBTransmitStateVariable = eUSBTxIdle ;

        *pTransmitComplete       = TRUE ;

        // That's all folks! Send it!

        USB_SendImmediate() ;

        return ;
        }

But thanks for the suggestion.

/A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndyG wrote:
This "round trip" of the data appears to take normally 10 milliseconds, and sometime 20 and I don't appear to be able to influence this time.

Andy, DateTime.Now only has a resolution of about 10 milliseconds under Windows NT 3.5 and later. Under Windows 98, it's only 55 milliseconds.

Don

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When you have a timer which has a resolution bigger than the time you want to measure, you have to run your test several times and then divide the total time by the number of times that you ran the test.

Embedded Dreams
One day, knowledge will replace money.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What baud rate? 115200? That should take right at about 11ms to send 128 chars..... and that would indees report 10ms 10ms 10ms 20ms 10ms 10ms 10ms 20ms or there about using 10ms resolution

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndyG wrote:
The embedded controller is sat in a tight loop interrogating the FTDI device, reading the 128 byte block, bitwise inverting it and sending it back to the PC.

Don't you read it bytewise and not bitwise?
I thought FTD245 had an 8 bit-parallel interface.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For better time resolution on Windows see QueryPerformanceCounter and QueryPerformanceFrequency.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The timer having a 10 ms resolution might have some effect, I suppose. :oops: According to a colleague of mine he is not even convinced that the timer event will fire at a frequency of any better than 10 ms either! Time for a stopwatch.

And I might not have meant "bitwise" - everything gets inverted anyway.

Thanks for the info re better timer accuracy.

I will have a play later in the day.

Thanks for all answers so far.

/A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My experience with QueryPerformanceCounter and QueryPerformanceFrequency is that it works very well! You will get down to µs resolution! :P

Here is a very good performance counter wrapper that you can use.

http://www.codeproject.com/datetime/perftimer.asp?msg=339606

matias

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What you can do in the situation you described is to have your PC-side timer fire at, say, 1 second. +/-10ms woud be 1%.

During that time period, count how many round-trips your echoed data makes, then divide to get your throughput.

Remember that there may be latency on your PC-side between receiving the echo and procesing it and initiating the next transaction.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think that we can safely say for the moment that the timing measurements I have been relying on at the PC are pure garbage.

Having experimented today my "1 millisecond" timer takes 15.75 seconds to fire 1000 times. Not what one might describe as "accurate".

This evening (when I get near the hardware again) I will use the suggested high accuracy timer and a few tight loops. That way the timing should start making sense again.

Thanks again, one and all.

/A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the point of the test is solely to measure throughput, why not just reverse the loop order. Start the transmission at the embedded controller and have the PC bounce it back to the controller. Your timing measurements should be extremely accurate using your controller's timers.

Vern

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

snafles wrote:
If the point of the test is solely to measure throughput, why not just reverse the loop order. Start the transmission at the embedded controller and have the PC bounce it back to the controller. Your timing measurements should be extremely accurate using your controller's timers.

Vern

That may indeed be a better approach. The varying latency on the PC-side still makes the test of the >>FTDI<< fairly meaningless--how are you measuring FTDI performance, even with accurate timers on the PC-side? I guess you could set up the test with an "ideal" client, and do relative comparisons using the same test conditions.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@snafles

I like the suggestion - as you rightly say that should allow more accurate timing. Though I would still have the problem of getting windows to "notice" the frame arrival and respond in something close to real time.

I would like to say that the reason that I have gone this way is that this mirrors the final system more closely. The PC will be master with responsibility for initiating dialogue and the micro responding to its polls.

If I were more honest, I would probably admit that I didn't realise what a can of worms I was opening with trying to get Windows events to work at this kind of frequency. :?

@Lee

I suppose that I am not trying to measure the FTDI performance as such, but rather tune the system so I can get data packets through quickly and get a feel for what I can expect.

I was disappointed with the performance, quite rightly as it transpires, and wanted to pick the collective brains here for a little orientation.

Cheers
A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndyG wrote:
Though I would still have the problem of getting windows to "notice" the frame arrival and respond in something close to real time.

:roll:
And I'm sure many here can attest that Windows is not real-time by any stretch of the imagination. Welcome to Microsoft (tm).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used an ftdi chip a couple years ago... just as an adapter... usb to rs232... I had an app that sent little packets of chars to the device... opcode, bytecount, couple of data bytes.... on the regular rs232 this workd fine at 115200.... on the converter dongle, I was only getting 9600 bps thruput... The fix was to put all 5 chars in the pkt in a buffer, and do 1 write file call with all 5 chars. What I had before was an auxout sub that did a writefile with 1 char.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Much better - now "round trip" times are now typically 3 milliseconds.

I suppose that's still not 3 megabits/second, but it's better than a poke in the eye with a sharp stick!

Thanks for all advice.

/A

p.s. Also, if anybody is using the Borland C++ FTD2xx example as a start point, the lib to go with the DLL is outdated and does not have some of the more esoteric functions.

I have generated a LIB for the the later DLL file which is compatible with C++ Builder if that is of any help to anyone.

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So 1280 bits (128 chars) in .003 sec is 420Kbits/sec. That seem right?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bob

I think the rate is actually higher than that, as there are actually 2 * 128 bytes getting transferred; one block after the other.

I therefore make it a 85 Kbyte/sec (roughly 700kbits) transfer rate.

What could be achieved in a single direction might be interesting, but this rate is OK for my needs.

Cheers
A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndyG wrote:

p.s. Also, if anybody is using the Borland C++ FTD2xx example as a start point, the lib to go with the DLL is outdated and does not have some of the more esoteric functions.

I have generated a LIB for the the later DLL file which is compatible with C++ Builder if that is of any help to anyone.

Or they(we) can use most recent DLLs with dynamic loading.

Anyway, FTDI people should make a Borland LIB too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FTDI do supply a Borland lib, but it is out of date. They may have another.

How do you do the dynamic loading thing in Borland, then? Does that mean one can use a latest DLL without the LIB file?

/A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndyG wrote:
FTDI do supply a Borland lib, but it is out of date. They may have another.

How do you do the dynamic loading thing in Borland, then? Does that mean one can use a latest DLL without the LIB file?

/A

Yes, this is the way I'm using it with borland c++ builder. Dynamic loading is done with windows API funcions and some pointer manipulation.

This can be put in the header file (private section of the form)


FT_HANDLE ftHandle;
FT_STATUS ftStatus;
HINSTANCE ftDLLHandle;

// define own type
typedef FT_STATUS (WINAPI *pFT_Open)(int deviceNumber, FT_HANDLE *pHandle);
typedef FT_STATUS (WINAPI *pFT_Write)(FT_HANDLE ftHandle,LPVOID lpBuffer,
                                            DWORD nBufferSize, LPDWORD lpBytesWritten);

// declare own pointers to funcitions -> name it as you like
pFT_Open FT_Open;
pFT_Write FT_Write;

and folowing is used later in code. This is a needed for every used FTDI function!
You can use this only once in the forms constructor.

ftDLLHandle = LoadLibrary("ftd2xx.dll");
if (ftDLLHandle == NULL))
        ShowMessage(SysErrorMessage(GetLastError()));
else  
{
    FT_Open = (pFT_OpenEx)GetProcAddress(ftDLLHandle, "FT_Open");
    FT_Write = (pFT_Write)GetProcAddress(ftDLLHandle, "FT_Write");
}

Point is that you have to "find" function in the DLL. This is done with GetProcAddress which finds function's address by name (between " "). You can check GetProcAddress return. If NULL something is wrong.

now use the FTDI funcitons as needed (just some simple example lines) and just like using LIB:


ftStatus = FT_Purge(ftDLLHandle, FT_PURGE_RX | FT_PURGE_TX);
ftStatus = FT_Write(ftHandle, &tx_buffer, 1, &BytesWritten);

Don't forget to close FTDI device and DLL with

FreeLibrary(ftDLLHandle);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks slawc.

Potentially very useful.

/Andy

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just noticed mistake in FT_Purge: it should be ftHandle instead of ftDLLHandle.

Anyway don't forget to check returns. :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just one more question.... is this usb 1 or 2? (100megabits or 400 megabits). If you are getting .7 megabits and it should really be 100 times faster, may I ask if you are running it on a P166 or something?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bobgardner wrote:
Just one more question.... is this usb 1 or 2? (100megabits or 400 megabits). If you are getting .7 megabits and it should really be 100 times faster, may I ask if you are running it on a P166 or something?

I don't know where you got the speed grades 100 Mbps and 400 Mbps, but it's not from USB. I think you are mixing it with FireWire/IEEE1394/i.Link.

FireWire has three differnt speed grades:
IEEE1394: 100 Mbps
IEEE1394a: 400 Mbps
IEE1394b: 800 Mbps

http://en.wikipedia.org/wiki/IEE...

Quote:
FireWire 400 can transfer data between devices at 100, 200, or 400 Mbit/s data rates (actually 98.304, 196.608, or 393.216 Mbit/s, but commonly referred to as S100, S200, and S400).

IEEE1394a (400 Mbps) FireWire is actually faster than 480 Mbps USB2.0 High Speed because it's a more intellgent standard with less extra data sent, but that's another story.
So if you have an external combined USB2.0/IEEE1394a HDD, then it would always be faster in transfer speed tests if you use 400 Mbps IEEE1394a than if you use 480 Mbps USB2.0 High Speed.

USB 2.0 High Speed vs. FireWire: http://www.barefeats.com/usb2.html

USB has three speed grades:
Low Speed: 1.5 Mbps
Fulll Speed: 12 Mbps
High Speed: 480 Mbps

If a device supports USB2.0 it actually don't telll you anything about if it can run High Speed (480 Mbps). Some USB2.0 devices can only run 12 Mbps for example. Many PC manufactures (and many others) uses the therm USB2.0 wrong, because it don't tell anything about the speed. They write USB2.0 when they actually mean USB High Speed. USB2.0 is a standard than can support High Spee. But devices can be for example be 12 Mbps devices and still be USB2.0 compatible devices, USB2.0 is just a standard, not a speed grade.

USB1.1 devices can however never be 480 Mbps devices and that's why many often use the therm USB1.1 vs. USB2.0 to describe the speed even though this is a misunderstading as it doesn't tell anything about the speed.
So be carefull if you buy an USB2.0 compatible IC and expect it to be 480 Mbps, becasue you might be surprise to find out that's it's either 1.5 Mbps or 12 Mbps even though the sticker says USB2.0 compatible.
What you should look for is if it's Low, Full or High Speed USB.
Be aware that High Speed is faster than Full Speed; this seems unlogical, but the name Full Speed was made long before 480 Mbps High Speed was supported. So they just decided to keep the name Full Speed even though it is misleading now.

But wheter the FT245 IC supports Full Speed or High Speed is not that important,. What matters is the speed on the other side of the IC (the 8-bit interface between FT245 and your AVR).
This is what it says in the FT245 datasheet:

Quote:
HARDWARE FEATURES
• Single Chip USB <-> Parallel FIFO bi-directional Data Transfer
• Transfer Data rate to 1M Byte / Sec - D2XX Drivers
• Transfer Data rate to 300 Kilobyte / Sec - VCP Drivers

As you can see, the maximum speed is 1M Byte/sec, this will result in 8 Mbps at the UBS side + some extra USB protcol data sent between the PC and your FT245. This is acheived if you use the D2XX Drivers. If you use VCP Drivers, then you can only acheive a speed of 300 Kilobyte / Sec.

From these data you can tell tha it is not a Low Speed (1.5 Mbps) USB device; because this is much slower than 8 Mbps.
So it could eiter be Full Speed (12 Mbps) or High Speed (480 Mbps), but it doesn't really matter as bot 12Mbps and 480 Mbps are fast enough.

I know for a fact that it is a Full Speed (12 Mbps) device, that can be set up as either an USB1.1 or USB2.0 (but still only 12 Mbps) device.
From the FT245 datasheet:

Quote:
USB 2.0 ( full speed option )
A new EEPROM based option allows the FT245BM to return a USB 2.0 device descriptor as opposed to USB 1.1. Note : The device would be a USB 2.0 Full Speed device (12Mb/s) as opposed to a USB 2.0 High Speed device (480Mb/s).

Quote:
USB Transceiver
The USB Transceiver Cell provides the USB 1.1 / USB 2.0 full-speed physical interface to the USB cable. The output drivers provide 3.3 volt level slew rate control signalling, whilst a differential receiver and two single ended receivers provide USB data in, SEO and USB Reset condition detection.

http://en.wikipedia.org/wiki/Usb

Quote:
USB standards

USB 1.0 came out in 1995, the same year that Apple adopted the IEEE 1394 standard known as Firewire. It supports two data rates of 1.5 Mbit/s for keyboards, mice, joysticks and the like, and a full speed mode at 12 Mbit/s, which is about 1.5 Mbyte/s.

USB 1.1 came out later in 1995. This standard added interrupt OUT transfers. See [2] (http://www.mindshare.com/pdf/usb...) for details.

USB 2.0 came out in 2002. The major feature of this standard is the addition of a high-speed rate of 480 Mbit/s, which is about 57 Mbyte/s. It also clarifies minor technical errata. At its highest speed USB competes directly with FireWire, except in the area of digital camcorders, where USB has technological limitations that prevent it from being viable.

Confusingly, the USB Forum has renamed USB 1.1 to USB 2.0 Full Speed; and USB 2.0 to USB 2.0 High Speed

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@bob

I don't know the details offhand about the USB frequencies, but I think I remember FTDI claiming 3 megabits/second transmission rate.

[edit] Ooops - sorry - just read AndersAnd's post - 1 megabyte/sec is quite a lot lower than my throughput.[/edit]

I'm happy with the throughput I am getting though, so I've stopped worrying.

If anybody else wants the test code I'm using, I'd be happy to post it for them to "run with it" and see where the time loss is.

Cheers
/A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndyG wrote:
[edit] Ooops - sorry - just read AndersAnd's post - 1 megabyte/sec is quite a lot lower than my throughput.[/edit]

Do you have a higher throughput than 1 MByte/sec?
What is your transfer speed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, it was early in the morning when I wrote that. :)

I meant to write "1 megabyte per second is much higher than I'm getting."

I make it 128 bytes in either direction (one block after the other) in nominally 3 milliseconds.

85 kilobytes per second - roughly 700 kilobits.

Cheers
/A

If we are not supposed to eat animals, why are they made out of meat?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, that makes more sense.

But you read a whole byte at a time and not just a bit right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh yeah - an 8 bit parallel transaction.

/A

If we are not supposed to eat animals, why are they made out of meat?