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
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.
Regards, Elisandra
Hi,
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;
Tsuneo
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 :)