• AVR Freaks

How to get maximum USB throughput

Author
Deenayd
Super Member
  • Total Posts : 905
  • Reward points : 0
  • Joined: 2004/09/08 06:15:13
  • Location: Poland
  • Status: offline
2009/06/20 05:18:35 (permalink)
0

How to get maximum USB throughput

How to get maximum USB throughput using PIC32 as USB device?

I need to send data from PIC32 to PC as fast as possible - at least about 1 megabyte per second.
Have anybody tried that?
How should I configure USB in PIC32?
Can I use one of predefined USB device classes?
I used to use RS emulation (CDC), but it's definitelly too slow for this application (up to 64kB per second if I'm not mistaken).

Slawek Piotrowski
Rejestracja Czasu Pracy Ewidencja Czasu Pracy
#1

18 Replies Related Threads

    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/20 17:01:48 (permalink)
    0
    1024KB/sec here with PIC32 under certain conditions.
    http://www.microchip.com/forums/tm.aspx?m=417509

    The theoretical maximum for full speed bulk transfer is 1216Bytes/ms (1216KB/s). But I've not seen any implementation which reaches that theoretical maximum.

    What is your application? The speed of bulk transfer is not guaranteed. If you want guaranteed maximum speed, you may have to use isochronous transfer (theoretical maximum 1023 Bytes/ms and this is reachable).



      USB_Links and libusb
    #2
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/21 01:25:11 (permalink)
    0
    Thanks. I will look into that. I don't need constant datarate. I just have about 4GB to send and this shouldn't take much more than 1 hour.

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #3
    Kiwi Mike AZ
    Super Member
    • Total Posts : 2044
    • Reward points : 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/21 20:44:23 (permalink)
    0
    Recommend using Bulk transfer then as Isochronous does not guarantee integrity, but bulk does.

    Mike
    #4
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/22 10:24:39 (permalink)
    0
    I have made a set of tests (bulk transfer) and I'm only able to get about 630kB/s (PIC to PC) datarate. Are there any special tricks I need to implement to get closer to 1MB/s?

    I am basing my firmware on Libusb demo from Microchip stack. I have added a new "function" in the firmware (case 0x40) that sends a set of (16384) packets - 64 bytes each. Host reads those and measures times using Windows' PerformanceCounter.

    The strange thing I have found is that speed is different if I plug the device into another USB port (in fact using a hub looks faster... really strange). Another thing is that compiling the code with optimisation on returns 630kB/s while using optimisised compilation I only get 520kB/s. So... I'm not sure where is the bottleneck (bus or PIC)

    My ideas to optimise:
    1) learn about PIC32 usb module - will it allow in/out buffers larger than one block? (per endpoint)
    2) use two endpoints per transfer - this way I will be able to setup one packet while previous one was being send
    3) move sending loop into USB ISR so I will get rid if "while" waiting loop in main code (main code will need to manage incoming transfer using PMP - already fully working with DMA)
    4) try other computer that doesn't have any USB devices attached

    Any hints welcome
    post edited by Deenayd - 2009/06/22 10:26:17

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #5
    Kiwi Mike AZ
    Super Member
    • Total Posts : 2044
    • Reward points : 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/22 12:30:32 (permalink)
    0

    Mostly on the PC side.

    In the host stack just keep feeding the data as fast as you can, i.e. do not use a timer and try every ms, but just check the appropiate USB Flag and then load and send new data.

    I used LibUSB and had to do a read request for 1,000,000 bytes.
    Otherwise I was only getting around 400 to 500Kbyte/sec
    The PC cannot keep up and will miss every second ms read.

    Also make sure it is the ONLY thing plugged onto the USB HOST CONTROLLER you are using..... beware many PC's and Laptops have a HUB internally that connect to either multiple external ports or some internal devices (e.g. keyboard, mouse, CD drive etc).

    Use an application like UVCView to check this.

    Mike
    #6
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/23 00:48:48 (permalink)
    0
    My test PC program was looping to read in 256kB chunks. That was guided by my final application's requirements (it will request data in such sized chunks). I have changed it to 1MB for testing and there was no difference in speed.

    I have tested with another PC (notebook) and results are almost ideally the same (both with optimised PIC code - 630kB/s; and unoptimised one - 530kB/s).


    I'm starting to think something in the PIC makes the code run too slow. Maybe interrupts are issued to late (USB is working on interrupts) or something like that....


    New test (faster!). I've moved USB ISR to IPL7 so it uses secondary register set. Result: speed with optimised code is now 689kB/s.


    Now I think the trick to make it faster would be changing USB ISR in a way that is optimised in servicing bulk IN transfers, maybe even bulk IN transfer on this one given endpoint.

    (BTW: yes, I know using USB in pooling mode should be faster if PIC was doing nothing more than USB; but it will not be a real world scenerio)

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #7
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/23 01:13:15 (permalink)
    0
    Wow, Che was not configured in this demo application and processor was running with only 60MHz clock wink

    Result after fixing that:
    Speed = 1055546 B/s

    That's fine for me Smile

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #8
    planum
    New Member
    • Total Posts : 16
    • Reward points : 0
    • Joined: 2009/06/22 10:03:35
    • Location: 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/29 12:13:15 (permalink)
    0
    Could you tell me :  How you testing speed between PC and PIC32 ? 
    #9
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/06/29 22:42:49 (permalink)
    0
    Using QueryPerformanceCounter and QueryPerformanceFrequency (on Windows)

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #10
    planum
    New Member
    • Total Posts : 16
    • Reward points : 0
    • Joined: 2009/06/22 10:03:35
    • Location: 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/10 02:02:15 (permalink)
    0
    COuld you tell me How you configured Che ?? I use this demo too .
    #11
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/10 04:41:09 (permalink)
    0

    #elif defined(__C32__)
    AD1PCFG = 0xFFFF;
    mCheConfigure(
    (((80000000 - 1) / 30000000 + 1) << _CHECON_PFMWS_POSITION)
    | CHE_CONF_PF_ALL
    | CHE_CONF_DC_NONE);
    #endif

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #12
    planum
    New Member
    • Total Posts : 16
    • Reward points : 0
    • Joined: 2009/06/22 10:03:35
    • Location: 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/10 05:36:51 (permalink)
    0
    Thanks :) . PIC working faster with CHE but USB SPEED don't .

    Now I have 1MB in 3072 ms ~ 0,33MB/s  I need ~ 1MB/s

    My configuration :

    DLL version:    0.1.12.2
    Driver version:    0.1.12.2

    bus/device  idVendor/idProduct
    bus-0/\\.\libusb0-0002--0x04d8-0x0204     04D8/0204
    - Manufacturer : Microchip Technology Inc.
    - Product      : Microchip Libusb Example Device
      wTotalLength:         32
      bNumInterfaces:       1
      bConfigurationValue:  1
      iConfiguration:       0
      bmAttributes:         c0h
      MaxPower:             50
        bInterfaceNumber:   0
        bAlternateSetting:  0
        bNumEndpoints:      2
        bInterfaceClass:    0
        bInterfaceSubClass: 0
        bInterfaceProtocol: 0
        iInterface:         0
          bEndpointAddress: 01h
          bmAttributes:     02h
          wMaxPacketSize:   64
          bInterval:        1
          bRefresh:         0
          bSynchAddress:    0
          bEndpointAddress: 81h
          bmAttributes:     02h
          wMaxPacketSize:   64
          bInterval:        1
          bRefresh:         0
          bSynchAddress:    0




    post edited by planum - 2009/07/10 05:39:05
    #13
    Deenayd
    Super Member
    • Total Posts : 905
    • Reward points : 0
    • Joined: 2004/09/08 06:15:13
    • Location: Poland
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/10 07:04:22 (permalink)
    0
    Take a look at thread linked to by xiaofan. I'd suspect problem with PC program (PC will not issue a USB request unless you request for data from your program so to get maximum speed you should request more data before you've received previous data).

    Slawek Piotrowski
    Rejestracja Czasu Pracy Ewidencja Czasu Pracy
    #14
    planum
    New Member
    • Total Posts : 16
    • Reward points : 0
    • Joined: 2009/06/22 10:03:35
    • Location: 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/11 10:46:12 (permalink)
    0
    What do you think about USB Device - MCHPUSB - Generic Driver Demo ? Can I  get ~1MB/s in this example?

    There is bulk transfer in PIC32 Firmware.

    Could you tell me more about :

    to get maximum speed you should request more data before you've received previous data


    For libUSB I use this code :

    #include <usb.h>
    #include <stdio.h>
    #include <conio.h>
    #include <Windows.h>


    /* the device's vendor and product id */
    #define MY_VID 1240
    #define MY_PID 516

    /* the device's endpoints */
    #define EP_IN 0x81
    #define EP_OUT 0x01

    #define BUF_SIZE 1024
    __int64 freq, start, end, diff;

    int retVal, nBytes;
    unsigned int mils,count;

    usb_dev_handle *open_dev(void);

    usb_dev_handle *open_dev(void)
    {
    struct usb_bus *bus;
    struct usb_device *dev;

    for(bus = usb_get_busses(); bus; bus = bus->next)
       {
         for(dev = bus->devices; dev; dev = dev->next)
           {
             if(dev->descriptor.idVendor == MY_VID
                && dev->descriptor.idProduct == MY_PID)
               {
                 return usb_open(dev);
               }
           }
       }
    return NULL;
    }

    int main(void)
    {
       int i =0;
    usb_dev_handle *dev = NULL; /* the device handle */
    char tmp[BUF_SIZE] = {0};
    char odb[BUF_SIZE] = {0};

    usb_init(); /* initialize the library */
    usb_find_busses(); /* find all busses */
    usb_find_devices(); /* find all connected devices */
    tmp[0]=0x80;

    if(!(dev = open_dev()))
       {
         printf("error: device not found!\n");
         return 0;
       }

    if(usb_set_configuration(dev, 1) < 0)
       {
         printf("error: setting config 1 failed\n");
         usb_close(dev);
         return 0;
       }

    if(usb_claim_interface(dev, 0) < 0)
       {
         printf("error: claiming interface 0 failed\n");
         usb_close(dev);
         return 0;
       }
    // start timer
    QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
    QueryPerformanceCounter((LARGE_INTEGER*)&start);

    for (;;)
    {
    retVal = usb_bulk_read(dev, EP_IN, odb, sizeof(odb), 5000);
    if (retVal > 0)
    {
    nBytes += retVal;
    }
    if (nBytes >= 262144) break; // Break at 1MByte (1024 x 1024)=1048576
    }

    // stop timer
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    diff = ((end - start) * 1000) / freq ;
    mils = (unsigned int) (diff & 0xffffffff);
    printf("time %u ms\n", mils);


    usb_release_interface(dev, 0);
    usb_close(dev);

    getch();
    return 0;
    }
    #15
    chinzei
    Super Member
    • Total Posts : 2250
    • Reward points : 0
    • Joined: 2003/11/07 12:39:02
    • Location: Tokyo, Japan
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/12 15:24:39 (permalink)
    0
    Hi, planum

    On the PC side,
    Request more bytes in single usb_bulk_read() call.
    In your code, each usb_bulk_read call requests 1K bytes. And then, usb_bulk_read is called 256 times in the loop.

    #define BUF_SIZE 1024
    char odb[BUF_SIZE] = {0};
    ...
    for (;;)
    {
    retVal = usb_bulk_read(dev, EP_IN, odb, sizeof(odb), 5000);
    if (retVal > 0)
    {
    nBytes += retVal;
    }
    if (nBytes >= 262144) break;
    }

    Each usb_bulk_read call takes overhead of 1 - 3ms. Then, on the USB line, you'll see transfer gaps between calls. This gaps reduce transfer speed.

    The loop is replaced with single usb_bulk_read call of 262144 bytes.

    #define BUF_SIZE 0x4000 // = 262144
    char odb[BUF_SIZE] = {0};
    retVal = usb_bulk_read(dev, EP_IN, odb, sizeof(odb), 5000);


    I wrote about this topic on the ST micro forum

    "How to improve bulk transfer thoughput on windows"
    Posted 23-04-2009 at 13:49 by tsuneo
    http://www.st.com/mcu/forums-cat-8181-12.html

    The first strategy to get greater transfer speed on USB is,
    - Request as many bytes as possible in single Read/Write call.
    The second strategy:
    - keep asynchronous forward reads/writes


    Tsuneo
    #16
    planum
    New Member
    • Total Posts : 16
    • Reward points : 0
    • Joined: 2009/06/22 10:03:35
    • Location: 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/15 02:28:50 (permalink)
    0

    Wow :) I get 955 kB/s  in 64kB buffer in PC libusb . Thanks chinzei, Deenyad .

    In new microchip MCHPFSUSB Framework v2.5 there is example (WinUSB High Bandwidth Demo) with transfer 1MB/s :)) . Now, for me libUSb is more easy then WinUSB .






    #17
    Stampede
    Super Member
    • Total Posts : 400
    • Reward points : 0
    • Joined: 2006/10/04 05:59:28
    • Location: Germany
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/15 03:15:46 (permalink)
    0
    Hello,

    did you change the USB stack? Or are these test completely based on a custom BULK transfer?
    I'm trying to access a SD card as fast as possible, but the USB tasks take nearly 900µs, with seems like infinity for me. Did you optimate something?
    My software is based on the SD card reader example, stack 1.04 for PIC32. I only get 400kB/s reading, writing is something around 300kB/s.
    Due to my measurements, the USB stack needs most of the time, copying data through SPI takes ca. 400µs

    regards
    Stampede
    #18
    planum
    New Member
    • Total Posts : 16
    • Reward points : 0
    • Joined: 2009/06/22 10:03:35
    • Location: 0
    • Status: offline
    RE: How to get maximum USB throughput 2009/07/15 04:18:54 (permalink)
    0
    I use :
    MCHPFSUSB Framework v2.5 for PIC32 , example - USB Device - LibUSB Generic Driver Demo
    IN PC I write simple  c language program based bulk.c example in libUSB-win32

    In PIC32 code I change clock to 80 Mhz and set CHECON register (sugesstion Deenyad :) )

    Yes I based on a custom BULK transfer .

    I sugesstion for you to look example WinUSB High Bandwidth Demo.





    #19
    Jump to:
    © 2019 APG vNext Commercial Version 4.5