How to initialize USBX

This page explains USBX initialization in two integration models:

  • without STM32CubeMX2, using direct USBX APIs and the STM32 controller layers

  • with STM32CubeMX2, using the generated mx_usbx_* files and the settings selected in the USBX panels

How to initialize USBX without STM32CubeMX2

Without STM32CubeMX2, the application drives the initialization order directly.

Common initialization sequence

The common USBX startup flow is:

  1. Allocate the USBX memory pool for internal objects, descriptors, queues, and transfers.

  2. Call ux_system_initialize() .

  3. Initialize the selected device stack, host stack, or both.

  4. Register the required device classes or host classes.

  5. Bind the STM32 controller layer.

  6. Start the application loop, task, or callback path that uses USBX.

The core USBX entry point is:

status = ux_system_initialize(usb_memory,
                              usb_memory_size,
                              UX_NULL,
                              0);

This call initializes the global USBX services and prepares the middleware memory pool.

Device-mode initialization

For device mode, a manual initialization flow typically looks like this:

status = ux_system_initialize(usb_memory, usb_memory_size, UX_NULL, 0);

status = ux_device_stack_initialize(high_speed_framework,
                                    high_speed_framework_length,
                                    full_speed_framework,
                                    full_speed_framework_length,
                                    string_framework,
                                    string_framework_length,
                                    language_id_framework,
                                    language_id_framework_length,
                                    device_change_callback);

status = ux_device_stack_class_register(class_name,
                                        class_entry,
                                        configuration_number,
                                        interface_number,
                                        class_parameter);

After the device stack is initialized, connect the STM32 device controller layer. In the STM32 USBX middleware, that bridge is implemented by interfaces/usbx_stm32_device_controllers and uses the STM32 DCD entry points such as ux_dcd_stm32_initialize() .

If the project uses STM32 reference descriptors, the device-descriptor content comes from interfaces/usbx_stm32_device_descriptors .

Host-mode initialization

For host mode, a manual initialization flow typically looks like this:

status = ux_system_initialize(usb_memory, usb_memory_size, UX_NULL, 0);

status = ux_host_stack_initialize(host_change_callback);

status = ux_host_stack_class_register(class_name,
                                      class_entry);

status = ux_host_stack_hcd_register(hcd_name,
                                    ux_hcd_stm32_initialize,
                                    hcd_param1,
                                    hcd_param2);

After the host stack is initialized, the STM32 HCD bridge from interfaces/usbx_stm32_host_controllers handles the controller-specific attach, port-state, and transfer management path.

Dual-role projects

If the project enables both roles, initialize USBX once with ux_system_initialize() , then initialize the device-side and host-side stacks in the order required by the application architecture. Keep the selected USB instances, descriptors, and memory budget coherent across both roles.

Execution model considerations

In No OS mode:

  • USBX runs in standalone mode.

  • The application remains responsible for the periodic processing path.

  • The generated or manual non-RTOS flow typically routes through app_usbx_process() and the USBX task-run APIs.

In FreeRTOS mode:

  • USBX can use middleware threads for enumeration, class processing, and the selected controller layers.

  • Device and host application threads can be generated separately.

  • Thread priorities and stack sizes must stay aligned with the selected class mix and controller load.

How to initialize USBX with STM32CubeMX2

With STM32CubeMX2, USBX initialization is driven by the configuration panels and the generated application files.

Generated application files

The generated USBX application layer is organized around a small set of common files plus optional role-specific files:

  • mx_usbx_app.c

  • mx_usbx_app.h

  • mx_usbx_device.c and mx_usbx_device.h when device init-code generation is available for the selected configuration

  • mx_usbx_host.c and mx_usbx_host.h when host init-code generation is available for the selected configuration

  • class-specific source files for the enabled device or host classes

These files are generated from the pack templates stored under middleware/usbx/.config/template . The templates themselves are not copied into the user application. STM32CubeMX2 evaluates the template set and writes the resulting mx_usbx_* source and header files into the generated project.

The common generated entry points are:

  • app_usbx_init() in mx_usbx_app.c and declared in mx_usbx_app.h

  • app_usbx_deinit() in mx_usbx_app.c and declared in mx_usbx_app.h

  • app_usbx_process() in mx_usbx_app.c and declared in mx_usbx_app.h for No OS projects

The role-specific generated entry points are:

  • app_usbx_device_init() and app_usbx_device_deinit() in mx_usbx_device.c and declared in mx_usbx_device.h

  • app_usbx_device_process() in mx_usbx_device.c and declared in mx_usbx_device.h for No OS projects

  • app_usbx_host_init() and app_usbx_host_deinit() in mx_usbx_host.c and declared in mx_usbx_host.h

  • app_usbx_host_process() in mx_usbx_host.c and declared in mx_usbx_host.h for No OS projects

The generated header also carries the device and host application thread names, stack sizes, and priorities when the RTOS path is enabled.

Read the generated files in this order: mx_usbx_app for the common memory pool and entry points, then mx_usbx_device or mx_usbx_host when role-specific init code is available, then the class-specific files that carry user callbacks, report descriptors, class-local buffers, and class-specific helper functions. The class registration calls are emitted in mx_usbx_device.c or mx_usbx_host.c , not in the class-specific files. Generated initialization is only a starting point, so the class callbacks, descriptors, storage handling, and board wiring must still match the real product behavior.

Dependencies required before generated initialization can work

Before relying on generated startup code, confirm these prerequisites:

  • No OS projects must call app_usbx_process() regularly in the main execution path

  • FreeRTOS projects must enable the RTOS middleware and the advanced APIs checked by the UI

  • device mode needs at least one enabled device class, a valid device descriptor strategy, HAL PCD support, and a USB peripheral configured in device mode

  • host mode needs at least one enabled host class, HAL HCD support, and a USB peripheral configured in host mode

  • host MSC needs either FileX integration or the no-FileX storage path

Generated initialization behavior

The generated flow depends on the selected execution mode.

In No OS mode:

  • the generated application layer provides app_usbx_process() in mx_usbx_app.c

  • role-specific standalone hooks such as app_usbx_device_process() and app_usbx_host_process() are emitted in mx_usbx_device.c and mx_usbx_host.c when the corresponding role is enabled

  • initialization remains explicit across mx_usbx_app.c and the enabled role-specific file

  • the application is still responsible for calling the process path at the required cadence

In FreeRTOS mode:

  • the generated application layer uses the configured thread names, priorities, and stack sizes from mx_usbx_app.h

  • the role-specific application thread settings are meaningful only for the roles that are enabled

  • the role-specific registration and controller hookup still live in mx_usbx_device.c and mx_usbx_host.c when those role files are generated

  • the project must still satisfy the role, class, controller, and board-level prerequisites selected in the configuration pages

Initialization explained

The initialization panel shown above is the part of STM32CubeMX2 that directly controls the generated initialization.

  • How to use this view: start here and confirm that the USBX middleware is enabled before reviewing the initialization settings. This is the entry point that opens the USBX configuration tree.

Role-dependent prerequisites

Before relying on generated initialization, verify that:

  • device mode has a valid device descriptor strategy and a selected USB device instance

  • host mode has a valid host-controller instance

  • the selected device and host classes match the enabled controller role

  • the project memory budget covers the USBX system stack size and the selected thread stacks

Typical bring-up checks

Before considering USBX initialized, verify:

  • ux_system_initialize() receives a valid memory pool

  • the descriptor arrays and language tables are valid for device mode

  • the selected device classes or host classes are registered before traffic starts

  • the STM32 PCD or HCD bridge is bound to the correct USB instance

  • FreeRTOS-only generated settings are not relied on in No OS projects