-
Notifications
You must be signed in to change notification settings - Fork 2.1k
drivers/periph_usbdev: fix set device address #19471
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
drivers/periph_usbdev: fix set device address #19471
Conversation
35f6fe1
to
0635f27
Compare
The address in the USB device can be set either directly after the SETUP stage on receipt of the `SET ADDRESS Request` or after the associated status stage. When the USB device address has to be set depends on the hardware. If `USBDEV_SET_ADDR_AFTER_STATUS` has the value 1 (default), the address is only set in the USB device after the status stage. Overwrite it with 0 in `periph_cpu.h` to set the address already directly after the SETUP stage. sys/usbus: use USBDEV_SET_ADDR_AFTER_STATUS Use symbol `USBDEV_SET_ADDR_AFTER_STATUS` to determine whether the device address has to be set directly after SETUP stage or after the associated STATUS stage. drivers/usbdev_synopsys_dwc2: set USBDEV_SET_ADDR_AFTER_STATUS DWC2 core requires that the device address has to be set directly after SETUP stage and not after the associated STATUS stage.
sys/usb/usbus/usbus_control.c
Outdated
@@ -241,6 +241,10 @@ static int _recv_dev_setup(usbus_t *usbus, usb_setup_t *pkt) | |||
case USB_SETUP_REQ_SET_ADDRESS: | |||
DEBUG("usbus_control: Setting address\n"); | |||
usbus->addr = (uint8_t)pkt->value; | |||
if (!IS_ACTIVE(USBDEV_SET_ADDR_AFTER_STATUS)) { |
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.
if (!IS_ACTIVE(USBDEV_SET_ADDR_AFTER_STATUS)) { | |
if (USBDEV_SET_ADDR_AFTER_STATUS) { |
Is sufficient if USBDEV_SET_ADDR_AFTER_STATUS
is always set.
sys/usb/usbus/usbus_control.c
Outdated
@@ -401,8 +405,10 @@ static int _handle_tr_complete(usbus_t *usbus, | |||
case USBUS_CONTROL_REQUEST_STATE_INACK: | |||
if (ep->dir == USB_EP_DIR_IN) { | |||
if (usbus->addr && usbus->state == USBUS_STATE_RESET) { | |||
usbdev_set(usbus->dev, USBOPT_ADDRESS, &usbus->addr, | |||
sizeof(usbus->addr)); | |||
if (IS_ACTIVE(USBDEV_SET_ADDR_AFTER_STATUS)) { |
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.
if (IS_ACTIVE(USBDEV_SET_ADDR_AFTER_STATUS)) { | |
if (USBDEV_SET_ADDR_AFTER_STATUS) { |
Same as above
drivers/include/periph/usbdev.h
Outdated
* in `periph_cpu.h` to set the address already directly after the SETUP stage. | ||
*/ | ||
#ifndef USBDEV_SET_ADDR_AFTER_STATUS | ||
#define USBDEV_SET_ADDR_AFTER_STATUS 1 |
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.
I think you want to include periph_conf.h
in this file to avoid conflicts when periph_conf.h
overrides this setting, but is included after this file.
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.
Since it is a property of the MCU and not of a board, it would be defined in periph_cpu.h
if it is defined. The file periph_cpu.h
is already included. So I wondered if I should call the symbol USBDEV_CPU_SET_ADDR_AFTER_STATUS
instead.
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 it in periph_cpu.h
sounds perfect. I don't have a strong opinion on the name, but using the USBDEV_CPU_
prefix sounds nice as that aligns it with the USBDEV_CPU_DMA_*
macros.
usbdev_synopsys_dwc2.h
(that overrides this) is as far as I can see not included in the stm32 periph_cpu.h
, so depending on the other includes in the file, it either does or does not override this define for that peripheral.
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.
usbdev_synopsys_dwc2.h
(that overrides this) is as far as I can see not included in the stm32periph_cpu.h
By intention because of USB cores and the different drivers used. It's included instead in boards/common/stm32/cfg_usb_otg_*.h
. usbdev_fs
requires to set the device address after STATUS stage.
The question is how we can ensure that the definition in usbdev_synopsys_dwc2.h
always comes before the default defintion in periph/usbdev.h
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.
I changed the name to USBDEV_CPU_SET_ADDR_AFTER_STATUS
.
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 question is how we can ensure that the definition in
usbdev_synopsys_dwc2.h
always comes before the default defintion inperiph/usbdev.h
That's why I was suggesting to include periph_conf.h
in periph/usbdev.h
. periph_conf.h
must include the usbdev_synopsys_dwc2.h
if it configures one, pretty much guaranteeing the correct order of includes required here. Other periph headers (periph/spi.h
and periph/i2c.h
) files also include periph_conf.h
, so I don't see much reason why not to include it also here.
Please squash! |
The address in the USB device can be set either directly after the SETUP stage on receipt of the `SET ADDRESS Request` or after the associated status stage. When the USB device address has to be set depends on the hardware. If `USBDEV_SET_ADDR_AFTER_STATUS` has the value 1 (default), the address is only set in the USB device after the status stage. Overwrite it with 0 in `periph_cpu.h` to set the address already directly after the SETUP stage.
Use symbol `USBDEV_SET_ADDR_AFTER_STATUS` to determine whether the device address has to be set directly after SETUP stage or after the associated STATUS stage.
DWC2 core requires that the device address has to be set directly after SETUP stage and not after the associated STATUS stage.
c323a13
to
88cabba
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.
Ack!
bors merge
Build succeeded: |
Thanks |
Contribution description
This PR allows to define when the device address is set on receipt of a SETUP with
SET ADDRESS Request
. It fixes the problem with enumeration of the Synopsys DWC2 USB OTG Core due to the wrong time of setting the device address.Especially, it fixes the problem that the enumeration fails completely for the
stm32f723e-disco
board with CDC ECM if CDC ACM is not used and the additional reset cycles during the enumeration for a couple of platforms such as ESP32-S2 and ESP32-S3.Background
The address in the USB device can be set either directly after the SETUP stage on receipt of the
SET ADDRESS Request
or after the associated STATUS stage. When the USB device address has to be set depends on the hardware implementation.Solution
To control the time of setting the device address, a new define
USBDEV_SET_ADDR_AFTER_STATUS
is introduced.If
USBDEV_SET_ADDR_AFTER_STATUS
has the value 1 (default), the address is set in the USB device after the STATUS stage. Since this is the default, existingperiph_usbdev
drivers shouldn't be affected. OverwritingUSBDEV_SET_ADDR_AFTER_STATUS
with 0 inperiph_cpu.h
or in driver header file let the address set directly after the SETUP stage.Testing procedure
Use
tests/usbus_cdc_ecm
:For
stm32f723e-disco
the enumeration doesn't work at all without this PR and works reliable with this PR.For any ESP32-S2 or ESP32-S3 board, the enumeration requires an addition reset cycle in every third or fourth enumeration without this PR and doesn't require any reset cycle with this PR.
Other platforms should still work with this PR, for example ATSAM platform:
Issues/PRs references