I did notice one difference between transactions that did contain the problem and transactions that didn't.
The Windows 8 tablet sent the USB IN/OUT packets within a few microseconds of each other, while my Windows 7 desktop sent the packets with about a millisecond between them.
Perhaps the PSoC USB controller is having problems with such rapid fire transactions? Maybe that's why successive IN/DATA/[N]ACK transactions sometimes (but not always) succeed; because they are given enough time after the previous transaction.
Attached is my protocol analyzer data with timestamps for both a good and a bad transaction.
UsbProblem2.jpg 336.3 K
One additional piece of information:
I slightly modified the generated Vendor Request handler code so that my firmware processes USB vendor requests in the main-loop context instead of the interrupt context, so the code sequence is:
Receive SETUP request interrupt and store the setup info (i.e. bRequest, wValue, etc...)
Receive any OUT packet interrupts and gather their data into a buffer
After processing the final OUT packet interrupt, set USBFS_ep0Mode = USBFS_MODE_NAK_IN_OUT so that the status IN packets will be NACKed until my main loop has completed the vendor request.
When the main loop has completed the vendor request, I do the following to allow the Status IN packet to be ACKed which will tell the host that the request has completed:
USBFS_ep0Mode = USBFS_MODE_STATUS_IN_ONLY;
CY_SET_REG8(USBFS_EP0_CR_PTR, (CY_GET_REG8(USBFS_EP0_CR_PTR) & ~USBFS_MODE_MASK) | USBFS_MODE_STATUS_IN_ONLY );
The lost IN packets seem to occur when the final OUT packet ISR sets the ep0 mode to USBFS_MODE_NAK_IN_OUT.
I can see that you are using PSoC5 and the people who are monitoring this USB forum are not that familiar with PSoC5 programming.
So, I feel that it would be better to post these questions in one of the PSoC5 forum threads to get the best solution.
If you have any general questions on USB, please post them here and we would love to help you.
I found the problem.
In order to prevent the EP0 OUT transaction from completing until I wanted it to, I was setting the ep0 mode to USBFS_MODE_ACK_OUT instead of USBFS_MODE_ACK_OUT_STATUS_IN. Since the Status IN packet was coming in before I completed my ep0 OUT ISR handler (which changed the mode to USBFS_MODE_NAK_IN_OUT after the last OUT packet), the SIE would ignore some of the IN packets.
Fixed by setting the ep0 mode register to USBFS_MODE_NAK_IN_OUT immediately upon entering the ep0 OUT ISR.