1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
19438: usbus: Add support for full speed with high speed phy r=miri64 a=bergzand

### Contribution description

This adds infrastructure around usbus and usbdev to query the speed of the USB link after enumeration. This as the maximum speed of the link might be slower than the maximum speed of the peripheral. This is the case with the stm32f429i-disco board that has a full speed phy coupled with the high speed peripheral.

This also adds the necessary code to the cdc_ecm code to use the correct packet size. The allocated buffer size is not modified with this PR unfortunately.

### Testing procedure

The `cdc_ecm` handler should work with a HS peripheral coupled with a FS phy.

### Issues/PRs references

Fixes an issue caused by #19358


Co-authored-by: Koen Zandberg <koen@bergzand.net>
This commit is contained in:
bors[bot] 2023-03-31 17:00:16 +00:00 committed by GitHub
commit f797bbee2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 138 additions and 5 deletions

View File

@ -36,7 +36,7 @@ extern "C" {
#define DWC2_USB_OTG_HS_ENABLED
/**
* @brief Common USB OTG HS configuration with on-chip FS PHY
* @brief Common USB OTG FS configuration
*/
static const dwc2_usb_otg_fshs_config_t dwc2_usb_otg_fshs_config[] = {
{

View File

@ -20,6 +20,7 @@ config BOARD_STM32F429I_DISC1
select HAS_PERIPH_TIMER
select HAS_PERIPH_UART
select HAS_PERIPH_USBDEV
select HAS_PERIPH_USBDEV_HS
# Put other features for this board (in alphabetical order)
select HAS_RIOTBOOT
@ -38,4 +39,6 @@ config BOARD_STM32F429I_DISC1
select HAVE_I3G4250D
select HAVE_L3GD20
select MODULE_PERIPH_USBDEV_HS if MODULE_PERIPH_USBDEV
source "$(RIOTBOARD)/common/stm32/Kconfig"

View File

@ -1,3 +1,7 @@
ifneq (,$(filter periph_usbdev,$(USEMODULE)))
USEMODULE += periph_usbdev_hs
endif
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
USEMODULE += l3gxxxx

View File

@ -8,6 +8,7 @@ FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_usbdev
FEATURES_PROVIDED += periph_usbdev_hs
# Put other features for this board (in alphabetical order)
FEATURES_PROVIDED += riotboot

View File

@ -1021,10 +1021,36 @@ static void _usbdev_init(usbdev_t *dev)
#endif
}
static usb_speed_t _get_max_speed(const usbdev_t *dev)
{
dwc2_usb_otg_fshs_t *usbdev = (dwc2_usb_otg_fshs_t *)dev;
const dwc2_usb_otg_fshs_config_t *conf = usbdev->config;
if (IS_USED(DWC2_USB_OTG_HS_ENABLED) && (conf->type == DWC2_USB_OTG_HS)) {
return USB_SPEED_HIGH;
}
return USB_SPEED_FULL;
}
static usb_speed_t _get_enumeration_speed(const usbdev_t *dev)
{
dwc2_usb_otg_fshs_t *usbdev = (dwc2_usb_otg_fshs_t *)dev;
const dwc2_usb_otg_fshs_config_t *conf = usbdev->config;
unsigned speed = (_device_regs(conf)->DSTS & USB_OTG_DSTS_ENUMSPD_Msk) >>
USB_OTG_DSTS_ENUMSPD_Pos;
switch (speed) {
case 0x00:
return USB_SPEED_HIGH;
case 0x03:
return USB_SPEED_FULL;
default:
assert(false); /* reserved values by peripheral */
}
return USB_SPEED_FULL; /* Should not be reached */
}
static int _usbdev_get(usbdev_t *dev, usbopt_t opt,
void *value, size_t max_len)
{
(void)dev;
(void)max_len;
int res = -ENOTSUP;
switch (opt) {
@ -1035,7 +1061,12 @@ static int _usbdev_get(usbdev_t *dev, usbopt_t opt,
break;
case USBOPT_MAX_SPEED:
assert(max_len == sizeof(usb_speed_t));
*(usb_speed_t *)value = USB_SPEED_FULL;
*(usb_speed_t *)value = _get_max_speed(dev);
res = sizeof(usb_speed_t);
break;
case USBOPT_ENUMERATED_SPEED:
assert(max_len == sizeof(usb_speed_t));
*(usb_speed_t *)value = _get_enumeration_speed(dev);
res = sizeof(usb_speed_t);
break;
default:

View File

@ -239,6 +239,26 @@ typedef enum {
USB_EP_DIR_IN, /**< Host in, device out */
} usb_ep_dir_t;
/**
* @brief Maximum transfer size for interrupt endpoints at full speed
*/
#define USB_ENDPOINT_INTERRUPT_FS_MAX_SIZE (64)
/**
* @brief Maximum transfer size for interrupt endpoints at high speed
*/
#define USB_ENDPOINT_INTERRUPT_HS_MAX_SIZE (1024)
/**
* @brief Maximum transfer size for bulk endpoints at full speed
*/
#define USB_ENDPOINT_BULK_FS_MAX_SIZE (64)
/**
* @brief Maximum transfer size for bulk endpoints at high speed
*/
#define USB_ENDPOINT_BULK_HS_MAX_SIZE (512)
#ifdef __cplusplus
}
#endif

View File

@ -70,6 +70,15 @@ typedef enum {
*/
USBOPT_MAX_SPEED,
/**
* @brief (usb_version_t) Speed at which the usb peripheral got enumerated by the host
*
* Should be equal or slower than @ref USBOPT_MAX_SPEED
*
* Setting this option must return -ENOTSUP
*/
USBOPT_ENUMERATED_SPEED,
/* expand list if required */
} usbopt_t;

View File

@ -589,6 +589,22 @@ void usbus_register_event_handler(usbus_t *usbus, usbus_handler_t *handler);
*/
void usbus_init(usbus_t *usbus, usbdev_t *usbdev);
/**
* @brief Get the maximum supported bulk endpoint transfer size based on the enumeration speed
*
* Should only be called after enumeration has finished by the peripheral. Calling this in response
* to the @ref USBUS_EVENT_USB_RESET is valid
*/
size_t usbus_max_bulk_endpoint_size(usbus_t *usbus);
/**
* @brief Get the maximum supported interrupt endpoint transfer size based on the enumeration speed
*
* Should only be called after enumeration has finished by the peripheral. Calling this in response
* to the @ref USBUS_EVENT_USB_RESET is valid
*/
size_t usbus_max_interrupt_endpoint_size(usbus_t *usbus);
/**
* @brief Create and start the USBUS thread
*

View File

@ -336,6 +336,12 @@ static void _handle_reset(usbus_t *usbus, usbus_handler_t *handler)
{
usbus_cdcecm_device_t *cdcecm = (usbus_cdcecm_device_t *)handler;
/* Set the max packet size advertised to the host to something compatible with the enumerated
* size */
size_t maxpacketsize = usbus_max_bulk_endpoint_size(usbus);
cdcecm->ep_in->maxpacketsize = maxpacketsize;
cdcecm->ep_out->maxpacketsize = maxpacketsize;
DEBUG("CDC ECM: Reset\n");
_handle_in_complete(usbus, handler);
cdcecm->notif = USBUS_CDCECM_NOTIF_NONE;

View File

@ -71,7 +71,7 @@ static int _send(netdev_t *netdev, const iolist_t *iolist)
/* load packet data into FIFO */
size_t iol_offset = 0;
size_t usb_offset = 0;
size_t usb_remain = cdcecm->ep_in->ep->len;
size_t usb_remain = cdcecm->ep_in->maxpacketsize;
DEBUG("CDC_ECM_netdev: cur iol: %d\n", iolist->iol_len);
while (len) {
mutex_lock(&cdcecm->out_lock);

View File

@ -162,6 +162,50 @@ usbus_endpoint_t *usbus_interface_find_endpoint(usbus_interface_t *interface,
return NULL;
}
size_t usbus_max_bulk_endpoint_size(usbus_t *usbus)
{
usb_speed_t speed;
int res = usbdev_get(usbus->dev, USBOPT_ENUMERATED_SPEED, &speed,
sizeof(speed));
if (res == -ENOTSUP) {
res = usbdev_get(usbus->dev, USBOPT_MAX_SPEED, &speed,
sizeof(speed));
}
if (res < 0) {
return 0; /* Misbehaving usbdev device not implementing any speed indication */
}
switch (speed) {
case USB_SPEED_HIGH:
return USB_ENDPOINT_BULK_HS_MAX_SIZE;
default:
return USB_ENDPOINT_BULK_FS_MAX_SIZE;
}
}
size_t usbus_max_interrupt_endpoint_size(usbus_t *usbus)
{
usb_speed_t speed;
int res = usbdev_get(usbus->dev, USBOPT_ENUMERATED_SPEED, &speed,
sizeof(speed));
if (res == -ENOTSUP) {
res = usbdev_get(usbus->dev, USBOPT_MAX_SPEED, &speed,
sizeof(speed));
}
if (res < 0) {
assert(false); /* Misbehaving usbdev device not implementing mandatory USBOPTS */
}
switch (speed) {
case USB_SPEED_HIGH:
return USB_ENDPOINT_INTERRUPT_HS_MAX_SIZE;
default:
return USB_ENDPOINT_INTERRUPT_FS_MAX_SIZE;
}
}
usbus_endpoint_t *usbus_add_endpoint(usbus_t *usbus, usbus_interface_t *iface,
usb_ep_type_t type, usb_ep_dir_t dir,
size_t len)

View File

@ -12,7 +12,6 @@ USEMODULE += ps
# Boards that don't have enough endpoints to use CDC ACM together with CDC ECM
ifeq (,$(filter stdio_%,$(filter-out stdio_cdc_acm,$(USEMODULE))))
BOARD_BLACKLIST += \
stm32f429i-disco \
stm32f4discovery \
weact-f401cc \
weact-f401ce \