Quantcast

How to use async mode

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to use async mode

Uwe Bonnes
Hello,

with my FT2232H test setup, libftdi-1/libusb-1 with asyn mode enabled and
following code snipplet (after setting up everything):

      struct ftdi_transfer_control *tc;
      int size = (1<<(CHUNKEXP));
      unsigned char buf[size];
      int actual_length;
      int res;
      if(do_async)
        {
          tc  = ftdi_read_data_submit(&ftdic,
                                        buf,
                                        size);
          res = ftdi_transfer_data_done (tc);
       }
      else
        {
          res = ftdi_read_data(&ftdic, buf, size);
        }
        if (res>0)
        /*do something with the data */

I don't see any consistant difference between both modes. Reading tops out
at 22 MByte/sec if no further processing is done. Writing out the data gets
me down to 18 MByte/sec

Probably I use the async mode in some wrong way. Any usage hints welcome!

Meanwhile I found fastftdi.c from the dsi/ram-tracer project. Throughing out
everything project related I can reach 28 MB/sec, even writing the data. Is
the license
(http://svn.navi.cx/misc/trunk/nds/dsi/ram-tracer/host/fastftdi.c) open
enough that I can offer an adapted version for libftdi? Is there interest?

Bye
--
Uwe Bonnes                [hidden email]

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------

--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [hidden email]  

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use async mode

Jim Paris
Uwe Bonnes wrote:

> Hello,
>
> with my FT2232H test setup, libftdi-1/libusb-1 with asyn mode enabled and
> following code snipplet (after setting up everything):
>
>       struct ftdi_transfer_control *tc;
>       int size = (1<<(CHUNKEXP));
>       unsigned char buf[size];
>       int actual_length;
>       int res;
>       if(do_async)
>         {
>           tc  = ftdi_read_data_submit(&ftdic,
>                                         buf,
>                                         size);
>           res = ftdi_transfer_data_done (tc);
>        }
>       else
>         {
>           res = ftdi_read_data(&ftdic, buf, size);
>         }
>         if (res>0)
>         /*do something with the data */
>
> I don't see any consistant difference between both modes.

I don't think submitting an async request and immediately waiting for
it to finish will speed things up over ftdi_read_data.  The benefit is
that you can do other things while it's receiving.
(Can you submit more read requests while you wait?)

-jim

--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [hidden email]  

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use async mode

Jie Zhang
In reply to this post by Uwe Bonnes
Hi Uwe,

On 02/04/2010 12:48 AM, Uwe Bonnes wrote:

> Hello,
>
> with my FT2232H test setup, libftdi-1/libusb-1 with asyn mode enabled and
> following code snipplet (after setting up everything):
>
>        struct ftdi_transfer_control *tc;
>        int size = (1<<(CHUNKEXP));
>        unsigned char buf[size];
>        int actual_length;
>        int res;
>        if(do_async)
>          {
>            tc  = ftdi_read_data_submit(&ftdic,
>                                          buf,
>                                          size);
>            res = ftdi_transfer_data_done (tc);
>         }
>        else
>          {
>            res = ftdi_read_data(&ftdic, buf, size);
>          }
>          if (res>0)
>          /*do something with the data */
>
> I don't see any consistant difference between both modes. Reading tops out
> at 22 MByte/sec if no further processing is done. Writing out the data gets
> me down to 18 MByte/sec
>
> Probably I use the async mode in some wrong way. Any usage hints welcome!
>
ftdi_read_data = ftdi_read_data_submit + ftdi_transfer_data_done.

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

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


Jie

--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [hidden email]  

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use async mode

Uwe Bonnes
In reply to this post by Jim Paris
>>>>> "Jim" == Jim Paris <[hidden email]> writes:

    Jim> Uwe Bonnes wrote:
    >> Hello,
    >>
    >> with my FT2232H test setup, libftdi-1/libusb-1 with asyn mode enabled
    >> and following code snipplet (after setting up everything):
    >>
    >> struct ftdi_transfer_control *tc; int size = (1<<(CHUNKEXP));
    >> unsigned char buf[size]; int actual_length; int res; if(do_async) {
    >> tc = ftdi_read_data_submit(&ftdic, buf, size); res =
    >> ftdi_transfer_data_done (tc); } else { res = ftdi_read_data(&ftdic,
    >> buf, size); } if (res>0) /*do something with the data */
    >>
    >> I don't see any consistant difference between both modes.

    Jim> I don't think submitting an async request and immediately waiting
    Jim> for it to finish will speed things up over ftdi_read_data.  The
    Jim> benefit is that you can do other things while it's receiving.  (Can
    Jim> you submit more read requests while you wait?)

I have tried  with two structs ftdi_transfer_control *tc and two buffers and
when submitting one tc reading the other. But inside libftdi, both submits
initialize a transfer on the same readbuffer, so data got scrambled.

Bye
--
Uwe Bonnes                [hidden email]

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------

--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [hidden email]  

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use async mode

Uwe Bonnes
In reply to this post by Jie Zhang
>>>>> "Jie" == Jie Zhang <[hidden email]> writes:

    Jie> Hi Uwe, On 02/04/2010 12:48 AM, Uwe Bonnes wrote:
    >> Hello,
    >>
    >> with my FT2232H test setup, libftdi-1/libusb-1 with asyn mode enabled
    >> and following code snipplet (after setting up everything):
    >>
    >> struct ftdi_transfer_control *tc; int size = (1<<(CHUNKEXP));
    >> unsigned char buf[size]; int actual_length; int res; if(do_async) {
    >> tc = ftdi_read_data_submit(&ftdic, buf, size); res =
    >> ftdi_transfer_data_done (tc); } else { res = ftdi_read_data(&ftdic,
    >> buf, size); } if (res>0) /*do something with the data */
    >>
    >> I don't see any consistant difference between both modes. Reading
    >> tops out at 22 MByte/sec if no further processing is done. Writing
    >> out the data gets me down to 18 MByte/sec
    >>
    >> Probably I use the async mode in some wrong way. Any usage hints
    >> welcome!
    >>
    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?.

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

Bye
--
Uwe Bonnes                [hidden email]

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------

--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [hidden email]  

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to use async mode

Jie Zhang
On 02/04/2010 01:57 AM, Uwe Bonnes wrote:

>>>>>> "Jie" == Jie Zhang<[hidden email]>  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 [hidden email]  

urjtag-async-usb-read.diff (2K) Download Attachment
Loading...