Deenayd
Super Member
- Total Posts : 905
- Reward points : 0
- Joined: 2004/09/08 06:15:13
- Location: Poland
- Status: offline
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).
|
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)
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).
|
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)
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.
|
Kiwi Mike AZ
Super Member
- Total Posts : 2056
- Reward points : 0
- Status: offline
RE: How to get maximum USB throughput
2009/06/21 20:44:23
(permalink)
Recommend using Bulk transfer then as Isochronous does not guarantee integrity, but bulk does. Mike
|
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)
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
|
Kiwi Mike AZ
Super Member
- Total Posts : 2056
- Reward points : 0
- Status: offline
RE: How to get maximum USB throughput
2009/06/22 12:30:32
(permalink)
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
|
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)
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)
|
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)
Wow, Che was not configured in this demo application and processor was running with only 60MHz clock Result after fixing that: Speed = 1055546 B/s That's fine for me
|
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)
Could you tell me : How you testing speed between PC and PIC32 ?
|
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)
Using QueryPerformanceCounter and QueryPerformanceFrequency (on Windows)
|
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)
COuld you tell me How you configured Che ?? I use this demo too .
|
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)
#elif defined(__C32__) AD1PCFG = 0xFFFF; mCheConfigure( (((80000000 - 1) / 30000000 + 1) << _CHECON_PFMWS_POSITION) | CHE_CONF_PF_ALL | CHE_CONF_DC_NONE); #endif
|
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)
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
|
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)
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).
|
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)
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; }
|
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)
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
|
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)
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 .
|
Stampede
Super Member
- Total Posts : 403
- 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)
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
|
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)
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.
|