IntergatedCircuits / USBDevice

Highly flexible Composite USB Device Library
Apache License 2.0
216 stars 45 forks source link

CDC bulk in transfer stalls for specific data lengths #21

Closed sammas123 closed 4 years ago

sammas123 commented 4 years ago

I have noticed in the latest USBDevice library the USB FS CDC IN endpoint seems to freeze when sending a packet of a multiple of 64 bytes: UsbDevice_SEND_CDC(buffer, 64) for example.

My USB knowledge is not the greatest but it seems to be related to this stackoverflow issue: https://stackoverflow.com/questions/41195559/usb-cdc-bulk-in-endpoint-freeze

Following the advice of that thread and sending a zero length packet indeed rectifies the issue on my device (stm32f722 using USBDevice4Cube wrapper library).

Note that I am using Termite 3.4 on the receiving side (100ms polling), and Line coding parameters are 115200 baud, 1 stop bit, 8 data bits, no parity.

benedekkupper commented 4 years ago

This is a tricky situation in the sense that it's hard to decide which layer's responsibility is it to send ZLP (zero length packet). It is even dependent on the OS driver, whether ZLPs are required to pass a buffer to the application. In any case I've added a commit that sends a ZLP at the end of each such transfer, please let me know if this solves your issue.

VaZso commented 4 years ago

I don't know if it is related but since I use your library, sometimes my CDC-ACM devices freeze.

Now I saw this modification, so upgraded this library in my project, put a counter inside and printed its value to this serial device in every 10 ms then in every 50 ms.

I have not compared it against the previous version of your library but it still freezes for me.

I try it under Linux (Debian). Sometimes it can count up to ~800, sometimes it can count in the ~2000 range but sooner or later it freezes (the STM32 is still running). If I pull out the USB connector partly in a way power still connected but data lines are not, then plug in back again, it starts to work again and I see the value of my counter (which counted in a higher range while it was frozen / not connected.

So I still curious if sammas123 still experiencing his problem or this has been fixed it.

VaZso commented 4 years ago

I have done a Wireshark capture. When I open the port at package 95, it sends out the internal buffer. From package 153, it sends only the counter ("Counter: 770"). At package 10151, I see my last received counter value ("Counter: 1093"). I don't know why I see the same data again at 10153, however I also saw it earlier like at package 9427.

So after that, I have not receiving any data, but I see "URB_INTERRUPT in" messages from package 10189 until I close opened port maybe near at package 10451.

So it seems to be unrelated to 64 byte-specific problem.

Anyway, in capture, I see "URB Interrupt in" messages maybe in every 242 messages, so device sends it to host then host sends it to device and a messages comes right after in the next package. However, when the connection freezes, I see the same "URB Interrupt in" ping-pont but without the message.

So it seems to me the message interrupt comes to host but message is not arriving.

Do you have any idea regarding this? Should I open another issue?

ttyacm.pcapng.gz

sammas123 commented 4 years ago

I have updated the library and tested the changes - in my initial testing it appears to resolve the problem, so thank you very much!

I can't comment on your issue VaZso as it does not appear on my windows machine. I will close this point and I recommend opening a new one as it seems unrelated.

VaZso commented 4 years ago

Thanks @sammas123 - I have opened a new issue.

It seems it halts for me when USBD_CDC_Transmit is called too often and as of the Wireshark capture above, it calls for an interrupt and host sends it, but it does not send its data. At software side, I see ep->State remains in USB_EP_STATE_DATA.

...so, I think this problem should exists also under Windows under the same circumstances. However, the OS may reset the connection so it may happen to be solved at driver level.