I am trying to add end points to the usb example, dev_hid_generic_freertos_twrk65f180m. I added end points to the descriptor and indeed, the TWR-K65F180M enumerates, correctly for all of the end points. However, when trying to send USB messages, only the first set of end points, 0x01 and 0x81 cause the USB_DeviceGenericCallback() method to be called.
In addition, even if the USB_DeviceGenericCallback() were called for all of the end points, I don't see from its arguments class_handle_t handle, uint32_t event and void *param, for which end point the call was made.
Is there an HID example that I've missed, which illustrates more than a pair of end points? If not, perhaps someone with more insight into the Kinetis USB middleware stack could point me in the right direction.
Hi Kirk.
I apologize for the late response, but I consulted your issue with Application Team. Please refer to their answer below.
Regarding the multiple pairs of endpoints enablement, I think you are using the HID generic class driver, for such standard class driver, only one pair of endpoint could be supported for sure. By no means, you could use a standard generic class driver to support a non-standard user case (multiple pairs of endpoints). Instead, you should use the usb_device_hid_generic_lite example, which has no standard class driver, so it is easy for you to add more endpoints support.
I hope this helps.
Best Regards,
Iva
Sadly, documentation for the FreeRTOS USB stack in SDK is woefully inadequate. If one simply wants to use a template and replace a few constants or rewrite a few methods, it's fine. But, if one wants to understand how the stack works, then too much time is required. The problem is that global macros used to choose between different running options are usually only documented by a comment. Let's take USB_DEVICE_CONFIG_USE_TASK as an example. Here's the entry from usb_device_config.h.
/*! @brief Whether the device task is enabled. */
#define USB_DEVICE_CONFIG_USE_TASK (0U)
The default is for the task to be disabled. However, in the example, USB appears to work. So, what does this global do? Ah, as a desperate measure, let's check out the documentation. The USB Stack Device reference Manual gives a hint:
#define USB_DEVICE_CONFIG_USE_TASK (0U)
Whether the device task is enabled.
The USB Stack User's Guide omits the Macros. The USB Stack Composite Device User's Guide adds:
10. Poll the device task when the “USB_DEVICE_CONFIG_USE_TASK” is none-zero. Poll the
HID keyboard and HID generic task when these tasks are implemented.
#if USB_DEVICE_CONFIG_USE_TASK #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
USB_DeviceEhciTaskFunction(g_UsbDeviceComposite.deviceHandle); #endif
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
USB_DeviceKhciTaskFunction(g_UsbDeviceComposite.deviceHandle); #endif
#endif
Which brings two more undefined macros into the mix. One would have thought that USB_DEVICE_CONFIG_USE_TASK would have needed to be 1 for the example to work, yet it appears just the opposite. The amount of time needed to wind through the example code is such that it might be quicker to simply write the usb driver one's self.
two years later and same thing. it's crazy how much tribal knowledge you have to accumulate to write an app that uses the USB stack. I know NXP ported dean camera's LUFA for some other platforms, would be a heaven send if there were a well documented stack available for the I.MX since one of it's biggest selling points is multiple dual role usb ports.
some of my biggest headaches:
all of the configuration settings you need to uncomment to enable usb stack drivers (USB_CONFIG_AUDIO, USB_DEVICE_CONFIG_KHCI)
if you move the default configuration files, they are silently recreated in source/generated
no simple documentation of the difference between the freeRTOS and regular OSA drivers (what does USB_DEVICE_CONFIG_USE_TASK do?)
no good instructions for writing your own class driver (i've been battling an issue for months where my host instance would stop receiving messages if i paused the debugger and anything came on usb while it was paused. It turns out, in my call to prime the receiver, I requested the size of the receiving buffer rather than the size of of the maximum message the device could send. i only discovered this by copying example drivers line by line until something changed.)
It sounds from Iva response below that NXP doesn't really see how this is a problem on their end..
I answered half of my own question. The endpoint causing the USBDeviceGenericCallback() to be called can be found by:
endpointAddress = ((usb_device_hid_struct_t *)handle)->interfaceHandle->endpointList.endpoint->endpointAddress;