USBX

1 Introduction

Besides offering STMicroelectronics USB stack, USBX, the Azure RTOS USB embedded stack is currently supported and offered with a set of applications running on STM32 MCUs.
The USB overview is a dedicated wiki page that provides a general overview of the Universal Serial Bus and its main features.
USBX is the Azure RTOS USB Host and USB Device embedded stack. It is tightly coupled with ThreadX. In some classes, it requires the FileX and NetX Duo stacks. It allows operation with USB devices with multiple configurations, composite devices, USB OTG, and supports USB power management.
USBX provides both USB Host and USB Device stacks with a large set of USB classes. The modular architecture makes porting onto different USB hardware IPs easier as soon as the low-level driver can answer the USBX requests.

All the STM32's USB IPs (Host, Device, OTG, High Speed, Full Speed) are supported transparently by USBX through the common STM32 HAL driver API.

Info.png The bare metal implementation is to be made available in the future (that is, using USBX without need for ThreadX).


USBX provides all common USB features and classes. The following figure provides the list of currently supported classes:

USBX supported classes


Info.png HUB class is to be made available in the future on specific products.


Besides ThreadX integration with USBX, the USB events are managed through interrupts.
The USBX stack has mainly three layers:

  • The lower layer is the controller layer that ensures interfacing with the Hardware USB peripheral, and for STM32 MCUs this layer is compatible with the HAL.
  • The middle layer ensures the USB stack processing and the interfacing requirements between the low and high layers.
  • The higher layer includes the different classes and ensures interfacing with the application layer.

The following figure provides an overview of the USBX three-layer architecture and main components.

USBX layers and components overeview

As presented in the following figure, the different layers can be easily found within the USBX folder.

USBX Folder architecture overview

For more details, please refer to Azure RTOS USBX documentation.

2 USBX device for STM32

This section provides the main guidelines for use of the USBX Stack with the HAL on STM32 MCUs.

2.1 STM32 Device Porting layer

As described in the previous section, USBX is based on three layers that must be referenced within any application project. To be able to interface with the STM32 HAL, the project must integrate the STM32 device controllers. The drivers presented in the figure below include all the APIs allowing interfacing with the STM32 HAL.

USBX STM32 Device Controllers

2.2 How to customize

After referencing the required drivers, and depending on the class and application requirements, the following points must be verified:
1. Add the convenient Descriptors: the device descriptor, configuration descriptor, interface descriptor, endpoint descriptor and the Strings (Language ID, Product ID, and Vendor ID, manufacturer, and so on). The following figure shows some of the required definitions for the HID class:

Example of required definitions for HID application


Info.png For reference, all the required descriptors can be found in the ux_device_descriptors.c/.h files within the provided STM32 HID device application.


2. Add the Class parameters: every class needs to interface with the user application through some variables or functions. Thus, for every class, there is a structure that must be filled before registering the class. As an example for the HID application, the following structure must be filled in order to be able to register the class:

HID class required parameters

3. Customize the USBX build options by modifying the status of the different conditional compilation defines in ux_user.h, file such as: • USBX thread stack size
• The maximum class number that can be loaded by USBX
• The maximum number of devices that can be attached into one USB system
• Maximum number of endpoints
• The device used class(es)
• The device state side use

4. Depending on the application requirements, all required peripherals and resources (UART, I2C, and so on) must be initialized generally in the stm32XXxx_hal_msp.c file (XX is the family name, for example h7, f7).

Info.png To make sure that all the customized defines in the ux_user.h file are taken into consideration, the UX_INCLUDE_USER_DEFINE_FILE should be added within the preprocessor defined symbols.


When configuring the project using STM32CubeMX and the X-CUBE-AZRTOS-XX package, a list of variables can be customized through the interface before generating a device application.

USBX parameters definition

To see the role of every variable, just click on it and a little window shows the description. For instance, "USBD_DEVICE_FRAMEWORK_BUILDER" allows the device framework builder to be enabled or disabled.

Parameter information example

2.3 How to use the USBX Device stack to implement an application

1. To start the USBX application, ThreadX must be initialized as described in How to use ThreadX section.
2. Initialize the USBX controller data structures and allocate the required memory.

  /* Initialize USBX Memory & data structures */
  ux_system_initialize(pointer, USBX_MEMORY_SIZE, UX_NULL, 0);

3. Prepare the Device, string and LangID frameworks.

  /* Get_Device_Framework_High_Speed and get the length */
  device_framework_high_speed = USBD_Get_Device_Framework_Speed(USBD_HIGH_SPEED,
                                &device_framework_hs_length);

  /* Get_Device_Framework_Full_Speed and get the length */
  device_framework_full_speed = USBD_Get_Device_Framework_Speed(USBD_FULL_SPEED,
                                &device_framework_fs_length);

  /* Get_String_Framework and get the length */
  string_framework = USBD_Get_String_Framework(&string_framework_length);

  /* Get_Language_Id_Framework and get the length */
  language_id_framework = USBD_Get_Language_Id_Framework(&languge_id_framework_length);

Note: the descriptors must be implemented at application level to be provided as parameters when initializing the stack. For reference, all the required descriptors can be found in the ux_device_descriptors.c/.h files within every provided STM32 device application.
4. Initialize the USBX device stack with the prepared frameworks.

  /* The code below is required for installation of the device portion of USBX.
  in this application */
  ret =  ux_device_stack_initialize(device_framework_high_speed,
                                    device_framework_hs_length,
                                    device_framework_full_speed,
                                    device_framework_fs_length,
                                    string_framework,
                                    string_framework_length,
                                    language_id_framework,
                                    languge_id_framework_length, UX_NULL);

5. Initialize the device class parameters and register the class.

  /* Initialize the device class. The class is connected with interface 0 in this case */
  ret = ux_device_stack_class_register(_ux_system_slave_class_xxxx_name,
                                       ux_device_class_xxxx_entry, 1, 0, (VOID *)&class_xxxx_parameter);

6. Initialize the USB hardware peripheral and start the controller.
7. Implement the required applications tasks using Threads or Message Queue as explained in How to use ThreadX section.

Info.png The bare metal implementation is to be made be available in the future (ie. to make possibe the use of USBX without need for ThreadX).


2.4 USBX device applications

This section provides an overview of the USBX Device applications offered on STM32 MCUs.

2.4.1 USBX Device application architecture

The Following figure shows the project architecture and main application files.

USBX Application’s main files architecture

2.4.2 USBX device application overview

The following table provides an overview about the offered USBX Device applications:

USBX Device application Overview
HID Application This application makes the STM32 emulate a mouse USB device. When connected to a host through its USB peripheral, The STM32 is detected as an STM32 HID Mouse. The cursor moves automatically. For more details, please refer to the applications Readme file.

This application was implemented according to the Device Class Definition for Human Interface Devices (HID) specification.

MSC application This application makes the STM32 emulate a Flash disc device. When connected to a host through its USB peripheral, the STM32 is detected as an STM32 mass storage device. The device can then be written, read and formatted. For more details, please refer to the application’s Readme file.

This application was implemented according to the Universal Serial Bus Mass Storage Class specification.

CDC ACM application This application makes the STM32 emulate an UART-USB Bridge. When connected to a host through its USB peripheral, The STM32 will be detected as an STM32 Virtual Com port. An HyperTerminal can be opened with the detected port and a communication can be established between the STM32 Virtual comport and the STM32 ST-link (UART) port. For more details, please refer to the application’s Readme file.

This application was implemented according to the Class definitions for Communication Devices specification.

Ux_Device_HID_CDC_ACM This application provides an example of Azure RTOS USBX stack usage on STM32H747I_Discovery board, it shows how to develop a composite USB Device communication Class "HID" and "CDC_ACM" based application. The application is designed to emulate an USB HID mouse device and USB-to-UART bridge following the Virtual COM Port (VCP) implementations.

For more details, please refer to the application’s Readme file.

CDC ECM application This application shows how to implement an application to run Web HTTP server stack over a USB interface using the CDC-ECM class. When an SD card is inserted into the STM32 board's SD-card reader and the board is powered up and connected to a DHCP-enabled Ethernet network, the green LED switches ON when Web HTTP server is successfully started. For further details, please refer to the application’s Readme file.


3 USBX Host for STM32

This section provides the main guidelines allowing use of the USBX Host Stack with the HAL on STM32 MCUs.

3.1 STM32 Host porting layer

As described in the previous section, the USBX stack is based on three layers that must referenced within any application project. To be able to interface with the STM32 HAL, the project must integrate the STM32 Host controllers interfacing with the HAL layer. The drivers presented in the figure below include all the APIs allowing interfacing with the STM32 HAL.

STM32 Host Controller drivers

3.2 How to customize


1. Customize the USBX build options by modifying the status of the different conditional compilation defines in the ux_user.h file, such as: • USBX thread stack size
• The maximum class number that can be loaded by USBX
• The maximum number of devices that can be attached into one USB system
• The maximum number of endpoint
• The host used class(es)
• The host state side use
2. Depending on the application requirements, the different peripherals and clocks should be correctly defined. Generally, the different peripheral IO initializations are done in the stm32XXxx_hal_msp.c (XX is the STM32 family that can be, for example, h7, f4, or f7).

Info.png To make sure that all the customized defines in the ux_user.h file are taken into consideration, the "UX_INCLUDE_USER_DEFINE_FILE" should be added within the preprocessor defined symbols.

When configuring the project using STM32CubeMX and the X-CUBE-AZRTOS-XX package, a list of variables can be customized through the interface before generating a host application.

USBX Host parameters definition

To see the role of every variable, just click on it and a little window shows the description.

3.3 How to use the USBX Host stack to implement an application

1. To start the USBX application, ThreadX must be initialized as described in How to use ThreadX section.
2. Initialize USBX’ different data structures to be used by the USB system.

  /* Initialize USBX memory. */
  if (ux_system_initialize(pointer, USBX_MEMORY_SIZE, UX_NULL, 0) != UX_SUCCESS)
  {
    ret = UX_ERROR;
  }

3. Register an error callback function to be able to get the error events at application level (this step is optional). This callback is called when an error occurs at thread level or at interrupt level. It can be called to inform the user of the error codes that can be related to the host controller, the device controller, the initialization, the class, the device stack, and so on.

  /* register a callback error function */
  _ux_utility_error_callback_register(&ux_host_error_callback);

4. Initialize the USB Host stack

  /* The code below is required for installing the host portion of USBX.  */
  if (ux_host_stack_initialize(ux_host_event_callback) != UX_SUCCESS)
  {
    status = UX_ERROR;
  }

Device status check: in fact, ux_host_stack_initialize() is the function that allows the initialization of the USB host stack, it takes a change event callback as a parameter, allowing the user application to determine whether the device status if defined. In fact this callback, if required, should be defined at application level. It is called when the device status is modified (inserted, removed, and so on) allowing the user to perform the required process following that event.
5. Register the class

  /* Register the convenient class. */
  if ((status =  ux_host_stack_class_register(_ux_system_host_class_xxxx_name,
                                              _ux_host_class_xxxx_entry)) != UX_SUCCESS)
  {
    status = UX_ERROR;
  }

6. Initialize the USB hardware peripheral.
7. Register all the available USB Host controllers with the USBX stack.

  /* Register all the USB host controllers available in this system. */
  if (ux_host_stack_hcd_register(_ux_system_host_hcd_stm32_name,
                                 _ux_hcd_stm32_initialize,
                                 USB_OTG_HS_PERIPH_BASE,
                                 (ULONG)&hhcd_USB_OTG_HS) != UX_SUCCESS)
  {
    status = UX_ERROR;
  }

7. Define and create the application required Threads or Message Queue.
8. Start the USB Host controller.

3.4 USBX Host applications

This section provides an overview of the offered USBX Device application.

3.4.1 USBX Host application architecture

The following figure shows the USB Host application main files and architecture.

USBX Host Application’s main files architecture

3.4.2 USBX Host application overview

The following table provides an overview of the offered USBX Device applications:

USBX Host application Overview
HID Application This application makes the STM32 emulate a USB HID Host that can enumerate and communicate with mice and keyboards. When an HID device (mouse or keyboard) is connected to a host through its USB peripheral, the STM32 detects it, recognizes its types and receives data in real time:
  • If a mouse device is connected, the pressed buttons, wheel movements and the modified cursor coordinates are detected and displayed.
  • If a keyboard device is connected, the pressed buttons are detected and displayed.

For further details, please refer to the application’s Readme file.

MSC Application This application makes the STM32 emulate a USB mass storage Host that can enumerate and communicate with Flash disk USB devices. When a Mass Storage is connected to the STM32 host through its USB peripheral, the STM32 detects the Device, enumerate it, create a file, write and read data and check the data integrity. For more details, please refer to the application’s Readme file.
Dual Class Application This application provides an example of Azure RTOS USBX stack usage. It shows how to develop a USB Host human interface "HID" and mass storage "MSC" that enumerates and communicates with:
  • A mouse or a keyboard.
  • A removable USB flash disk

For further details, please refer to the application’s Readme file.

CDC ACM Application This application provides an example of an STM32 USB Host CDC. When a CDC device is plugged into the STM32 Host board through an available port, a message is displayed on the UART HyperTerminal showing some information about the attached device. After the enumeration phase, the Host must be able to properly decode the CDC_ACM class request, and receive and send (from/to) the device.

For further details, please refer to the application’s Readme file.