We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I am trying to get Bulk transfer working in USB. i can send data from host to device (out report), but my IN Report is not working. To test the bulk transfer I am using the C# program from Jan Axelson wesbite.http://www.lvr.com/winusb.htm I am using a sniffer program to check the end points and the program does show that i have both Input, Bulk and Output Bulk end points with max packet size of 64 bytes. When i try to read data, i dont even seem to get an interrupt when i put a break point at USB_ISR. I am using LPC 2478 with Keil and i modified the HID example to work with bulk. Any ideas?
/* Endpoint, BULK In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(2), /* bEndpointAddress */ //USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ 0x00, /* 32ms */ /* bInterval , not used in bulk*/ /* Endpoint, BULK Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(2), /* bEndpointAddress */ //USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(0x0040), /* wMaxPacketSize */ // = 64 0x00, /* 32ms not used in bulk*/
> I am trying to get Bulk transfer working in USB. i can send data from host to device (out report), but my IN Report is not working. > When i try to read data, i dont even seem to get an interrupt when i put a break point at USB_ISR.
Fill the IN endpoint with a packet using USB_WriteEP(), first, outside of the endpoint ISR (callback). USB endpoint interrupt doesn't occur on IN endpoints, until your firmware passes a packet to the IN endpoint.
Endpoint interrupt arises just when a transaction finishes successfully. For OUT endpoints, it is when the USB engine receives a packet from host. But for IN endpoints, it's when a packet, loaded by firmware, is sent to the host. That is, unless your firmware passes a packet to the IN endpoint, no endpoint interrupt occurs.
For IN endpoint, usually, endpoint interrupt is used for block transfer of large data. The first packet of the block is written to the endpoint outside of the endpoint ISR, to start block transfer. Second and latter packets are filled to the IN endpoint in the endpoint ISR.
It's similar to UART RX/TX. For UART RX, your firmware reads data at UART RX interrupt. But for UART TX, your firmware writes to the UART TX buffer, first.
Tsuneo
Tsuneo, thanks for the reply.. I found out the problem was this..
void USB_Configure_Event (void) { if (USB_Configuration) { /* Check if USB is configured */ GetInReport(); USB_WriteEP(HID_EP_IN, &InReport[0], sizeof(InReport)); } }
I did not the change the endpoint from HID_EP_IN to 0x82. After i changed it everything is working great. I guess this is called once during the enumeration? But i dont understand what exactly is the purpose if this configuration event. I have read couple of other posts where you explained it, but i still dont understand the purpose of it, all it is doing is reading the IN endpoint buffer.
USB_Configure_Event() is called from Set_Configuration request handler. The HID example writes (USB_WriteEP()) the first packet to the IN endpoint, here.
> I guess this is called once during the enumeration? But i dont understand what exactly is the purpose if this configuration event.
Set_Configuration request is a part of enumeration sequence. On enumeration, host reads out descriptors from the target device to know about the device. And then, host checks if it has enough resources to run the device or not. - PC device driver for the device - Bus bandwidth required to run the device endpoints etc. Set_Configuration notifies to the device that host is prepared to run the device.
In this request, device is expected to do these jobs - Enable and initialize the endpoints other than the default one - Initialize the context (variables and flags) for the communication using these endpoints > I did not the change the endpoint from HID_EP_IN to 0x82. After i changed it everything is working great.
Really everything ? Surely, you've gotten IN packets from the device. But how about the contents of the packet? Jan's host example expects that the device returns the same packet written by the host application, immediately (loop back). With your change, the host app gets the previous packet, not the current one.
1) Delete the contents of USB_Configure_Event()
usb_user.c #if USB_CONFIGURE_EVENT void USB_Configure_Event (void) { // comment the contents of this call /* if (USB_Configuration) { /* Check if USB is configured */ GetInReport(); USB_WriteEP(HID_EP_IN, &InReport, sizeof(InReport)); } */ } #endif
2) Modify endpoint ISR (callback) for OUT as follows. In this snippet, the process for TX packet is light one (just copy, for loopback). But when the process takes more steps, you may move USB_WriteEP() elsewhere, where the TX packet is actually made up.
usb_user.c #include <string.h> #define BULK_EP_OUT 0x02 #define BULK_EP_IN 0x82 #define USB_BUFFER_SIZE 64 U8 usb_RX_buffer[ USB_BUFFER_SIZE ]; U8 usb_TX_buffer[ USB_BUFFER_SIZE ]; void USB_EndPoint2( U32 event ) { U32 packet_size; switch (event) { case USB_EVT_OUT: packet_size = USB_ReadEP( BULK_EP_OUT, usb_RX_buffer ); // Read a packet from the OUT endpoint memcpy( usb_TX_buffer, usb_RX_buffer, (size_t)packet_size ); // In this snippet, just copy the data // from RX buffer to TX buffer for loopback // Usually, your firmware parses RX packet // And it makes up a TX packet on the TX buffer USB_WriteEP( BULK_EP_IN, usb_TX_buffer, packet_size ); // Return TX packet break; case USB_EVT_IN: // // nothing to do, here // break; } }
Thanks, I did not check if i am getting "proper" data but i was getting data. But i will def look into..
Hi Tsuneo,
>For IN endpoint, usually, endpoint interrupt is used for block transfer of large data. The first packet of the block is written to the endpoint outside of the endpoint ISR, to start block transfer. Second and latter packets are filled to the IN endpoint in the endpoint ISR.
This is exactly what i am trying to do. I have about 127 bytes of data (status message) that i want to transfer from device to PC everytime i hit the read button on the PC App. Like you mentioned above i sent 64 bytes of 0s outside the ISR, and the latter packet of 63 bytes in the endpoint ISR. But in the PC App (that i got from Jan Alexons website), even after changing the "bytesToRead" to 127 bytes, it reads only first the 64 bytes and reads the next 63 bytes when i hit the read button again. Can i call the USB_Write function in the main loop? or is there some time i need to wait between every USB_write function calls?
Thanks, Nav