chipKIT® Development Platform

Inspired by Arduino™

Using USB 2.0 512-byte packet size on Max 32

Created Thu, 27 Sep 2012 19:09:29 +0000 by peplin


Thu, 27 Sep 2012 19:09:29 +0000

I have a project running on the Max32 that acts as as a USB device. Basically it sends a steady stream of data from the device to the host, IN transfers.

Until this point, we had been setting the IN endpoint descriptor to use 64 byte packets. We continuously call GenWrite() from the chipKIT/Microchip USB device library with at most 64 bytes of data (i.e. <= 1 packet). This works fine, but we're hitting some performance bottlenecks, likely due to the large number of transfers we have to initiate.

I'd like to bump this up to using full 512 byte packets, which are allowed for bulk endpoints like this one in the USB 2.0 spec. Here's the output of lsusb -vvv with the new descriptor:

Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x1bc4 Ford Motor Co.
  idProduct          0x0001 
  bcdDevice            1.00
  iManufacturer           1 Ford Motor Company
  iProduct                2 
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           32
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
Device Status:     0x0001
  Self Powered

It looks like I successfully switch the endpoint max packet size to 512 bytes, and the bcdUSB is v 2.0. So far so good.

However, when I now call GenWrite() with more than 64 bytes of data, it works for a couple of transfers and then dies. I've examined the traffic in Wireshark and found that this happens:

  • The host makes a URB IN request for 512 bytes of data (that's what our receiving end requests, and that works fine when the packets are 64 bytes)
  • The device response with only 64 bytes, and gives a status of "Remote I/O error" (this is expected when we don't have a full packet to send)
  • This continues for a few rounds, the host requesting 512 and the device sending 64
  • Finally, the device response with 0 bytes and the status: Broken Pipe

At this point, the USB device is entirely reconfigured on the host - it gets a new device ID, the endpoints are all broken, and we have to start over. The PIC32 is definitely not crashing or anything, because I can still see debug output continuing just fine over UART.

Has anyone else been successful with 512 byte packets on the PIC32?


Fri, 28 Sep 2012 11:45:56 +0000

I have not done what you are asking about, but on a hunch, try a size that's not an exact multiple of 64. Try 511 for example, and see what happens. I think there is special handling that has to happen for zero length packets (ZLPs) when you get to the end of the 512 bytes. By going to 511, you don't have any ZLPs.



Fri, 05 Oct 2012 11:07:10 +0000

Only USB HIGH SPEED and SUPER SPEED allow for bulk endpoints greater than 64 bytes. FULL SPEED devices (PIC32) are limited to a max BULK endpoint size of 64 bytes.

While it is true that there are out of spec "exploits" and tricks that can work they however are still out of spec and there are no guarantees that something that works with one host will work with another or even work all the time on the same host. Then there are hubs to consider and devices that may be downstream of that hub.

Even if the host was going to allow bulk endpoints of 512 bytes on a FULL SPEED device, there is certain more that needs to be altered in the microchip stack than just the endpoint size in the endpoint descriptor. However, I just cannot recommend trying to use USB out of spec like that...


Mon, 08 Oct 2012 15:02:26 +0000

Ah, I understand now - I mistakenly read "USB 2.0" as meaning it could actually do high-speed. I see now in the full reference manual that it's actually a "USB 2.0 Full Speed OTG controller". Digilent, I might suggest this be moved to the website so others aren't bitten by the same confusion.