Hi,
my USB composite device:
- generic HID
- virtual COM
- custom class with interrupt IN, interrupt OUT and bulk IN endpoint
runs on MK22FN512VLL12. I use USB stack from SDK 2.1
The device communicates with host for several hours but then suddenly I get one of my custom class'es IN endpoints frozen in transfer state. For this frozen endpoint, endpoint state structure (in s_UsbDeviceKhciState structure) contains e.g.:
transferLength = 0x11
tranferDone = 0x00
state = 0x4040
It means that the endpoint is in transfer state waiting for host to read the data from the device.
My USB host (libusb library on Win 10) tries to read the data. However, the read function (libusb_interrupt_transfer or libusb_bulk_transfer) always timeouts with no data read. The USB_DeviceKhciIsrFunction is not executed when the transfer is initiated by the host.
There is no issue with data transfers from the host to the device on interrupt OUT endpoint, these always work, even when IN tranfers are frozen as described above.
To send data from the device to the host using interrupt IN or bulk IN endpoint I use USB_DeviceSendRequest() function. If this call succeeds I set my internal flag indicating that the transfer is in progress. Once callback function of the endpoint is called I clear the flag. I initiate next transfer only when the flag is cleared.
Can you please recommend how to troubleshoot this issue?
You mention 'running for hours' and setting and clearing flags.
This has all the classic signs of a race condition in the flag handling.
Is the flag marked volatile?
Is it set in the IRQ and cleared outside of the IRQ (or other way around)?
Hi Bob,
thanks. Yes, the flag caused the issue. I had these two lines in my code without disabling interrupts before and enabling them after:
USB_DeviceSendRequest(...)
busy = 1;
Quite a surprise for me that that interrupt indicating transfer completion (and clearing busy flag) can happen so quickly, that it happens inside USB_DeviceSendRequest. (CPU runs at 120 MHz, USB is full speed - 12 MHz). I used exactly same construction also in my other project and I never had any issue with that device. But that project was sending 2x - 3x larger packets over USB....
But of course, stupid mistake.
My solution to this flag issue is to increment a byte inside the IRQ on an event.
Then outside the IRQ compare that value to a previous copy to see if the event happened.
Gets rid of the whole set/clear race mess.
Hi Martin,
We do not recommend you to use SDK 2.1. Could you please try using our latest SDK version (2.5.0).
You can download it from the following link:
https://mcuxpresso.nxp.com/en/welcome
Regards,
Felipe
This is my usb communication when the communication freezes. Host wants to read data from endpoint 4 (that is interrupt in endpoint) but the transaction ends with NAK.
At the same time, this is the state of endpoint 4:
(endpointState[0] has also always tranferring = 1, all other endpoints has transferring = 0)
Also, no there are no USB interrupts at that time.
Hi Felipe,
unfortunately, my app built with SDK2.5 has exactly same issue.
Martin