USBD ROM Stack  2.0
ROM based USB device stack
How to implement simple CDC device ?

This section introduces you to CDC (Communications Device Class) application development using USB ROM stack. The topics in this section provide step-by-step instructions on implementing a simple CDC class USB device using USB ROM stack.

Initialization

After successfully initializing the USBD ROM stack i.e. USBD_HW_API_T::Init, the CDC class driver needs to be initialized as follows:

Defining USB Descriptors

The following example shows the configuration descriptor for the USB CDC class device:

/*
* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor)
*/
ALIGNED(4) uint8_t USB_FsConfigDescriptor[] = {
/* Configuration 1 */
USB_CONFIGURATION_DESC_SIZE, /* bLength */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL( /* wTotalLength */
USB_CONFIGURATION_DESC_SIZE +
USB_INTERFACE_ASSOC_DESC_SIZE + /* interface association descriptor */
USB_INTERFACE_DESC_SIZE + /* communication control interface */
0x0013 + /* CDC functions */
1 * USB_ENDPOINT_DESC_SIZE + /* interrupt endpoint */
USB_INTERFACE_DESC_SIZE + /* communication data interface */
2 * USB_ENDPOINT_DESC_SIZE + /* bulk endpoints */
0
),
0x02, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
USB_CONFIG_SELF_POWERED, /* bmAttributes */
USB_CONFIG_POWER_MA(500), /* bMaxPower */
/* Interface association descriptor IAD*/
USB_INTERFACE_ASSOC_DESC_SIZE, /* bLength */
USB_CDC_CIF_NUM, /* bFirstInterface */
0x02, /* bInterfaceCount */
CDC_COMMUNICATION_INTERFACE_CLASS, /* bFunctionClass */
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */
0x00, /* bFunctionProtocol */
0x04, /* iFunction */
/* Interface 0, Alternate Setting 0, Communication class interface descriptor */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_CDC_CIF_NUM, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoint used */
CDC_COMMUNICATION_INTERFACE_CLASS, /* bInterfaceClass: Communication Interface Class */
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass: Abstract Control Model */
0x00, /* bInterfaceProtocol: no protocol used */
0x04, /* iInterface: */
/* Header Functional Descriptor*/
0x05, /* bLength: CDC header Descriptor size */
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
CDC_HEADER, /* bDescriptorSubtype: Header Func Desc */
WBVAL(CDC_V1_10), /* bcdCDC 1.10 */
/* Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
CDC_CALL_MANAGEMENT, /* bDescriptorSubtype: Call Management Func Desc */
0x01, /* bmCapabilities: device handles call management */
USB_CDC_DIF_NUM, /* bDataInterface: CDC data IF ID */
/* Abstract Control Management Functional Descriptor*/
0x04, /* bFunctionLength */
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
CDC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities: SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported */
/* Union Functional Descriptor*/
0x05, /* bFunctionLength */
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
CDC_UNION, /* bDescriptorSubtype: Union func desc */
USB_CDC_CIF_NUM, /* bMasterInterface: Communication class interface is master */
USB_CDC_DIF_NUM, /* bSlaveInterface0: Data class interface is slave 0 */
/* Endpoint 1 Descriptor*/
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_CDC_INT_EP, /* bEndpointAddress */
USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
WBVAL(0x0010), /* wMaxPacketSize */
0x02, /* 2ms */ /* bInterval */
/* Interface 1, Alternate Setting 0, Data class interface descriptor*/
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_CDC_DIF_NUM, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: no alternate setting */
0x02, /* bNumEndpoints: two endpoints used */
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass: Data Interface Class */
0x00, /* bInterfaceSubClass: no subclass available */
0x00, /* bInterfaceProtocol: no protocol used */
0x04, /* iInterface: */
/* Endpoint, EP Bulk Out */
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_CDC_OUT_EP, /* bEndpointAddress */
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
WBVAL(USB_FS_MAX_BULK_PACKET), /* wMaxPacketSize */
0x00, /* bInterval: ignore for Bulk transfer */
/* Endpoint, EP Bulk In */
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_CDC_IN_EP, /* bEndpointAddress */
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
WBVAL(64), /* wMaxPacketSize */
0x00, /* bInterval: ignore for Bulk transfer */
/* Terminator */
0 /* bLength */
};

Execution

After a successful CDC Initialization the stack is ready to receive the packets from host. Even if the device is physically connected to the host using an USB cable the host does not recognize the presence of device until the D+ line is pulled up using 1.5K ohm resistor (LPC device controllers operate in high-speed or full-speed mode only). To enable the connection the application software should call USBD_HW_API_T::Connect with enable set to 1. Before enabling the connection the application should enable the USB interrupt.

NVIC_EnableIRQ(USB0_IRQn); // enable USB0 interrupts
/* now connect */
USBD_API->hw->Connect(g_hUsb, 1);

After connection the CDC class executes through callback functions setup during initialization.

Installing IRQ handlers

USBD ROM stack implements the interrupt handler for USB device controller and invokes the USBD ROM stack routines according to the event type. Hence application should connect this handler to the application vector table. This is done by calling USBD_HW_API_T::ISR from the USB IRQ handler as shown in the code snippet below. The USBD ROM handle passed to the ISR() routine is the one obtained in previous step.

void USB0_IRQHandler(void)
{
USBD_API->hw->ISR(g_hUsb);
}

Implementing callback

The CDC Class executes by calling callback routines setup during CDC initialization. The callbacks used in CDC are:

-VCOM_SetLineCode: Called when a line coding request is sent from the host indicating a new connection over the USB bus. Over the line coding request, it could indicate a new set of UART parameters such as baud rate, number of data bits, start bit, stop bits, etc.

-VCOM_bulk_in_hdlr: Called when a BULK IN request is sent from the host, once the connection is established and line is not busy, hardware API WriteEP() should be called to send data back to the host.

-VCOM_bulk_out_hdlr: Called when a BULK_OUT request is sent from the host, hardware API ReadEP() should be called to collect data from the host

Subsections: