Nick Guzzardo

MCUXpresso USB Generic HID Example - High Speed and 1kB Packet Size

Discussion created by Nick Guzzardo on Sep 19, 2018
Latest reply on Sep 21, 2018 by jeremyzhou

I attempted to ppst this as a blog, but I wasn't allowed to select a "place" which prevented the post, so starting a new discussion is the next best thing.

 

Here are the details:  I was running the USB generic HID device example code from the MCUXpresso SDK for the LPCXpresso54608 board (OM13092).  This MCU/dev baord was chosen because it included a USB HS PHY.  Along with the example code, there is a C# program referenced in the readme which identifies when the correct VID and PID are registered on the PC and allows for data to be transferred to the dev board and receives/displays data that is echoed back.  Here is the link to download it, but per the example code readme, you will need to make some modifications.  I have attached the modified C# code to this post as well.

 

A USB HID Component for C# - CodeProject 

 

Default settings for the LPC54608 example code have it running on the full-speed (FS) port (J3) with 8-byte reports.  The following changes allow the board to communicate with USB high-speed (HS) on J2 with 1024-byte reports.

 

First, changing the following in "usb_device_config.h" switches the active PHY from FS / J3 to HS / J2:

 

From:

/*! @brief LPC USB IP3511 FS instance count */
#define USB_DEVICE_CONFIG_LPCIP3511FS (1U)

/*! @brief LPC USB IP3511 HS instance count */
#define USB_DEVICE_CONFIG_LPCIP3511HS (0U)

 

To:

/*! @brief LPC USB IP3511 FS instance count */
#define USB_DEVICE_CONFIG_LPCIP3511FS (0U)

/*! @brief LPC USB IP3511 HS instance count */
#define USB_DEVICE_CONFIG_LPCIP3511HS (1U)

 

I also changed the polling period to be as frequent as possible which I believe is supposed to be 125µs.  The change is as follows

 

In "usb_device_descriptor.h" I changed the generic buffer lengths, the HS packet sizes and the interrupt interval to be as frequent as possible which I believe is supposed to be 125µs:

 

From:

#define USB_HID_GENERIC_IN_BUFFER_LENGTH (8U)
#define USB_HID_GENERIC_OUT_BUFFER_LENGTH (8U)
#define USB_HID_GENERIC_ENDPOINT_COUNT (2U)
#define USB_HID_GENERIC_INTERFACE_INDEX (0U)
#define USB_HID_GENERIC_ENDPOINT_IN (1U)
#define USB_HID_GENERIC_ENDPOINT_OUT (2U)

#define USB_HID_GENERIC_CLASS (0x03U)
#define USB_HID_GENERIC_SUBCLASS (0x00U)
#define USB_HID_GENERIC_PROTOCOL (0x00U)

#define HS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE (8U)
#define FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE (8U)
#define HS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x04U) /* 2^(4-1) = 1ms */
#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x01U)

#define HS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE (8U)
#define FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE (8U)
#define HS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x04U) /* 2^(4-1) = 1ms */
#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x01U)

 

To:

#define USB_HID_GENERIC_IN_BUFFER_LENGTH (1024U) // <--
#define USB_HID_GENERIC_OUT_BUFFER_LENGTH (1024U) // <--
#define USB_HID_GENERIC_ENDPOINT_COUNT (2U)
#define USB_HID_GENERIC_INTERFACE_INDEX (0U)
#define USB_HID_GENERIC_ENDPOINT_IN (1U)
#define USB_HID_GENERIC_ENDPOINT_OUT (2U)

#define USB_HID_GENERIC_CLASS (0x03U)
#define USB_HID_GENERIC_SUBCLASS (0x00U)
#define USB_HID_GENERIC_PROTOCOL (0x00U)

#define HS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE (1024U) // <--
#define FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE (8U)
#define HS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x01U) /* 2^(4-1) = 1ms */ // <--
#define FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL (0x01U)

#define HS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE (1024U) // <--
#define FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE (8U)
#define HS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x01U) /* 2^(4-1) = 1ms */ // <--
#define FS_HID_GENERIC_INTERRUPT_IN_INTERVAL (0x01U)

 

NOTE - Though I changed the IN and OUT buffer length and packet size above, that was not sufficient to to actually change the packet size.  The report descriptor also had to be modified.  I was concerned that the parameter associated with the "Report Count" was only one byte, but with some Googling, I found a program that will generate the appropriate hex for the descriptor.  The following link explains this pretty well and provides the link to the HID descriptor tool:  Tutorial about USB HID Report Descriptors | Eleccelerator 

 

I included a few extra commented lines to show the descriptor changes for 255, 256, 512 and 768 byte packets with only the 1024 byte line uncommented.  The report descriptor is in the file "usb_device_descriptor.c":

 

From:

uint8_t g_UsbDeviceHidGenericReportDescriptor[] = {
0x05U, 0x81U, /* Usage Page (Vendor defined)*/
0x09U, 0x82U, /* Usage (Vendor defined) */
0xA1U, 0x01U, /* Collection (Application) */
0x09U, 0x83U, /* Usage (Vendor defined) */

0x09U, 0x84U, /* Usage (Vendor defined) */
0x15U, 0x80U, /* Logical Minimum (-128) */
0x25U, 0x7FU, /* Logical Maximum (127) */
0x75U, 0x08U, /* Report Size (8U) */
0x95U, 0x08U, /* Report Count (8U) */
0x81U, 0x02U, /* Input(Data, Variable, Absolute) */

0x09U, 0x84U, /* Usage (Vendor defined) */
0x15U, 0x80U, /* Logical Minimum (-128) */
0x25U, 0x7FU, /* Logical Maximum (127) */
0x75U, 0x08U, /* Report Size (8U) */
0x95U, 0x08U, /* Report Count (8U) */
0x91U, 0x02U, /* Output(Data, Variable, Absolute) */
0xC0U, /* End collection */

};

 

To:

uint8_t g_UsbDeviceHidGenericReportDescriptor[] = {
0x05U, 0x81U, /* Usage Page (Vendor defined)*/
0x09U, 0x82U, /* Usage (Vendor defined) */
0xA1U, 0x01U, /* Collection (Application) */
0x09U, 0x83U, /* Usage (Vendor defined) */

0x09U, 0x84U, /* Usage (Vendor defined) */
0x15U, 0x80U, /* Logical Minimum (-128) */
0x25U, 0x7FU, /* Logical Maximum (127) */
0x75U, 0x08U, /* Report Size (8U) */
// 0x95U, 0xFFU, /* Report Count (255U) */ // <--
// 0x96U, 0x00U, 0x01U, /* Report Count (256U) */ // <--
// 0x96U, 0x00U, 0x02U, /* Report Count (512U) */ // <--
// 0x96U, 0x00U, 0x03U, /* Report Count (768U) */ // <--
0x96U, 0x00U, 0x04U, /* Report Count (1024U) */ // <--
0x81U, 0x02U, /* Input(Data, Variable, Absolute) */

0x09U, 0x84U, /* Usage (Vendor defined) */
0x15U, 0x80U, /* Logical Minimum (-128) */
0x25U, 0x7FU, /* Logical Maximum (127) */
0x75U, 0x08U, /* Report Size (8U) */
// 0x95U, 0xFFU, /* Report Count (255U) */ // <--
// 0x96U, 0x00U, 0x01U, /* Report Count (256U) */ // <--
// 0x96U, 0x00U, 0x02U, /* Report Count (512U) */ // <--
// 0x96U, 0x00U, 0x03U, /* Report Count (768U) */ // <--
0x96U, 0x00U, 0x04U, /* Report Count (1024U) */ // <--
0x91U, 0x02U, /* Output(Data, Variable, Absolute) */
0xC0U, /* End collection */
};

 

Don't forget to also change the contents of "usb_device_descriptor.h" to match the report descriptor.

 

I have only done simple tests with these modifications so far, but by adding a timer in the PC program that starts at the beginning of the PC-USB transmission and stops after the PC receives the echoed data back from the dev board, I have been able to verify that the round trip time for 1024 bytes is ~600µs (slightly more than 2x microframes at 125µs each.

Attachments

Outcomes