libftdi Archives

Subject: Re: How to use async mode

From: Jie Zhang <jie.zhang@xxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Cc: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 7 Feb 2010 21:28:43 +0800
On 02/04/2010 01:57 AM, Uwe Bonnes wrote:
"Jie" == Jie Zhang<jie.zhang@xxxxxxxxxx>  writes:
     Jie>  ftdi_read_data = ftdi_read_data_submit + ftdi_transfer_data_done.

     Jie>  So actually the same code is executed whether do_async is true or
     Jie>  not.  Generally async mode is used to submit data transfer requests
     Jie>  without need to wait for their completion until you really need the
     Jie>  data read back.

     Jie>  I did those work about half a year ago and then switched to other
     Jie>  tasks.  So I need to refresh my memory before answer your
     Jie>  question. I will also try to review and test your patches for
     Jie>  libftdi-1 in this week I hope.

Probably we have different needs, a non-blocking read versus a streaming
read. A streaming read would imply that we can have outstanding
ftdi_read_data_submit() calls. But in the present implementation, as soon as
the remaining buffer can not fill up the size of the request, another
libusb_fill_bulk_transfer() is started with the same readbuffer as argument,
and now both pending libusb_fill_bulk_transfer()s write to the same buffer.

Is the urjtag problem of non-blocking transactions also solved with a
streaming approach as in fastftdi?.

I didn't know the answer for this question. But I can explain how the async mode helps UrJTAG.

Currently the usbconn_ftdi_flush code looks like below:

    ftdi_write_data ()
    if (there is anything to read)
        ftdi_read_data ()

ftdi_write_data () sends FT2232 commands to perform JTAG operations, which will generate data. The data is cached in a buffer in FT2232 chip and waits for host to send a read command to fetch it. The problem is the buffer in FT2232 is small (4 * 64 bytes). When it's full, you have to read it back. So in this sync mode, you can only send a small number of commands to read back a small number bytes.

With async mode, I change the usbconn_ftdi_flush to be

    if (there is any thing to read)
        ftdi_read_data_submit ()
    ftdi_write_data ()
    if (there is any thing to read)
        ftdi_transfer_data_done ()

Yes, with async mode we can submit a read transfer request before writing data! In this way the host can read back data as soon as they are generated by the written FT2232 commands and empty the buffer in FT2232 chip which used to cache the data. So writing FT2232 commands and reading back data occurs concurrently. The buffer will not be filled up quickly. That means, we can accumulate much more FT2232 commands until there are 63 * 64 bytes to read back. This will increase the USB bus usage largely.

A draft patch for UrJTAG to use async mode is attached. It's based on the latest UrJTAG svn trunk.

libftdi-1.0 can achieve the same performance on memory read for our gdbproxy as libftd2xx. My observation is that libftd2xx uses multiple threads to achieve this performance. It looks like one of those threads is always trying to read data in a loop, which has the same concurrent effect as async mode but pays much higher cost. It always occupies a high percentage of CPU even in idle. Async mode libftdi can be looked as an advantage compared with proprietary libftd2xx.

But then there is the other problem with compiling libusb-1 code for
windows. Or is the libusb-1 for windows effort already in some usefull
state? There was a lot mailing list activity recently...

Yes. I have already tried to build our gdbproxy + UrJTAG + libftdi-1.0 + libusb-winusb. It worked and passed several initial tests.


Jie


--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   

Attachment: urjtag-async-usb-read.diff
Description: Text Data

Current Thread