-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Zlp request2 #149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zlp request2 #149
Conversation
…uested length to know if a ZLP needs to happen. (fixes hathach#139)
I'm not sure the best way to handle this, but I've determined that this patch breaks if data sent down the Control Pipe during the Data Phase is an exact multiple of the packet size. The culprit is the event handler. Right now, there's no way to tell the difference between a ZLP sent as part of a Data Phase and a ZLP sent as part of a Status Phase, so the event gets eaten and tinyusb never schedules an OUT xfer to receive the ZLP as part of the Status Phase. @hathach Perhaps it's time to remove that TODO :P? |
Mulling over possible solutions to this problem. QuestionsFor @hathach:
For @pigrew:
If you hooked up your stm32f070rb to a packet analyzer, did you see ZLPs being xferred over the control pipe that were not xferred before your patch? Easy Way
I don't care for sharing globals between modules, like this. But this is the simplest, least invasive way to fix the problem. Hard Way
I would really like some feedback on these possible solutions and how to make them better. |
I wrote the patch before I had any sort of USB analyzer, so I don't know. Now, I have a DreamSourceLab DSLogic, which makes it merely inconvenient to answer your question (and I have not traced it...). However, I can say that USBTMC, with the interrupt EP disabled (leaving a 32-byte config descriptor (cfg + interface + EP IN+ EP OUT)), and 8 byte EP0 packets, does not work in the master branch. (there's a small typo where I forgot to rename some macros in the USBTMC descriptors which makes it less simple to run this test, I'll post a PR for that in the next few days. It would be nice to have Travis CI try building a few different variations of USBMTC, though perhaps only on a single platform so that there's less building required...). When I use the same code with this ZLP patch, it does work. I would appreciate if this PR is merged, as it fixes the CONTROL IN case (AFAIK). If I'm reading it correctly, the "TODO"
The class module has extra information which is required to decide if a ZLP is needed. In the case of control EP, if a short packet is sent depends on the value of wLength, which as of now, the DCD does not itself know. It's an library architecture question about how much of the EP0 control/parsing the DCD should do. Up to now, I've been leaning towards minimizing the DCD, and putting everything centrally in the library. Control are parsed/handled by I don't have time to debug this ZLP patch at the moment, but my quick thinking is similar to your "simple" case, but I would make all of the logic go into usbd_control.c. Route all xfer packets on EP0 to usbd_control (get rid of the I think of fixing CONTROL IN and CONTROL OUT as separate (but related) issues. Fixing CONTROL OUT can be a separate patch? |
Unless you have local patches, I'm not sure how your code can work, even with this ZLP patch as-is. Right now, even with this patch, tinyusb will eat/discard |
This patch only works for control data IN. My reading is that only ZLP sent OUT are ignored, and ZLP IN are handled properly with this patch. I have some uncommitted code in usbtmc, but it's unrelated to the logic here. |
New thought on test code: We don't have a good example for checking if ZLP and such is correct. We could create a new "vendor class" for debugging/verifying the core. Do we want to do this? I believe that libcm0 I propose that we add some debug code to help us with this. I could hack some debug tests into the USBTMC class, or we can create a new testing class. libopencm3 has a debug class for testing, though its license is not compatible with this project, so we can't use their code directly. Perhaps we can implement the same interface, though. USBTMC's VISA driver is pretty flexible and allows the host application to send/receive arbitrary control requests, however it doesn't give full control of the device to the host application (like libusb would). The specification also allows for vendor-defined messages. Perhaps adding this, but disabled by default, would be a good interim solution. I'm going to add a simple interface to USBTMC to allow it to respond to control transfers with specified data lengths, to make debugging easier. However, I'll leave the extension disabled by default. |
Oh, that's what you mean by:
Anyways, can you and @hathach works out the details here for getting this merged as well as a CONTROL OUT fix? My msp430 patch is blocked on fixing CONTROL OUT, and as much as I want to work on this, I have to move on to paid work for the time being. |
@cr1901 I apologize for the confusion. When first writing the patch, I hadn't considered CONTROL OUT requests. Do you have a suggested method for testing CONTROL OUT (on Windows 10)? USBTMC's driver seems to have very buggy CONTROL OUT support. @hathach I'd appreciate if you could review this patch, and then we can worry about CONTROL OUT as a separate issue? What are your thoughts? |
@pigrew Sorry for the delay, I had to move on to other things for now (I was gone 9-13, and sick this week).
I'm afraid I don't, unless libusb's WinUSB wrapper gives you easy access to the CONTROL OUT (it should AIUI).
I second this, is there any possibility this patch could be reviewed/submitted soon to keep momentum going? This patch is already merged locally in #194; I will need a corresponding fix for CONTROL OUT as well however, which could be a separate PR. |
@pigrew @cr1901 Sorry, I am late to the party, somehow this falls off my radar. I see we need to send ZLP as you both pointed out when
Yes, currently usbd discard the ZLP transfer with EP0, we will probably need to address that in order for this patch to work. It is hard to do it by simply reviewing and asking, @pigrew already did a great work. I will check out this pr to its own branch and do some dirty work. Will also find a way to test it out as well. Thank you very much :) |
… pigrew-ZLP_Request2
@hathach Thanks for looking at this. I've made this thread way too long already, but here is a brief summary for you:
|
Thanks @pigrew for lots of useful tips and suggestions, I have added couple of unit tests with Ceedling/CMock/Unity #206. This will help to simulate/mock the situation we are to tests. I have been wanting to add more tests with CMock/Unity, this is a good chance to do so :). PS: I am still in the middle of other works, but I will try to fix this. It is not as fast as we would like :) |
@pigrew You need to add uart.c file to the |
zlp request2. PR for PR (has issues with STM32F0 FSDEV)
@hathach It looks like it's related to the SET CONFIGURATION request (which doesn't have a data stage). |
@pigrew I think fsdev somehow miss a setup packet, it doesn't report the setup packet that it doesn't response to. Post on the other PR, but I merge here as well for reference. sometime miss a setup packet, then completely non-response to that packet as following screenshot nd log. As shown in the log, the setup packet is as follows string index 0, len = 255, then string index 2 len =2. It completely skip the string index = 2, len = 255 I have no idea how removing above line could cause this issue, it is possibly something related to the fsdev timing thing ? Not sure though hmm. I was thinking may be event queue is overflow and increased You can get the similar log with new
|
@hathach , Yep, I saw your message, and am still confused about the cause. On stm32, the reference manual says that it will always ACK a setup packet, even if it were to discard it (due to its buffer being full, etc)... It also stated that the USB spec only allows the device to ACK it. not sure if that's what's happening. I traced the logic a bit, and the difference with vs without the A smaller patch to get stm32 working is to add an
|
@pigrew Yeah, device does ACK the setup packet, as shown in the trace screenshot, but it didn't call |
One step closer.... It's calling tud_control_status() twice... When handling TUSB_REQ_SET_CONFIGURATION, it "manually" calls
|
@hathach, I'm heading to sleep for the night, and shouldn't spend much time on this during the next few days.... Perhaps you can craft a good fix? My analysis:
Somewhere we need to tell usb_control that there is a new control transfer, in the event that there is no data phase. |
Yeah, your analysis is very helpful. Please take the bed, I will review the whole usbd control again. Thank you very much for your work again :) |
this should fix your mentioned issue with status (no data) didn't update It certainly make the stack more stable but it still doesn't help with f0. I still think the dcd discard the setup packet somehow (but still ACK it to the host). |
fix tud_control_status() didn't update request
@hathach The patch helps my F070.... I'm able to enumerate my device now, and ZLP for control IN transfers which are multiples of the packet size are working. So, I'm happy with the patch now, and unable to reproduce the issues you found... |
The code now passes my USBTMC test script on STM32F070. |
@pigrew I still see the discard setup packet as above, but it is recoverable. Though it is kind of random. If you notice a couple seconds of delay in enumeration, that is host has to issue a bus reset and re-enumerate due to lack of response. I don't remember if this happens before but it is easy to reproduce on my Linux machine. However the purpose of this PR (ZLP) has been fully complete, we can merge this now, great works :D. Thank you very much. I will file an separated issue for missing setup packet on F0, we will look at it later on when having time. |
@pigrew I am ready to merge this long-waited PR, let's me know if you want to do anything else :) |
Great. I just changed the other TU_ASSERT, and hopefully we can merge this PR and I'll look at the other patches I have queued up. I have a likely-controversial patch which speeds up enumeration on Windows when EP0 has a max packet size of 8. Perhaps this is a separate issue, but Windows will always perform a bus-reset during enumeration. Windows always waits a few seconds for a timeout..... My solution is for that is to pre-transmit the status packet along with the first data packet when in an unconfigurated state. I have sometimes noticed the slow enumeration, I'll see if I can debug that too (as it's probably a separate issue).... |
Ship it. It's ready for merging, AFAIK. |
windows behavior is standard, I will try to investigate on how dcd discard the setup packet from dcd, by trying to add some TU_ASSERT() to pause CPU for error condition. But it is workable now, so we can live with it :) |
I completely agree. It's working well enough for me. Thanks for looking at it, I'll look also in the next few days if you don't solve it before then. Be sure to read the STM32 reference manual where it says:
|
thanks for the tip, I probably won't be able to do much with this port this week. This is not urgent, so no hurry :) |
When deciding if a ZLP needs to be sent, the requested length in the status packet has to be compared to the length being transmitted.
Also, I think there's a possible buffer overrun here in handling HID out control transfers, so I added a TU_VERIFY to make sure the buffer is long enough. I wonder if there are other places where this happens?
Tested on the stm32f070rb.