Application template
The redesigned USB stack makes the composite device application easy to implement and aligned with the general device.
Application structure template
For a general device, a demo contains only one class. However, for the composite device, a demo contains more than one class. Likewise, a structure is required to manage the application involving more than one class.
typedef struct composite_device_struct
{
usb_device_handle deviceHandle;
class_handle_t classHandle1;
class_handle_t classHandle2;
…
class_handle_t classHandlen;
uint8_t speed;
uint8_t attach;
uint8_t currentConfiguration;
uint8_t currentInterfaceAlternateSetting[USB_COMPOSITE_INTERFACE_COUNT];
}composite_device_struct_t;
deviceHandle: The handle pointer to a device, which is returned by the USB_DeviceClassInit.
speed: Speed of the USB device. USB_SPEED_FULL/USB_SPEED_LOW/USB_SPEED_HIGH.
attach: Indicates whether the device is attached or not.
currentConfiguration: The current device configuration value.
currentInterfaceAlternateSetting: The current alternate setting for each interface.
classHandlen: The pointer to a class.
This is an example for a composite device HID mouse + HID keyboard:
This structure is in the “composite.h” file.
Prototype:
typedef struct _usb_device_composite_struct
{
usb_device_handle deviceHandle;
class_handle_t hidMouseHandle;
class_handle_t hidKeyboardHandle;
uint8_t speed;
uint8_t attach;
uint8_t currentConfiguration;
uint8_t currentInterfaceAlternateSetting[USB_COMPOSITE_INTERFACE_COUNT];
} usb_device_composite_struct_t;
Parent topic:Application template
Application initialization process
Before initializing the USB stack by calling the USB_DeviceClassInit function, the usb_device_class_config_list_struct_t and usb_device_class_config_struct_t are assigned values respectively. For example, for MSC + CDC, the steps are as follows:
Declare the g_compositeDeviceConfigList as global variables of the type usb_device_class_config_list_struct_t.
usb_device_class_config_list_struct_t g_compositeDeviceConfigList = { g_compositeDevice, USB_DeviceCallback, 2, };
Declare the g_compositeDevice as global variables of the type usb_device_class_config_struct_t.
usb_device_class_config_struct_t g_compositeDevice[2] = { { USB_DeviceCdcVcomCallback, (class_handle_t)NULL, &g_UsbDeviceCdcVcomConfig, }, { USB_DeviceMscCallback, (class_handle_t)NULL, &g_mscDiskClass, } };
Add a function for the USB device ISR.
For EHCI,
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) void USBHS_IRQHandler(void) { USB_DeviceEhciIsrFunction(g_composite.deviceHandle); } #endif
For KHC1,
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U) void USB0_IRQHandler(void) { USB_DeviceKhciIsrFunction(g_composite.deviceHandle); } #endif
For LPC IP3511,
#if defined(USB_DEVICE_CONFIG_LPC3511IP) && (USB_DEVICE_CONFIG_LPC3511IP > 0U) void USB0_IRQHandler(void) { USB_DeviceLpc3511IpIsrFunction (g_composite.deviceHandle); } #endif
Enable the USB device clock.
For EHC1,
CLOCK_EnableUsbhs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk)); USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ);
For KHC1,
#if ((defined FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED) && (FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED)) CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, 48000000U); #else CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk)); #endif /* FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED */
For LPC IP3511,
CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcFro, CLOCK_GetFreq(kCLOCK_FroHf));
Call the USB_DeviceClassInit function.
if (kStatus_USB_Success != USB_DeviceClassInit(CONTROLLER_ID, &g_compositeDeviceConfigList, &g_composite.deviceHandle)) { usb_echo("USB device composite demo init failed\r\n"); return; } else { usb_echo("USB device composite demo\r\n"); …… }
Get a handle for each class. For example,
CDC virtual com:
g_composite.cdcVcom.cdcAcmHandle = g_compositeDeviceConfigList.config[0].classHandle;
MSC ramdisk:
g_composite.mscDisk.mscHandle = g_compositeDeviceConfigList.config[1].classHandle;
Initialize each class application.
Such as,
CDC virtual com:
USB_DeviceCdcVcomInit(&g_composite);
MSC ramdisk:
USB_DeviceMscDiskInit(&g_composite);
Set the interrupt priority and enable the USB device interrupt
NVIC_SetPriority((IRQn_Type)irqNo, USB_DEVICE_INTERRUPT_PRIORITY); NVIC_EnableIRQ((IRQn_Type)irqNo);
Enable the USB device funtionally:
USB_DeviceRun(g_composite.deviceHandle);
Parent topic:Application template