Hi!
First of all, some information: I'm starting a project using LPC2388 (I have MCB2000 board) and I'm new to ARM. In this project we have some code provided by other company to speed up our development, a kind of library to access some functions like USB, UART, SPI, etc. The code we have for USB is based on Keil's USBCDC, and it is ported to work with FreeRTOS. We have to use CDC because this project is supposed to act as a Modbus Slave and should be compatible with the softwares we have (using a USB-Serial converter is not desirable). For testing purposes, we are echoing all data receive by USB, and it works fine, apparently we have no data loss. I use teraterm and I don't send more than 256 bytes at a time.
Now my question: I noticed that in the descriptor they have defined the max size of the bulk endpoints in 256 bytes. As far as I know, the max size of a bulk endpoint (for a full-speed device) is 64 bytes, but please correct me if I'm wrong. So, I don't understand how it is working! I tried to simply change the max size in the descriptor, but then I have data loss. This is probably happening because the code provided doesn't handle ZLP and it's not dividing data in 64 (or whatever is the proper max size) bytes packets. I also tried to use a USB sniffer (software - I have Snoopy and USBlyzer) but I got more confused. I always see the host sending up to 100 bytes packets, no matter the max size defined (64 or 256 bytes).
Thanks in advance! Regards Elisandra
I believe you are mixing packet size and report size. You are correct the max packet size is 64 bytes but the report size can be larger, up to 4K Bytes if I'm not mistaken. If your device report size does not match your application report size + 1, you will get the error that you are seeing. Please search this forum for report size and packet size. There has been much written about the two. Bradford
Hi,
thanks for your quick reply. I'll search those topics as you suggested. It's the first time I work with CDC, there's a lot to learn. Buy I still don't understand one thing:
... /* Interface 1, Alternate Setting 0, Data class interface descriptor*/ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_CDC_DIF_NUM, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: no alternate setting */ 0x02, /* bNumEndpoints: two endpoints used */ CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass: Data Interface Class */ 0x00, /* bInterfaceSubClass: no subclass available */ 0x00, /* bInterfaceProtocol: no protocol used */ 0x5E, /* iInterface: */ /* Endpoint, EP2 Bulk Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(2), /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(USB_CDC_BUFSIZE), /* wMaxPacketSize */ 0x00, /* bInterval: ignore for Bulk transfer */ /* Endpoint, EP2 Bulk In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(2), /* bEndpointAddress */ USB_ENDPOINT_TYPE_BULK, /* bmAttributes */ WBVAL(USB_CDC_BUFSIZE), /* wMaxPacketSize */ 0x00, /* bInterval: ignore for Bulk transfer */ ...
I've searched for some examples of CDC descriptors, and in every descriptor I've seen USB_CDC_BUFSIZE is set to 64 bytes (for full-speed devices). In the code I have it is set to 256 bytes. Is it right? isn't that the endpoint max packet size?
Regards, Elisandra
This is probably happening because the code provided doesn't handle ZLP and it's not dividing data in 64 (or whatever is the proper max size) bytes packets.
I agree.
"I also tried to use a USB sniffer (software - I have Snoopy and USBlyzer) but I got more confused. I always see the host sending up to 100 bytes packets, no matter the max size defined (64 or 256 bytes)."
It's natural. Actual packet splitting - gathering is done on the host controller - USB hardware on the PC. Software sniffer intercepts the communication between the device driver and the host controller (more precisely, high-level device driver and low-level one, which control host controller). Then, you don't see split packets on the software sniffer. If you see the traffic on a hardware bus analyzer, you'll see the traffic as you expect.
wMaxPacketSize field (USB_CDC_BUFSIZE) of full-speed bulk endpoint should be one of these figures, 64, 32, 16, 8. It's defined in USB2.0 spec.
Tsuneo
Hi
thanks for your reply, now what I see in the sniffer makes more sense.
wMaxPacketSize is well defined in the spec, I just can't understand why it accepts the value 256 and works fine in this situation (as long as the packet size is less than 256 bytes). It worked under XP sp2 and Vista.
Anyway, I'll try to implement data spliting and ZLP handling in the code. It's a little confusing because I must use FreeRTOS, and I'm not used to it.
If you have any tip for this implementation to put me on the right direction, I'll appreciate :)
thanks! Best regards Elisandra
"wMaxPacketSize is well defined in the spec, I just can't understand why it accepts the value 256 and works fine in this situation (as long as the packet size is less than 256 bytes). It worked under XP sp2 and Vista."
How many PCs did you check? Can you check every PC in the world?
When you go out of spec, it doesn't mean you always get failure in every system/hardware. Some host controller may work, but others don't. As long as you follow the spec, your device is guaranteed to work on every system/hardware. "It's a little confusing because I must use FreeRTOS, and I'm not used to it."
I don't use FreeRTOS yet, too. :-)
JC Wren shows FreeRTOS demo combined with LPCUSB on LPC2148 www.freertos.org/Free-RTOS-FAT-file-system-USB-LPC2148.html
The USB device engine of LPC2388 is very similar to LPC2148. It'll give you a start point for your FreeRTOS task.
Thanks for your reply, Tsuneo :)
Sure it would be a little dificult to test in every PC in the world ;) I've tested in 5 different PCs, and I just expected to see some failure in this universe. I tought this point of the spec would be more "respected".
Thanks for the link, too. I'll look into it carefully.
Hi again!
Well, I've looked both the link you've suggested and LPCUSB alone. And I'm ashamed to say that I couldn't understand how packet spliting and ZLP are implemented :(
Now I'm trying to implement them following the steps you explained in this thread: http://www.keil.com/forum/docs/thread13504.asp . So far I've done the part regarding to bulk In endpoint.
The good news are that I successfully sent more than 64 bytes, without data loss. The bad news are that I'm still having troubles with packets lenghts multiple of 64 bytes. So it seems that I'm not sending the ZLP packet properly. Using USBlyzer I see the ZLP transfer failed. After that, there's two requests "query device relations", the first one is a "removal relation" and the second one is a "ejection relation", and both are not supported. Then there's a "surprise removal" and the device is disconnected. Now I'm trying to figure out why this is happening.
My mistake, I've downloaded the wrong hex file to my board... the results posted before are from my first attempt to solve this issue, and I've tried to solve it in a relly bad way. So, please ignore my last post.
I'm trying to follow Tsuneo's steps (http://www.keil.com/forum/docs/thread13504.asp). As the BulkIn interrupt is triggered after data is sent, it is using SOF event to poll the buffer and send ZLP. But it seems that after I've sent some data to my device, I don't have any SOF interrupt anymore. So I can't send data back to the host.
I'll try to understand what is happening, right now I'm a little lost.
Hi there,
I just want to report my progress :)
So, I finally got the packet spliting and the ZLP working, not exactly the way I wanted to, but it is a progress. I couldn't follow all the steps Tsuneo pointed though. I've tried in many ways, but never succeeded in reading FE bit status. So right now I'm not checking endpoint IN buffer status before writing, and I risk to have data overwriting. Now I'll try to figure out how to read this status.
Besta regards, Elisandra
"but never succeeded in reading FE bit status"
I mistakenly use WrCmd() in the posts. http://www.keil.com/forum/docs/thread13504.asp It is replaced to RdCmdDat() as follows.
a) bulk OUT EP - Check the FE bit of "Select Endpoint" command, if the EP buffer is empty, return - - WrCmd( CMD_SEL_EP(EPAdr(CDC_DEP_OUT)) ); if ( CMD_DATA & EP_SEL_F == 0 ) return; // - wrong
if ( RdCmdDat( CMD_SEL_EP(EPAdr(CDC_DEP_OUT)) ) & EP_SEL_F == 0 ) return;
b) bulk IN EP - Check the FE bit of "Select Endpoint" command, if no empty EP buffer, return - - WrCmd( CMD_SEL_EP(EPAdr(EPNum)) ); if ( CMD_DATA & EP_SEL_F != 0 ) return; // - wrong
if ( RdCmdDat( CMD_SEL_EP(EPAdr(CDC_DEP_IN)) ) & EP_SEL_F != 0 ) return;
Thank you, Tsuneo! It's really nice of you sharing your knowledge :) I find it very difficult to get used to LPC family... I understood the steps you've explained, but I was unable to implement them by myself (I didn't know which macros/functions/definitions to use, there isn't many explanaitions on the code...). Also I find it almost impossible to understand the datasheet. Just one detail, I got it working this way: if ( RdCmdDat( DAT_SEL_EP(EPAdr(CDC_DEP_IN)) ) & EP_SEL_F != 0 ) return;
Now, thanks to Tsuneo, I got it all working :)