-
Notifications
You must be signed in to change notification settings - Fork 84
Description
Currently every UsbBus implementation that I am aware of is Sync and it synchronizes access by wrapping most UsbBus methods in a critical section. This can cause latency issues, because it means that during USB reads, writes and polling any higher priority interrupt handlers will be delayed. This has been a problem in practice (see stm32-rs/stm32-usbd#32, stm32-rs/synopsys-usb-otg#27).
In theory a UsbBus could be implemented which is not Sync, as the Sync bound was removed in #149. Unfortunately, in practice such a UsbBus ends up being extremely restrictive. This is because UsbDevice and UsbClass-es contain a reference to UsbBus and if UsbBus isn't Sync then &UsbBus isn't send and therefore UsbDevice and UsbClass-es using the bus aren't Send. This means that there is no safe way to move them into interrupt handlers or elsewhere, even with mutexes and other synchronization. This rules out practically any architecture except for using UsbDevice and UsbClass-es in the main loop.
Given all this, there is a practical need for a way to implement UsbBus without critical sections everywhere while still allowing you to move UsbDevice and UsbClass-es to other threads.
My main claim is this:
I believe it isn't possible for individual UsbBus implementations to fix this problem on their own. There is a need to adjust the usb-device API to resolve this.
I don't have a specific proposal, but I have two high-level solution outlines:
-
Split
UsbBusinto components which can be owned exclusively byUsbDeviceandUsbClass-es. E.g. theUsbDevicewould have exclusive ownership of the core USB registers (interrupts, statuses and whatnot) and eachUsbClasswould have exclusive ownership of its own endpoints. Since all endpoints are allocated ahead of time there should be minimal interaction between these components at runtime and thus minimal need for synchronization using critical sections. -
Make
UsbDeviceexclusively own theUsbClass-es. This would allowUsbDeviceto exclusively own the entireUsbBus, thus requiring no synchronization. (This is compatible with solution 2 from this semi-related issue: Figure out a better way to keep track of the list of classes #9.)
I would love to have some feedback on what people think of this. Can this be done? Should this be done? Is anyone using workarounds for this in practice and if so what are these workarounds?