Hi Ping,
I created a new workspace and imported the project you recommended. I have successfully built the example. But am not sure how to utilize the example source in my project. I have built 4 successful versions of my product using LCPXpresso but all of them are using a UART for host communication.
I now need to build a version which communicates the application data over the USB as a HID Class device. I have experience developing software for USB HID devices in the past but have never used a driver API. I essentially designed my own driver in these experiences.
But I believe using the NXP USB ROM API is the best solution for my project. However, I am not very familiar with this technique and would appreciate your help. Thanks for your patience with me.
Here is the state of my project:
I have successfully compiled my application such that the host communication is abstracted from the hardware interface. In this abstraction, I have an initialization function that I want to handle the enumeration and set up the USB_IRQ_Handler. I also have a transmit buffer in which I queue the data for the host reports. So I need to find a way to service the Endpoint 1 interrupts such that I load the data successfully to IN token polls.
Requirements:
1. Method or function to enumerate my device
I believe that I can review the USB_ROM_HID example to figure out how to modify the descriptors and initialization for my project configuration. I only need 2 endpoints inclusive of the Control Endpoint 0. Endpoint 1 should be configured as an Interrupt Pipe for transmission of data packets from my application.
Can I utilize the example code much like a function call to do the following:
Initialize the USB descriptors with my device data
Connect the device to the USB
Enumerate the device
Establish endoint1 interrupt polls at a periodic rate
Here is the essential structure of main in the example:
int main(void)
{
USBD_API_INIT_PARAM_T usb_param;
USB_CORE_DESCS_T desc;
ErrorCode_t ret = LPC_OK;
Initialization of device for USB peripheral use - I understand this.
/* initialize USBD ROM API pointer. */
g_pUsbApi = (const USBD_API_T *) LPC_ROM_API->usbdApiBase;
Is the above essentially establishing a handle for the USB API?
/* initialize call back structures */
memset((void *) &usb_param, 0, sizeof(USBD_API_INIT_PARAM_T));
usb_param.usb_reg_base = LPC_USB0_BASE;
usb_param.max_num_ep = 2 + 1;
usb_param.mem_base = USB_STACK_MEM_BASE;
usb_param.mem_size = USB_STACK_MEM_SIZE;
I am not sure I understand the above but don't think I really need to.
/* Set the USB descriptors */
desc.device_desc = (uint8_t *) USB_DeviceDescriptor;
desc.string_desc = (uint8_t *) USB_StringDescriptor;
desc.high_speed_desc = USB_FsConfigDescriptor;
desc.full_speed_desc = USB_FsConfigDescriptor;
desc.device_qualifier = 0;
I need to modify the descriptors used in the above functions with my application data. Is this correct?
/* USB Initialization */
ret = USBD_API->hw->Init(&g_hUsb, &desc, &usb_param);
if (ret == LPC_OK) {
usb_param.mem_base = USB_STACK_MEM_BASE + (USB_STACK_MEM_SIZE - usb_param.mem_size);
ret =
usb_hid_init(g_hUsb,
(USB_INTERFACE_DESCRIPTOR *) &USB_FsConfigDescriptor[sizeof(USB_CONFIGURATION_DESCRIPTOR)],
&usb_param.mem_base, &usb_param.mem_size);
The above code actually sets up the USB ROM driver to enumerate with the host in a manner that is accomplished without much foreground attention by my application. Is this correct?
if (ret == LPC_OK) {
/* enable USB interrupts */
NVIC_EnableIRQ(USB0_IRQn);
Above enables interrupts that will begin once device is connected to USB. But the servicing of the interrupts is handled by the driver without much attention from my foreground application during device enumeration. Is this correct?
/* now connect */
USBD_API->hw->Connect(g_hUsb, 1);
How do I know when the enumeration is complete or when the Set Configuration command has been successfully accomplished?
}
}
while (1) {
__WFI();
}
I assume that this while loop should be deleted as my application foreground will be doing things like collecting, processing, and queuing data for transmission over endpoint1.
}
2. Method or function to load endpoint1 data such that USB_IQR_Handler successfully retrieves transmit data to host.
Below is the USB_IRQ_Handler in the example:
void USB_IRQHandler(void)
{
uint32_t *addr = (uint32_t *) LPC_USB->EPLISTSTART;
if ( LPC_USB->DEVCMDSTAT & _BIT(8) ) { /* if setup packet is received */
addr[0] &= ~(_BIT(29)); /* clear EP0_OUT stall */
addr[2] &= ~(_BIT(29)); /* clear EP0_IN stall */
}
USBD_API->hw->ISR(g_hUsb);
}
Do I need to do write code in the handler to load the endpoint1 payload and monitor the success of transmission? If so, can you provide an example of how this function is implemented through the API?
I also need to set up endpoint0 to transfer vendor specific commands in the data payload. And this will require that I need to know when the driver has endpoint0 data, and that I have a means to transmit data back to the host through endpoint0 in response to the vendor commands. But I will leave this task for a later discussion.
If you can help me understand how to accomplish Methods 1 and 2 utilizing a revision of the example code, I would be very appreciative.
Thanks
512-635-4963