-
Notifications
You must be signed in to change notification settings - Fork 7.3k
usb: device_next: Add Kconfig to set maximum speed #76255
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
Conversation
config USBD_MAX_SPEED | ||
int | ||
default 0 if USBD_MAX_SPEED_FULL | ||
default 1 if USBD_MAX_SPEED_HIGH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this indirection is needed? Why not simple do if (IS_ENABLED(CONFIG_USBD_MAX_SPEED_HIGH)
in the C code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The choice here makes it possible to add Super-Speed support later on without much hassle. IS_ENABLED(CONFIG_USBD_MAX_SPEED_HIGH)
would make things harder IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense, thanks. I'll take a closer look later today.
drivers/usb/udc/udc_dwc2.c
Outdated
dcfg |= usb_dwc2_set_dcfg_devspd(USBD_SUPPORTS_HIGH_SPEED ? | ||
USB_DWC2_DCFG_DEVSPD_USBHS20 : USB_DWC2_DCFG_DEVSPD_USBFS20); | ||
break; | ||
case USB_DWC2_GHWCFG2_HSPHYTYPE_UTMIPLUS: | ||
gusbcfg |= USB_DWC2_GUSBCFG_PHYSEL_USB20 | | ||
USB_DWC2_GUSBCFG_ULPI_UTMI_SEL_UTMI; | ||
dcfg |= USB_DWC2_DCFG_DEVSPD_USBHS20 | ||
<< USB_DWC2_DCFG_DEVSPD_POS; | ||
dcfg |= usb_dwc2_set_dcfg_devspd(USBD_SUPPORTS_HIGH_SPEED ? | ||
USB_DWC2_DCFG_DEVSPD_USBHS20 : USB_DWC2_DCFG_DEVSPD_USBFS20); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This layer violation. You may not use anything from subsys/usb/device_next. And there is absolutely no need to limit the high-speed controller to full speed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are valid reasons for disabling high-speed, otherwise the peripherals wouldn't support it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the reasons aside (the most trivial one is replicating an existing device with a newer SoC in a way that allows reusing existing host software without any modifications), please guide how to achieve this functionality without "layer violation". Note that USB itself has design choices that could be classified as layering violations, like:
- different configurations based on operating speed
- the meaning of bInterval field in Endpoint descriptor depends on operating speed
- isochronous feedback size and meaning depends on operating speed
The operating speed plays so significant role in USB that I believe there must be a way to force Full-Speed only operation of High-Speed capable device without resorting to filtering out high-speed detection handshake on D+/D- lines.
subsys/usb/device_next/Kconfig
Outdated
choice USBD_MAX_SPEED_CHOICE | ||
prompt "Max supported connection speed" | ||
default USBD_MAX_SPEED_FULL if UDC_IT82XX2 || UDC_KINETIS || UDC_NRF || UDC_STM32 | ||
default USBD_MAX_SPEED_HIGH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This layer violation. You may not use anything from drivers/usb//Kconfig. or have any dependencies on drivers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then how do you enable the easy and quite significant code and RAM savings on platforms that have controllers that are not capable of high-speed operation? Please come up with alternative instead of just screaming "layer violation".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's consider CDC ACM sample to be representative one. When building it for nRF52840DK (CONF_FILE=usbd_next_prj.conf west build --pristine -b nrf52840dk/nrf52840 -d build-cdc-acm-next ~/zephyrproject/zephyr/samples/subsys/usb/cdc_acm
) on 596ef0a the summary is:
Memory region Used Size Region Size %age Used
FLASH: 61636 B 1 MB 5.88%
RAM: 20976 B 256 KB 8.00%
IDT_LIST: 0 GB 32 KB 0.00%
With this PR the summary is:
Memory region Used Size Region Size %age Used
FLASH: 60924 B 1 MB 5.81%
RAM: 20080 B 256 KB 7.66%
IDT_LIST: 0 GB 32 KB 0.00%
Note that this PR does only the low-hanging fruits and more savings would be possible (but would require a lot of COND_CODE
which may be too costly maintenance-wise).
e14c6eb
to
8907371
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The speed choice looks good now :)
Rebased to fix merge conflicts. |
Rebased to fix merge conflicts. |
This PR achieves two main goals:
The design that enables above goals boils down to:
Architecture Working Group is expected to resolve following disagreement: a) Whether allowing user to limit High-Speed capable controller to operate at Full-Speed only is supported use case.
b) Whether having a single user-configurable source of truth for maximum supported speed (Kconfig choice Future extensibility considerations:
|
For completeness (and to avoid confusion), could we have option 3 added to the table in #76255 (comment) (or create a new table with all three options listed)? |
A quick note from me as part of the upcoming discussion: @jfischer-no wrote:
Not only there is a tangible benefit, but Nordic has specific requests from customers to implement this. The reasoning is simple, as outlined by the customer: smaller code size, reduced complexity, ability to reuse parts of verification/internal certification. |
This would only reduce memory usage. It does not reduce code size, the code is already there and is always built. This PR actually increases complexity. Again, for a USB device, if you replace a full-speed device with another that is a high-speed device, then no verification/certification can be reused because it is a new device regardless of speed. |
That's the exact reason for a customer wanting to limit the maximum USB speed. |
I do not know the customer's exact reason. I would be surprised if you did. However, the customer will need to re-certify/verify the new USB device because it would be a completely new device, regardless of what maximum speed the final product will support. |
That was the question that immediately jumped out to me as well. |
@jfischer-no is there some reason that the driver layer cant have a choice-type config structure to get the "ease of use" like in option 1/3 but not depend on upper layer? |
yet another case of zephyr missing a multi instance static software config system |
See #76255 (comment) |
This PR has nothing to do with DT or multi-instance static software configuration system. There is no dependency on DT in the USB device stack next. |
I disagree. Option 1/3 is precisely what has the one and only one Kconfig option to limit the application as a whole to Full-Speed only.
You don't seem to accept that the real world use case for the user is to limit the USB stack (external device behavior) to particular speed. Forcing the controller to disable High-Speed chirp is just a necessary consequence of the user choice to limit the stack. |
yes I know, but someone else brought it up, and I think you can't deny it would be nice to be able configure the limit per device since many platforms have multiple devices (not endpoints, devices) that use the same driver. But it is outside of the scope of this PR so we don't need to discuss about it here, you're right
I read your comment and you said
I think we are past this by now in the discussion because it was made clear that the goal is to configure a device to act only as full speed for the purpose of footprint savings, whether you personally want to do this is besides the point. And as far as Kconfig bloat, I don't think that is even valid here. I am willing to completely agree with you on this statement you made:
because to me that seems like the most sound architecture, and therefore your option 2 seems preferable. But I also have to say that at first looking at the comparison comment above , at a glance, the option 1/3 looks more preferable from a user perspective. Whether it is long term a good design is more important of course, but what I don't understand is why would you be opposed to a solution that combines your architectural awareness with the usability of the other two options. It seems obvious to me here unless I don't understand something that we can get the best of both worlds simply by introducing the user choice config similar to what is option 1/3 at the driver level to be fundamentally like option 2. What is the complication here, if there is any, from a technical (non opinionated) perspective? and don't say "bloat" or "unnecessary" |
If the user chooses to limit USB functionality (to Full-Speed only) at the stack level, then it doesn't matter what underlying drivers are there (all drivers should be aware that they are operating with Full-Speed only stack and therefore should disable High-Speed chirp).
The technical point is that by having the user-selectable option in UDC to limit the speed, then we would have to either:
This is what option 3 is really. There is a hidden UDC Kconfig selected based on stack functionality so the UDC drivers can disable High-Speed chirp based on a UDC Kconfig instead of USB stack configuration. |
This whole disagreement is summed up in the latest commit "usb: device_next: Change speed selection Kconfig dependency". I believe this commit is extremely harmful, but it may be the only way to move this forward. |
Fix a typo resulted in USBD_SPEED_HS unregistering Full-Speed class instead of High-Speed. Signed-off-by: Tomasz Moń <[email protected]>
Two main ideas behind setting maximum speed are: * Allow code and RAM optimizations at compile time * Allow High-Speed capable drivers to limit operating speed to user choice. This commit only introduces the necessary Kconfig options but does not implement any code or RAM optimizations and does not modify any driver. Signed-off-by: Tomasz Moń <[email protected]>
Allow compiler optimizations to remove High-Speed handling code. Knowing that maximum operating speed is Full-Speed allows to reduce bulk buffers from 512 to 64 bytes. More RAM optimizations are possible but this commit only gets the low hanging fruits. Signed-off-by: Tomasz Moń <[email protected]>
Limit maximum operating speed in DCFG register if USB stack is configured to support only Full-Speed. Signed-off-by: Tomasz Moń <[email protected]>
In my opinion, the user is supposed to configure the speed of the stack and drivers ough to honor that choice. However current Zephyr USB maintainer imposes that the dependency is the other way round, i.e. that user first needs to disable High-Speed chirp at driver level and only then can select Full-Speed only operation. Adhere to the arbitrarily set up rule to allow this really necessary functionality to enter Zephyr. I consider this change to be harmful because it opens up a Kconfig trap that allows configuring High-Speed capable stack with a device driver limited to Full-Speed only operation. Signed-off-by: Tomasz Moń <[email protected]>
Setting maximum supported speed to Full-Speed can reduce code size by allowing compiler optimizations at compile time and also helps reducing RAM by allocating smaller bulk buffers. More RAM optimizations are possible but this commit only gets the low hanging fruits.
Another idea is that High-Speed capable drivers can use this information to limit operating speed to user choice. This PR implements this only for udc_dwc2 driver.
Implements: #75002