USB Component  
MDK Middleware for USB Device and Host Communication
 
Loading...
Searching...
No Matches
Create an Application

The steps to create a microcontroller application that uses USB communication with an USB Device controller are:

  1. Select RTE Components along with the USB Device Classes that are required for your application.
  2. Enable and configure the USB Device Driver.
  3. Configure the USB Device that connects the USB Middleware to the microcontroller USB peripheral.
  4. Configure USB Device Class Configuration and USB Endpoint Settings for each selected USB Device Class and instance.
  5. Configure the System Resources according to the USB Device component's Resource Requirements.
  6. Implement the Application Code using code templates that are provided for the USB Device Classes.
  7. If required by your application, you can change the default USB Device descriptors.
  8. Debug you application using the built-in mechanisms of the USB Component.

For interfacing to an USB Host computer, standard USB Device Classes drivers can be used. This may require additional software development for the USB Host application. An exemplary application for interfacing to an USB HID Device is explained here.

RTE Component Selection

Only a few steps are necessary to complete the RTE Component selection:

  1. From the USB group:
    • Select USB:CORE component that provides the basic functionality required for USB communication.
    • Set USB:Device component instances to '1'. This creates one USB Device for communication with the USB Host.
    • Select the desired USB Classes (HID/MSC/CDC/Custom Class) components. For example, set USB:Device:HID component instances to '1' to create a single HID Class Device. If you select more than one class or multiple instances of the same class on the same device, you will create a Composite USB Device.
  2. From the CMSIS Driver group:
    • Select an appropriate USB Device driver component suitable for your microcontroller.
  3. From the Device group:
    • Select the target microcontroller device component.
    • Additional device specific driver components may be required according to the validation output.
  4. From the CMSIS group:
    • Select the CMSIS:CORE component to provide the core interface to the processor.
    • Select a suitable CMSIS:RTOS2 component that is required by the application.
RTE Component Selection
Note
  • Most microcontrollers have only one USB Controller implemented in hardware and only one driver Driver_USBD0 is available. In this case, only one USB:Device component can be selected to generate USB Device 0.
  • On a single USB Device 0 an USB Composite Device may be implemented that combines multiple USB Device Classes.
  • When a microcontroller implements multiple USB Controllers an additional USB Device 1 can be generated by setting USB:Device component instances to '2'.

USB Driver and Controller

The USB Device Driver and the USB Controller of the microcontroller need to be correctly configured. In particular this means:

  • The USB Device Driver selected under the Drivers group is typically configured with a driver specific configuration header file. Some microcontrollers may require settings that are related to a physical layer interface (PHY). The picture below shows two possible variants. Either, the USB PHY is integrated into the controller, or an external chip is used for providing the USB signal lines:
USB Controller and PHY Setups
  • The USB Controller of the microcontroller typically needs specific clock settings. Consult the user's guide of the microcontroller to understand the requirements. Alternatively you may copy the setup of a similar USB Device configuration provided for various evaluation boards (BSP).

USB Device Configuration

The configuration file USBD_Config_n.h contains a number of important settings for the specific USB Device.

  • The Driver_USBD# number is set according to the selected USB Controller. This specifies which driver will be used for the USB Device determining the pin-out as well. For devices with single USB Device Controller it will typically be '0'.
  • High-Speed may be selected if supported by the USB Controller.
  • The Vendor ID (VID) needs to be set to a private Vendor ID. The default Vendor ID is owned by Keil and must not be used for actual products. Please visit USB-IF for more information on how to apply for a valid Vendor ID.
  • Every device variant needs an unique Product ID. Together with the Vendor ID, it is used by the Host computer's operating system to find a driver for your device.
  • The Device Release Number will be shown in Windows and Linux systems as “Firmware Revision”. The number will be interpreted as “binary coded decimal”, meaning that 0x0101 will be shown as firmware revision 1.01.
  • The Manufacturer, Product and the Serial Number String can be set to identify the USB Device from the USB Host.

Refer to USB Core Configuration for more configuration options of the USB Device.

Note
You can configure the USB Device at run-time using the functions from the USB Device Core API. The section USB Device Core explains the details. Implement the run-time specific behavior with the user code template USBD_User_Device_n.c.

USB Device Class Configuration and USB Endpoint Settings

The USB Device Class Parameters and Endpoint Settings are configured in separate files for each USB Device Class and separately for each instance. The configuration files contain Device Class specific Endpoint Settings.

  • USBD_Config_ADC_n.h configuration for Audio Device Class (ADC).
  • USBD_Config_CDC_n.h configuration for Communication Device Class (CDC).
  • USBD_Config_HID_n.h configuration for Human Interface Device Class (HID).
  • USBD_Config_MSC_n.h configuration for Mass Storage Device Class (MSC).
  • USBD_Config_CustomClass_n.h configuration for Custom Class.

Each USB Endpoint can only be used once on the same USB Device. It has to be made sure that the different USB Device Classes or multiple instances of the same USB Device Class use different Endpoints. The default configuration supports applications that use a single USB Device Class. The remaining parameters are specific settings that configure parameters for USB communication speed and the USB Device Class.

System Resource Configuration

For proper operation, the USB Device Component requires some system configuration settings. The requirements are:

  • Additional main stack size of 512 bytes.
  • The USB Device Component uses CMSIS-RTOS2 threads. In case RTX v5 is used no changes to RTX settings are necessary as all resources are allocated statically.

For more information, check the USB Device component's Resource Requirements section.

User Code Implementation

files provide function templates used to implement USB Device Class functionality. The available functions are explained in the Reference section of the USB Component. These routines can be adapted to the needs of the microcontroller application, in case that functionality different then default is needed.

The following templates are available for the USB Device component:

Template Name Purpose
USBD_User_ADC_n.c Functions for an ADC device.
USBD_User_CDC_ACM_n.c Functions for a CDC (ACM) device.
USBD_User_CDC_ACM_RNDIS_VETH_n.c Functions for a CDC (ACM) RNDIS virtual Ethernet device.
USBD_User_CDC_ACM_RNDIS_ETH_n.c Functions for a CDC (ACM) RNDIS and Ethernet bridge device (Ethernet-over-USB).
USBD_User_CDC_ACM_UART_n.c Functions for a CDC (ACM) device demonstrating a USB <-> UART bridge.
USBD_User_CDC_NCM_n.c Functions for a CDC (NCM) device.
USBD_User_CDC_NCM_ETH_n.c Functions for a CDC (NCM) device (Ethernet-over-USB).
USBD_User_CustomClass_n.c Functions for a device supporting a custom USB Device class.
USBD_User_Device_n.c Functions for specific Control Endpoint 0 requests handling.
USBD_User_SerNum_n.c Example for specific Control Endpoint 0 requests handling: Changing the serial number of the USB Device.
USBD_User_HID_n.c Functions for a HID device.
USBD_User_HID_Mouse_n.c Example for a HID device acting as a mouse input device.
USBD_User_MSC_n.c Functions for a mass storage device.
USBD_MSC_n.c Shows how to get access to storage media either from the application/File System or from the USB host.

Changing Default USB Descriptors

If there are different requirements regarding the USB Descriptors, the USB Component allows that. A user can change any or all of the default USB descriptors. Default descriptors are the ones that library creates based on Device and Classes configuration file settings and are located in the code memory.

The descriptors can be changed in two of the following ways:

Static change

Static change of descriptors can be done to replace default descriptors if they will not change at run-time. The descriptors can be easily overridden by user code by creating descriptors with the same name.

USB Device Descriptor Purpose
const uint8_t usbdn_ep0_descriptor[] Control Endpoint 0 descriptor.
const uint8_t usbdn_device_descriptor[] USB Device descriptor.
const uint8_t usbdn_config_descriptor_fs[] Configuration descriptor for low/full-speed.
const uint8_t usbdn_config_descriptor_hs[] Configuration descriptor for high-speed.
const uint8_t usbdn_device_qualifier_fs[] Device qualifier for low/full-speed.
const uint8_t usbdn_device_qualifier_hs[] Device qualifier for high-speed.
const uint8_t usbdn_other_speed_config_descriptor_fs[] Other speed configuration descriptor for low/full-speed.
const uint8_t usbdn_other_speed_config_descriptor_hs[] Other speed configuration descriptor for high-speed.
Note
n in usbdn_ represents the USB Device instance. So for the USB Device 0 instance, you have to use usbd0_...
Only the String descriptors cannot be replaced this way.

Code Example

#include "rl_usb.h"
// Statically change USB Device 0 Device Descriptor
const uint8_t usbd0_device_descriptor[] = {
18U, // bLength = 18 bytes
1U, // bDescriptorType = 1 = Device Descriptor Type
0U,2U, // bcdUSB = 2.00 (little-endian)
0U, // bDeviceClass = 0 = Defined in interface
0U, // bDeviceSubClass = 0 = Defined in interface
0U, // bDeviceProtocol = 0 = Defined in interface
64U, // bMaxPacketSize = 64
0x51U,0xC2U, // idVendor = 0xC251 (little-endian)
0x34U,0x12U, // idProduct = 0x1234 (little-endian)
0U,1U, // bcdDevice = 1.00 (little-endian)
0U, // iManufacturer = 0 = No Manufacturer string
0U, // iProduct = 0 = No Product string
0U, // iSerialNumber = 0 = No Serial Number string
1U // bNumConfigurations = 1 = 1 configuration
};

Dynamic change

Dynamic change of descriptors can be used to change descriptors at run-time. The struct usbd_desc_t contains the required information. It is stored in RAM and contains pointers to the USB descriptors. If you change the pointers in the structure to point to the externally created ones, you effectively change the descriptors.

The structure usbdn_desc (n indicating the USB Device instance number) contains the pointers to the descriptors. The following code example shows how to override the device descriptor for the USB Device 0 (usbd0_desc):

Code Example

#include "rl_usb.h"
// Dynamically change USB Device 0 Device Descriptor
const uint8_t dev0_device_descriptor[] = {
18U, // bLength = 18 bytes
1U, // bDescriptorType = 1 = Device Descriptor Type
0U,2U, // bcdUSB = 2.00 (little-endian)
0U, // bDeviceClass = 0 = Defined in interface
0U, // bDeviceSubClass = 0 = Defined in interface
0U, // bDeviceProtocol = 0 = Defined in interface
64U, // bMaxPacketSize = 64
0x51U,0xC2U, // idVendor = 0xC251 (little-endian)
0x34U,0x12U, // idProduct = 0x1234 (little-endian)
0U,1U, // bcdDevice = 1.00 (little-endian)
0U, // iManufacturer = 0 = No Manufacturer string
0U, // iProduct = 0 = No Product string
0U, // iSerialNumber = 0 = No Serial Number string
1U // bNumConfigurations = 1 = 1 configuration
};
int main (void) {
...
usbd0_desc.device_descriptor = dev0_device_descriptor;
...
}
Note
For just changing the serial number string use the USBD_SetSerialNumber function.
For non high-speed capable device following descriptors are not important:

Debugging

USB Device Component is distributed in a source form and it allows direct code debug. However, with breakpoint stopping the program execution the USB Device will usually malfunction as USB Host will not be able to properly enumerate the device or communicate with it thus causing communication timeouts and failures. For such usage case a non-intrusive debug via the debug events is also provided (via Event Recorder).

USB_Debug.h configuration file is used to configure the level of debug events.

The USB Device:Debug Events describes the events implemented in the USB Device Component.

Event Recorder

is a powerful tool that provides visibility to the dynamic execution of the program.

The USB Device Component generates a broad set of Debug Events for the Event Recorder and implements required infrastructure to interface with it.

To use the Event Recorder it is required to create an image with event generation support. The necessary steps are:

  1. : in the RTE management dialog enable the software component CMSIS-View:Event Recorder.
  2. Ensure that Event Recorder is initialized preferably by if CMSIS-RTOS2 RTX v5 is used, or alternatively by calling the function in the application code.
  3. Event Recorder Configuration: if necessary, adjust default Event Recorder configuration.
  4. In USB_Debug.h enable USB Device event generation and configure event filters.
  5. Build the application code, download it to the target hardware and start a debug session.

Now, when the USB Device generates event information, it can be viewed in the .

Configuration

This section describes the configuration settings for the Event Recorder.

USB Event Generation Configuration

Selecting the USB:CORE will add the file USB_Debug.h to your project. Use this file to set the event generation configuration for USB core, drivers, and device classes separately. The file is common for USB Device and Host components.

USB_Debug.h file for event generation configuration

The following settings are available for event generation configuration of each module:

  • Off means no events will be generated by the module
  • Errors means only error events will be generated by the module
  • Errors + API means error and API call events will be generated by the module
  • All means all available events will be generated by the module. Besides error and API call events, this contains operation and detailed events.

Event IDs

The USB Device component uses the following event IDs:

Component Event ID
USBD_Core 0xA0
USBD_Driver 0xA1
USBD_CC 0xA2
USBD_ADC 0xA3
USBD_CDC 0xA4
USBD_HID 0xA5
USBD_MSC 0xA6