USBD API: How to use WriteEP reliably?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USBD API: How to use WriteEP reliably?

901 Views
pwuertz
Contributor II

Hi,

I'm having trouble understanding how to use WriteEP on Bulk IN endpoints reliably, in particular how to recover from errors. My USB vendor class firmware (and basic understanding) is based on the USBD CDC example from the LPCOpen library for the LPC XPresso 1769 Evaluation Board.

My general understanding is that the application sends a packet to the host by calling WriteEP and then waits for the USB_EVT_IN event indicating a successful transmission before sending the next packet. If the host application (libusb in my case) is constantly checking for data at this endpoint everything is nice and well.

I'm observing the problem that if the host, for whatever reason, is currently not polling for data the communication blocks indefinitely even when trying to read the data at some later time. So what I did/observed is:

  1. Host: Application is idle and is currently not submitting bulk read requests.
  2. Device: Call WriteEP and wait for USB_EVT_IN.
  3. Host: Some seconds later a bulk read request is issued.
  4. Device: No USB_EVT_IN or any other kind of event appears at the EP handler.
  5. Host: Libusb reports read timeout.
  6. Device: No further data is sent because there are no events.

So the problem is that the LPC USB stack may give up on sending a packet written by WriteEP and seemingly doesn't provide a way to inform the application or recover from this state. The CDC example application doesn't really address this issue, but instead uses a workaround: It won't call WriteEP until a host CDC driver is detected which will usually continue to read/buffer IN data even if the data isn't read from userspace.

I'm looking for a way to detect and handle this situation correctly. How to detect when the USB stack "gave up" sending a packet?

How to clear the bulk endpoint buffers when recovering from such a situation? I observed that when I force WriteEP even with no prior USB_EVT_IN acknowledgement the data transmission indeed continues but the packet order at the host is getting mixed up.

Labels (3)
Tags (1)
1 Reply

516 Views
pwuertz
Contributor II

Typical. Struggling for days and just (well one day) after posting a question comes the eureka moment. The "stall" I observed only affected the first written packet. Adding a one second delay between USB initialization and the first written packet fixed the problem. Disconnect/reconnecting the USB device causes a "stall" again (by "stall" I don't mean the EP halt feature by the way).

So after a few more experiments with some of the USBD_API_INIT_PARAM_T callbacks it seems that I need to wait at least until USB_Configure_Event before calling WriteEP, else data written by WriteEP is going to be lost without notification. So whenever this event is thrown I reset my own "wait for packet sent" logic and everything is fine, even after disconnect/reconnect.

This implicit reset behavior is an important bit of information and it would have been really helpful if the NXP examples demonstrated how to track resets.

IMHO, the API should provide an event at the registered endpoint handler to deal with the situation when an EP is reset internally or pending writes are canceled.