Hi everybody I'm trying to migrate from AT91SAM7S256 to SAM3S8B Micro controller. I applied some necessary changes in my project and everything works well. But I have a problem: In previous project we use HID sample code for AT91SAM7S in \Keil\ARM\Boards\Atmel\AT91SAM7S-EK\USB\HID. I replaced USB source code with related HID sample codes for SAM3S in \Keil\ARM\Boards\Atmel\SAM3S-EK\USBHID and USB communication performance significantly decreased. For example reading 2 bytes from our new hid device takes more than 1 second but in old hid device this takes about 40 milliseconds. Our descriptor for old project is:
#include "type.h" #include "usb.h" #include "usbcfg.h" #include "usbdesc.h" #include "hid.h" /* HID Report Descriptor */ const BYTE HID_ReportDescriptor[] = { HID_UsagePageVendor(0xFF), HID_Usage(0xFF), HID_Collection(HID_Application), HID_Usage(0xFF), HID_ReportCount(64), HID_ReportSize(8), HID_LogicalMin(-128), HID_LogicalMax(127), HID_Input(0), HID_Usage(0xFF), HID_ReportCount(64), HID_ReportSize(8), HID_LogicalMin(-128), HID_LogicalMax(127), HID_Output(0), HID_EndCollection, }; /* USB Standard Device Descriptor */ BYTE USBHID_DeviceDescriptor[] = { USB_DEVICE_DESC_SIZE, USB_DEVICE_DESCRIPTOR_TYPE, WBVAL(0x0110), /* 1.10 */ 0x00, 0x00, 0x00, USB_MAX_PACKET0, WBVAL(0xF6B5), WBVAL(0xBD60), WBVAL(0xFFFF), 0x04, 0x1C, 0x42, 0x01 }; const WORD HID_ReportDescSize = sizeof(HID_ReportDescriptor); /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ const BYTE USBHID_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, USB_CONFIGURATION_DESCRIPTOR_TYPE, WBVAL( 1*USB_CONFIGUARTION_DESC_SIZE + 1*USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + 2*USB_ENDPOINT_DESC_SIZE ), 0x01, 0x01, 0x00, USB_CONFIG_BUS_POWERED /*|*/ /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, USB_INTERFACE_DESCRIPTOR_TYPE, 0x00, 0x00, 0x02, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE, 0x92, /* HID Class Descriptor */ /* HID_DESC_OFFSET = 0x0012 */ HID_DESC_SIZE, HID_HID_DESCRIPTOR_TYPE, WBVAL(0x0100), /* 1.00 */ 0x00, 0x01, HID_REPORT_DESCRIPTOR_TYPE, WBVAL(HID_REPORT_DESC_SIZE), /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, USB_ENDPOINT_DESCRIPTOR_TYPE, USB_ENDPOINT_IN(2), USB_ENDPOINT_TYPE_INTERRUPT, WBVAL(0x0040), 0x1, /* 1ms */ /* Endpoint, HID Interrupt out */ USB_ENDPOINT_DESC_SIZE, USB_ENDPOINT_DESCRIPTOR_TYPE, USB_ENDPOINT_OUT(3), USB_ENDPOINT_TYPE_INTERRUPT, WBVAL(0x0040), 0x1, /* 1ms */ /* Terminator */ 0 };
And our descriptor for new one is:
#include "type.h" #include "usb.h" #include "usbcfg.h" #include "usbdesc.h" #include "hid.h" #define HID_INPUT_REPORT_BYTES 64 #define HID_OUTPUT_REPORT_BYTES 64 #define HID_FEATURE_REPORT_BYTES 1 const U8 HID_ReportDescriptor[] = { HID_UsagePageVendor( 0x00 ), HID_Usage ( 0x01 ), HID_Collection ( HID_Application ), HID_LogicalMin ( 0 ), /* value range: 0 - 0xFF */ HID_LogicalMaxS ( 0xFF ), HID_ReportSize ( 8 ), /* 8 bits */ HID_ReportCount ( HID_INPUT_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Input ( HID_Data | HID_Variable | HID_Absolute ), HID_ReportCount ( HID_OUTPUT_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Output ( HID_Data | HID_Variable | HID_Absolute ), HID_ReportCount ( HID_FEATURE_REPORT_BYTES ), HID_Usage ( 0x01 ), HID_Feature ( HID_Data | HID_Variable | HID_Absolute ), HID_EndCollection, }; const U16 HID_ReportDescSize = sizeof(HID_ReportDescriptor); /* USB Standard Device Descriptor */ const U8 USB_DeviceDescriptor[] = { USB_DEVICE_DESC_SIZE, USB_DEVICE_DESCRIPTOR_TYPE, WBVAL(0x0110), /* 1.10 */ // WBVAL(0x0200), /* 2.00 */ 0x00, 0x00, 0x00, USB_MAX_PACKET0, WBVAL(0xF6B5), WBVAL(0xBD60), WBVAL(0x0100), /* 1.00 */ 0x01, 0x02, 0x03, 0x01 }; /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */ const U8 USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, USB_CONFIGURATION_DESCRIPTOR_TYPE, WBVAL( USB_CONFIGUARTION_DESC_SIZE + USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + 2*USB_ENDPOINT_DESC_SIZE ), 0x01, 0x01, 0x00, USB_CONFIG_BUS_POWERED /*|*/ // USB_CONFIG_SELF_POWERED /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, USB_INTERFACE_DESCRIPTOR_TYPE, 0x00, 0x00, 0x02, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE, 0x04, /* HID Class Descriptor */ /* HID_DESC_OFFSET = 0x0012 */ HID_DESC_SIZE, HID_HID_DESCRIPTOR_TYPE, WBVAL(0x0100), /* 1.00 */ 0x00, 0x01, HID_REPORT_DESCRIPTOR_TYPE, WBVAL(HID_REPORT_DESC_SIZE), /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, USB_ENDPOINT_DESCRIPTOR_TYPE, USB_ENDPOINT_IN(1), USB_ENDPOINT_TYPE_INTERRUPT, WBVAL(0x0040), 0x01, /* 1ms */ /* Endpoint, HID Interrupt Out */ USB_ENDPOINT_DESC_SIZE, USB_ENDPOINT_DESCRIPTOR_TYPE, USB_ENDPOINT_OUT(2), USB_ENDPOINT_TYPE_INTERRUPT, WBVAL(0x0040), 0x01, /* 1ms */ /* Terminator */ 0 };
As you see, we use 64byte endpoint in both projects and 1 millisecond time interval for hid device. Any idea why does this problem?
I don't find any problem on the descriptors.
> For example reading 2 bytes from our new hid device takes more than 1 second but in old hid device this takes about 40 milliseconds.
a) How did you measure these timing? - What is the start timing of the measurement?
Every process, involved in from the start to the end of measurement, is possible to cause the delay, not just "reading".
b) Are you using the same PC application for this measurement?
AT91SAM7S256 and SAM3S8B share almost same USB engine, though SAM3S8B's is slightly enhanced.
Tsuneo
a & b) We use the same application to measure time for AT91SAM7S256 and SAM3S8B. These applications use a polling mechanism for sending and receiving commands. We also use GetTickCount() to measure read function time right before sending command and after the receiving command. It means that our time consist of a send/receive time pair.
> We use the same application to measure time
Then, the difference should be caused by the device side.
Measure the performance on the firmware, using SysTick, as follows.
usbuser.c uint32_t g_timing[3]; void USB_EndPoint2 (U32 event) { // EP2 (interrupt OUT) handler // when a packet comes from host, this routine is called g_timing[0] = SysTick->VAL; // capture SysTick value USB_ReadEP( ... ); // read a packet from OUT EP, and parse the command on the packet ... USB_WriteEP( ... ); // put a packet to the IN EP g_timing[1] = SysTick->VAL; // capture SysTick value } void USB_EndPoint1 (U32 event) { // EP1 (interrupt IN) handler // when the packet completes to send, this routine is called g_timing[2] = SysTick->VAL; // capture SysTick value }
After putting "get input" command, puase the firmware execution on the debugger, and read g_timing[] values using the debugger. Which one causes so long delay?