mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge #19438
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:
commit
f797bbee2e
@ -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[] = {
|
||||
{
|
||||
|
@ -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"
|
||||
|
@ -1,3 +1,7 @@
|
||||
ifneq (,$(filter periph_usbdev,$(USEMODULE)))
|
||||
USEMODULE += periph_usbdev_hs
|
||||
endif
|
||||
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
USEMODULE += l3gxxxx
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user