2010-05-01 07:48 AM
Bug in CTR_HP of USB library.
#usb-interrupts #determining-the-right-endpoints-in-ctr_hp2011-05-17 04:49 AM
Hi,
In our STM32F102/103 devices, USB events can generate 3 interrupts and are mapped to three different lines of the NVIC: 1) USB low-priority interrupt (Channel 20): Triggered by all USB events (Correct transfer, USB reset, etc.). The firmware has to check the interrupt source before serving the interrupt. 2) USB high-priority interrupt (Channel 19): Triggeredonly by
a correct transfer event for isochronous and double-buffer bulk transfer to reach the highest possible transfer rate.
3) USB wakeup interrupt (Channel 42): Triggered by the wakeup event from the USB Suspend mode. Is it possible to share me your code able to elaborate this race condition ? Thanks Cheers, STOne-32.
2011-05-17 04:49 AM
You quoted correctly that:
2) USB high-priority interrupt (Channel 19): Triggeredonly by
a correct transfer event for isochronous and double-buffer bulk transfer to reach the highest possible transfer rate.
The important word is ''Triggered''. This means that the hardware only guarantees that the correct ISR is called. In the case where high-priority end points AND low-priority ends points are pending, the CTR_HP is correctly called. It is still the responsibility of the CTR_HP to ONLY processes the USB high-priority end points. Instead of code, I have attached sequence diagrams for these bug scenarios. If this is not enough to show the problem, I can generate some code to highlight the problem.
2011-05-17 04:49 AM
When the high priority interrupt occurs does the ISTR register show the high priority endpoints first? If the ISTR is polled in a loop during the interrupt service routine, is it guaranteed that all HP endpoint sources show up in ISTR before LP ones?
I understand that the endpoint register can be checked to see if the interrupt request comes from isochronous or double buffered bulk transfer endpoints, but if the endpoints are not stacked up by high/low priority there really isn't a use for a second high priority interrupt vector, since all the endpoints would have to be checked as they showed up in the ISTR register regardless of HP or LP priority. Jack Peacock2011-05-17 04:49 AM
If an interrupt service routine takes 500ms to complete then there's a serious design flaw somewhere!
Assuming a good RTOS where the USB interrupts can be queued as events for completion routines at the task level then it comes back to the question of why a HP interrupt is required. Deferring USB interrupt completion to the task level rather than interrupt assures that HP interrupts won't be lost while a LP event is clearing. If both USB interrupt service routines have to clear every pending endpoint interrupt that shows up in the ISTR then why bother with the HP vector? Why would any interrupt sources other than CTR appear on the ISTR for the HP interrupt? I don't know exactly how the USB macrocell works, but if it isn't smart enough to restrict interrupt sources appearing in the ISTR for the HP vector then it makes more sense to handle all USB interrupts through the LP vector. If there is a composite USB device with more than one bulk transfer endpoint then the HP vector does have to handle multiple endpoints per interrupt. Back to the same problem, looping through ISTR updates for each endpoint, be it HP or LP. Jack Peacock2011-05-17 04:49 AM
The reason is that you do not want to mix your long running(upto 500ms)-low priority control transactions with your fast running-high priority transactions. Note that the problem is not that you do not service your high priority transactions first. The problem with using just one level of interrupt is that if you start a long running transaction, you can not handle any high priority transaction that come in after until you are done with the long running transaction.
2011-05-17 04:49 AM
If the USB library it does not support the USB spec of 500ms, whose spec should it follow?
Why assume a RTOS? A lot of custom devices just communicate, do simple filtering and talk to hardware. With all the ARM's sofware interrupts, a RTOS for these simple devices is just a detriment. You have one implict assumption that is incorrect. The ISR does not need to service all pending end points in one call. In fact a good design for the CTR_HP is to get the highest priority pipe from the hardware register (with no testing), clear pending for it, service it, and then exit (no looping). This optimizes the normal case of having only one high priority pipe pending. This also removes all interactions with the low priority pipes.2011-05-17 04:49 AM
thanks to Jon for submitting this issue. I have been debugging precisely the problem scenario you described, handling a pending control msg on pipe 0 within CTR_HP() which eventually caused a hard fault.
I fixed it by replacing this
while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
with this
if (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
ST, please consider fixing this in your library. Thanks!