usb: device_next: Reduce code size on Full-Speed only configuration

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ń <tomasz.mon@nordicsemi.no>
This commit is contained in:
Tomasz Moń 2024-09-04 08:19:32 +02:00 committed by Benjamin Cabé
commit b3eb6f2d11
19 changed files with 104 additions and 59 deletions

View file

@ -37,6 +37,12 @@ extern "C" {
* @{
*/
/* 1 if USB device stack is compiled with High-Speed support */
#define USBD_SUPPORTS_HIGH_SPEED IS_EQ(CONFIG_USBD_MAX_SPEED, 1)
/* Maximum bulk max packet size the stack supports */
#define USBD_MAX_BULK_MPS COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64))
/*
* The USB Unicode bString is encoded in UTF16LE, which means it takes up
* twice the amount of bytes than the same string encoded in ASCII7.

View file

@ -126,7 +126,8 @@ struct usbd_context *sample_usbd_setup_device(usbd_msg_cb_t msg_cb)
}
/* doc add string descriptor end */
if (usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) {
err = usbd_add_configuration(&sample_usbd, USBD_SPEED_HS,
&sample_hs_config);
if (err) {

View file

@ -68,13 +68,13 @@ static K_FIFO_DEFINE(bt_hci_tx_queue);
/*
* Transfers through three endpoints proceed in a synchronous manner,
* with maximum packet size of high speed bulk endpoint.
* with maximum packet size of max supported speed bulk endpoint.
*
* REVISE: global (bulk, interrupt, iso) specific pools would be more
* RAM usage efficient.
*/
UDC_BUF_POOL_DEFINE(bt_hci_ep_pool,
3, 512,
3, USBD_MAX_BULK_MPS,
sizeof(struct udc_buf_info), NULL);
/* HCI RX/TX threads */
static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE);
@ -138,7 +138,8 @@ static uint8_t bt_hci_get_bulk_in(struct usbd_class_data *const c_data)
struct bt_hci_data *data = usbd_class_get_private(c_data);
struct usbd_bt_hci_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_in_ep.bEndpointAddress;
}
@ -151,7 +152,8 @@ static uint8_t bt_hci_get_bulk_out(struct usbd_class_data *const c_data)
struct bt_hci_data *data = usbd_class_get_private(c_data);
struct usbd_bt_hci_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_out_ep.bEndpointAddress;
}
@ -449,7 +451,7 @@ static void *bt_hci_get_desc(struct usbd_class_data *const c_data,
{
struct bt_hci_data *data = usbd_class_get_private(c_data);
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return data->hs_desc;
}

View file

@ -254,7 +254,7 @@ static void *lb_get_desc(struct usbd_class_data *const c_data,
{
struct lb_data *data = usbd_class_get_private(c_data);
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return data->hs_desc;
}

View file

@ -36,7 +36,7 @@ LOG_MODULE_REGISTER(usbd_cdc_acm, CONFIG_USBD_CDC_ACM_LOG_LEVEL);
UDC_BUF_POOL_DEFINE(cdc_acm_ep_pool,
DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 2,
512, sizeof(struct udc_buf_info), NULL);
USBD_MAX_BULK_MPS, sizeof(struct udc_buf_info), NULL);
#define CDC_ACM_DEFAULT_LINECODING {sys_cpu_to_le32(115200), 0, 0, 8}
#define CDC_ACM_DEFAULT_INT_EP_MPS 16
@ -171,7 +171,8 @@ static uint8_t cdc_acm_get_int_in(struct usbd_class_data *const c_data)
const struct cdc_acm_uart_config *cfg = dev->config;
struct usbd_cdc_acm_desc *desc = cfg->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_int_ep.bEndpointAddress;
}
@ -185,7 +186,8 @@ static uint8_t cdc_acm_get_bulk_in(struct usbd_class_data *const c_data)
const struct cdc_acm_uart_config *cfg = dev->config;
struct usbd_cdc_acm_desc *desc = cfg->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if1_hs_in_ep.bEndpointAddress;
}
@ -199,7 +201,8 @@ static uint8_t cdc_acm_get_bulk_out(struct usbd_class_data *const c_data)
const struct cdc_acm_uart_config *cfg = dev->config;
struct usbd_cdc_acm_desc *desc = cfg->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if1_hs_out_ep.bEndpointAddress;
}
@ -210,7 +213,8 @@ static size_t cdc_acm_get_bulk_mps(struct usbd_class_data *const c_data)
{
struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return 512U;
}
@ -350,7 +354,7 @@ static void *usbd_cdc_acm_get_desc(struct usbd_class_data *const c_data,
const struct device *dev = usbd_class_get_private(c_data);
const struct cdc_acm_uart_config *cfg = dev->config;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return cfg->hs_desc;
}

View file

@ -106,7 +106,8 @@ static uint8_t cdc_ecm_get_int_in(struct usbd_class_data *const c_data)
struct cdc_ecm_eth_data *data = dev->data;
struct usbd_cdc_ecm_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_int_ep.bEndpointAddress;
}
@ -120,7 +121,8 @@ static uint8_t cdc_ecm_get_bulk_in(struct usbd_class_data *const c_data)
struct cdc_ecm_eth_data *data = dev->data;
struct usbd_cdc_ecm_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if1_1_hs_in_ep.bEndpointAddress;
}
@ -131,7 +133,8 @@ static uint16_t cdc_ecm_get_bulk_in_mps(struct usbd_class_data *const c_data)
{
struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return 512U;
}
@ -145,7 +148,8 @@ static uint8_t cdc_ecm_get_bulk_out(struct usbd_class_data *const c_data)
struct cdc_ecm_eth_data *data = dev->data;
struct usbd_cdc_ecm_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if1_1_hs_out_ep.bEndpointAddress;
}
@ -475,7 +479,7 @@ static void *usbd_cdc_ecm_get_desc(struct usbd_class_data *const c_data,
const struct device *dev = usbd_class_get_private(c_data);
struct cdc_ecm_eth_data *const data = dev->data;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return data->hs_desc;
}

View file

@ -249,7 +249,8 @@ static uint8_t cdc_ncm_get_int_in(struct usbd_class_data *const c_data)
struct cdc_ncm_eth_data *data = dev->data;
struct usbd_cdc_ncm_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_int_ep.bEndpointAddress;
}
@ -263,7 +264,8 @@ static uint8_t cdc_ncm_get_bulk_in(struct usbd_class_data *const c_data)
struct cdc_ncm_eth_data *data = dev->data;
struct usbd_cdc_ncm_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if1_1_hs_in_ep.bEndpointAddress;
}
@ -274,7 +276,8 @@ static uint16_t cdc_ncm_get_bulk_in_mps(struct usbd_class_data *const c_data)
{
struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return 512U;
}
@ -288,7 +291,8 @@ static uint8_t cdc_ncm_get_bulk_out(struct usbd_class_data *const c_data)
struct cdc_ncm_eth_data *data = dev->data;
struct usbd_cdc_ncm_desc *desc = data->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if1_1_hs_out_ep.bEndpointAddress;
}
@ -1009,7 +1013,7 @@ static void *usbd_cdc_ncm_get_desc(struct usbd_class_data *const c_data,
const struct device *dev = usbd_class_get_private(c_data);
struct cdc_ncm_eth_data *const data = dev->data;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return data->hs_desc;
}

View file

@ -479,7 +479,7 @@ static void *usbd_hid_get_desc(struct usbd_class_data *const c_data,
const struct device *dev = usbd_class_get_private(c_data);
const struct hid_device_config *dcfg = dev->config;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return dcfg->hs_desc;
}

View file

@ -344,7 +344,11 @@ static void *usbd_midi_class_get_desc(struct usbd_class_data *const class_data,
LOG_DBG("Get descriptors for %s", dev->name);
return (speed == USBD_SPEED_HS) ? config->hs_descs : config->fs_descs;
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return config->hs_descs;
}
return config->fs_descs;
}
@ -382,7 +386,8 @@ static uint8_t usbd_midi_get_bulk_in(struct usbd_class_data *const class_data)
const struct device *dev = usbd_class_get_private(class_data);
const struct usbd_midi_config *cfg = dev->config;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return cfg->desc->if1_1_in_ep_hs.bEndpointAddress;
}
@ -395,7 +400,8 @@ static uint8_t usbd_midi_get_bulk_out(struct usbd_class_data *const class_data)
const struct device *dev = usbd_class_get_private(class_data);
const struct usbd_midi_config *cfg = dev->config;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return cfg->desc->if1_1_out_ep_hs.bEndpointAddress;
}

View file

@ -61,7 +61,7 @@ struct CSW {
#define MSC_NUM_INSTANCES CONFIG_USBD_MSC_INSTANCES_COUNT
/* Can be 64 if device is not High-Speed capable */
#define MSC_BUF_SIZE 512
#define MSC_BUF_SIZE USBD_MAX_BULK_MPS
UDC_BUF_POOL_DEFINE(msc_ep_pool,
MSC_NUM_INSTANCES * 2, MSC_BUF_SIZE,
@ -149,7 +149,8 @@ static uint8_t msc_get_bulk_in(struct usbd_class_data *const c_data)
struct msc_bot_ctx *ctx = usbd_class_get_private(c_data);
struct msc_bot_desc *desc = ctx->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_in_ep.bEndpointAddress;
}
@ -162,7 +163,8 @@ static uint8_t msc_get_bulk_out(struct usbd_class_data *const c_data)
struct msc_bot_ctx *ctx = usbd_class_get_private(c_data);
struct msc_bot_desc *desc = ctx->desc;
if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
return desc->if0_hs_out_ep.bEndpointAddress;
}
@ -755,7 +757,7 @@ static void *msc_bot_get_desc(struct usbd_class_data *const c_data,
{
struct msc_bot_ctx *ctx = usbd_class_get_private(c_data);
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return ctx->hs_desc;
}

View file

@ -890,7 +890,7 @@ static void *uac2_get_desc(struct usbd_class_data *const c_data,
struct device *dev = usbd_class_get_private(c_data);
const struct uac2_cfg *cfg = dev->config;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
return cfg->hs_descriptors;
}

View file

@ -472,9 +472,11 @@ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx,
/*
* If the other-speed-configuration-descriptor is requested and the
* controller does not support high speed, respond with an error.
* controller (or stack) does not support high speed, respond with
* an error.
*/
if (other_cfg && usbd_caps_speed(uds_ctx) != USBD_SPEED_HS) {
if (other_cfg && !(USBD_SUPPORTS_HIGH_SPEED &&
(usbd_caps_speed(uds_ctx) == USBD_SPEED_HS))) {
errno = -ENOTSUP;
return 0;
}
@ -691,7 +693,8 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx,
* If the Device Qualifier descriptor is requested and the controller
* does not support high speed, respond with an error.
*/
if (usbd_caps_speed(uds_ctx) != USBD_SPEED_HS) {
if (!USBD_SUPPORTS_HIGH_SPEED ||
usbd_caps_speed(uds_ctx) != USBD_SPEED_HS) {
errno = -ENOTSUP;
return 0;
}

View file

@ -215,7 +215,7 @@ usbd_class_node_get(const char *name, const enum usbd_speed speed)
return c_nd;
}
}
} else if (speed == USBD_SPEED_HS) {
} else if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs,
usbd_class_node, c_nd) {
if (strcmp(name, c_nd->c_data->name) == 0) {
@ -358,7 +358,7 @@ int usbd_register_all_classes(struct usbd_context *const uds_ctx,
{
int ret;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) {
if (blocklist != NULL && is_blocklisted(c_nd, blocklist)) {
continue;
@ -430,7 +430,7 @@ int usbd_unregister_class(struct usbd_context *const uds_ctx,
/* TODO: The use of atomic here does not make this code thread safe.
* The atomic should be changed to something else.
*/
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs,
usbd_class_node, i) {
if ((i->c_data == c_nd->c_data) &&
@ -470,7 +470,7 @@ int usbd_unregister_all_classes(struct usbd_context *const uds_ctx,
{
int ret;
if (speed == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) {
ret = usbd_unregister_class(uds_ctx, c_nd->c_data->name,
speed, cfg);

View file

@ -266,6 +266,12 @@ int usbd_add_configuration(struct usbd_context *const uds_ctx,
goto add_configuration_exit;
}
if (speed == USBD_SPEED_HS && !USBD_SUPPORTS_HIGH_SPEED) {
LOG_ERR("Stack was compiled without High-Speed support");
ret = -ENOTSUP;
goto add_configuration_exit;
}
if (speed == USBD_SPEED_HS &&
usbd_caps_speed(uds_ctx) == USBD_SPEED_FS) {
LOG_ERR("Controller doesn't support HS");

View file

@ -228,6 +228,7 @@ int usbd_device_shutdown_core(struct usbd_context *const uds_ctx)
struct usbd_config_node *cfg_nd;
int ret;
if (USBD_SUPPORTS_HIGH_SPEED) {
SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->hs_configs, cfg_nd, node) {
uint8_t cfg_value = usbd_config_get_value(cfg_nd);
@ -236,6 +237,7 @@ int usbd_device_shutdown_core(struct usbd_context *const uds_ctx)
LOG_ERR("Failed to cleanup registered classes, %d", ret);
}
}
}
SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->fs_configs, cfg_nd, node) {
uint8_t cfg_value = usbd_config_get_value(cfg_nd);

View file

@ -45,7 +45,7 @@ static inline uint8_t usbd_get_num_configs(const struct usbd_context *const uds_
if (speed == USBD_SPEED_FS) {
desc = uds_ctx->fs_desc;
} else if (speed == USBD_SPEED_HS) {
} else if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
desc = uds_ctx->hs_desc;
} else {
return 0;
@ -70,7 +70,7 @@ static inline void usbd_set_num_configs(struct usbd_context *const uds_ctx,
if (speed == USBD_SPEED_FS) {
desc = uds_ctx->fs_desc;
} else if (speed == USBD_SPEED_HS) {
} else if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
desc = uds_ctx->hs_desc;
} else {
return;

View file

@ -281,6 +281,7 @@ int usbd_init_configurations(struct usbd_context *const uds_ctx)
usbd_init_update_fs_mps0(uds_ctx);
if (USBD_SUPPORTS_HIGH_SPEED) {
SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->hs_configs, cfg_nd, node) {
int ret;
@ -294,6 +295,7 @@ int usbd_init_configurations(struct usbd_context *const uds_ctx)
LOG_INF("HS bNumConfigurations %u",
usbd_get_num_configs(uds_ctx, USBD_SPEED_HS));
}
}
SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->fs_configs, cfg_nd, node) {
int ret;

View file

@ -147,7 +147,8 @@ static int register_classes(const struct shell *sh)
shell_print(sh, "dev: register FS %s", c_nd->c_data->name);
}
if (usbd_caps_speed(my_uds_ctx) != USBD_SPEED_HS) {
if (!USBD_SUPPORTS_HIGH_SPEED ||
usbd_caps_speed(my_uds_ctx) != USBD_SPEED_HS) {
return 0;
}

View file

@ -136,7 +136,8 @@ static void *usb_test_enable(void)
err = usbd_add_descriptor(&test_usbd, &test_sn);
zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err);
if (usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) {
err = usbd_add_configuration(&test_usbd, USBD_SPEED_HS, &test_hs_config);
zassert_equal(err, 0, "Failed to add configuration (%d)");
}
@ -144,7 +145,8 @@ static void *usb_test_enable(void)
err = usbd_add_configuration(&test_usbd, USBD_SPEED_FS, &test_fs_config);
zassert_equal(err, 0, "Failed to add configuration (%d)");
if (usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) {
if (USBD_SUPPORTS_HIGH_SPEED &&
usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) {
err = usbd_register_all_classes(&test_usbd, USBD_SPEED_HS, 1, NULL);
zassert_equal(err, 0, "Failed to unregister all instances(%d)");