Does LPC1343 USBCDC example lack flow control when sending from target to host?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Does LPC1343 USBCDC example lack flow control when sending from target to host?

748 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ian201 on Tue Feb 01 11:56:59 MST 2011
When using the lpcxpresso usbcdc example, data appears to be lost when sending large amounts from target to host. Does the example usbcdc lack flow control? Is this a limitation of the usb cdc specification, or the lpc1343 device?

vcomdemo.c V1.02
cdcuser.c V1.10
usbcore.c V1.20
serial.c V1.10

The code changes made below are to construct a pathological test, which floods the USB interface with writes from target to host. I set ser_AvailChar to always return '1' to signal data is always available. In ser_AvailChar, a single incrementing byte is sent on each call. The usbcdc example project is otherwise unmodified.

I would expect to see in the output file [0,1,2,3,4,...,255,0,1,2...], repeated as fast as the target interface can send, and the host can accept.

On Linux:
cat /dev/ttyACM0 > capture
hexdump capture | less

* serial.c *

int ser_Read (char *buffer, const int *length) {
        static int increment = 0;
        buffer[0] = increment++;
        return 1;
}

void ser_AvailChar (int *availChar) {
        return 1;
}
0 Kudos
12 Replies

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by igorsk on Wed Mar 16 07:44:09 MST 2011
Have a look at BlueUSB.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by caprock on Tue Mar 15 15:29:24 MST 2011
I see there are several stacks and confusion reigns...

Is there an open source usb stack that is available for LPC13xx & LPC17xx that you can recommend? Or can someone provide info on a ported version such as lpcusb.

What I would like (ultimately) is an open source stack. Initial use is for Dual USB-CDC and grow into other uses as I learn.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ktownsend on Tue Mar 15 13:43:17 MST 2011

Quote: domen
I can't really publish the code because it has silly license restrictions. And it's somewhat integrated with another project, so it's questionably helpful.



Indeed, it would be nice to see an example based on something like lpcusb (open source). 

There are many contradictions in some of the licensing terms on the examples that have been published, and it isn't always clear how to proceed.  A very simple USBCDC example without the license restrictions on the Keil code would be exceedingly useful, as with the USBHID and USBMSC examples for the LPC1343 which use the same underlying stack.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by caprock on Tue Mar 15 07:21:22 MST 2011
domen,

Thanks for the reply, and the hints provided.

I'm a novice to this usb stack so more study is really needed. Especially around the BulkIn processes.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by domen on Tue Mar 15 02:02:30 MST 2011
OK, an addition. You must not send more than one <64B packet in one frame time, and since BulkIn seems to get called after transfer you sometimes have to ignore those calls until next SOF (this one was hard to track... everything worked fine on low speed, and on high speed, but not in between, and I suspected problems to be elsewhere).

I can't really publish the code because it has silly license restrictions. And it's somewhat integrated with another project, so it's questionably helpful.

OTOH, I can try to help and explain what I did / how I think (USB is full of surprises :P) this works.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by caprock on Mon Mar 14 10:24:40 MST 2011
Domen,


Quote:

After giving up, I've actually managed to fix my issues



I have also run into this same issue - data drops from target to host.

Is it possible for you to publish the code fixes needed?

Thanks to all for the great detective work!
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by domen on Mon Feb 21 09:51:01 MST 2011
After giving up, I've actually managed to fix my issues :D

Now I'm getting 800+kB/s mcu->pc, no data dropped.

Things I've learned:
- I don't know the proper terminology, so i'll abuse a term "transfer"; transfer here means n*64B packets + ending packet (<64B, yes, you also need to send Zero Length Packet). Transfers don't stop on frame (1ms) boundaries.
- ONLY call BulkIN when you start a transfer (and even then, you could call it from Start of frame interrupt [but ONLY if it's the start of a transfer]), in all other cases BulkIN will get called from interrupt handler.
- There doesn't seem to be a way to tell if EP buffers are full. I've spend too much time figuring this out, and the proper solution was just elsewhere.


And while at it, I'll also write a note about host -> device:
- When host sends data BulkOUT callback gets called. If you can't handle the data, don't ReadEP, and host will keep retrying (and getting automatically declined). When you do get space again, you need to call ReadEP yourself.

Resulting "device echo" (host (some data) -> device (reply same data) -> host) transfer rate was 500+kB/s, and that includes overhead for circular buffers, semaphores etc.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ktownsend on Sun Feb 20 15:13:23 MST 2011

Quote: domen
Unfortunately, I got stuck at the same problem... Bulk_IN keeps getting called, even though I don't write anything to EP, and data gets lost.

I also limited it to one write to endpoint per frame (effectively limiting to 64*1000 B/s), but a bit nicer way:
enable USB_SOF_EVENT, and implement USB_SOF_Event.



I'll look into that.  Thanks for the tip.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by domen on Sun Feb 20 12:54:36 MST 2011

Quote: KTownsend
I had to buffer the data and limit writing to the endpoint to once per ms (1000 frames/sec) to get the USB CDC example to work properly without dropping frames or data.



Unfortunately, I got stuck at the same problem... Bulk_IN keeps getting called, even though I don't write anything to EP, and data gets lost.

I also limited it to one write to endpoint per frame (effectively limiting to 64*1000 B/s), but a bit nicer way:
enable USB_SOF_EVENT, and implement USB_SOF_Event.
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ian201 on Thu Feb 03 18:18:24 MST 2011
Was an issue with tty handling on Linux.
To resolve: stty -F /dev/ttyACM0 raw
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ktownsend on Tue Feb 01 18:51:55 MST 2011
I had to buffer the data and limit writing to the endpoint to once per ms (1000 frames/sec) to get the USB CDC example to work properly without dropping frames or data.

  // This is a terribly ugly way to do this, but there must be
  // at least 1ms between USB frames (of up to 64 bytes) ... the
  // way this is implemented below is slow, but should at
  // least avoid dropped characters, etc.  Needs to be rewritten
  // with something much better performing though!
  #ifdef CFG_PRINTF_USBCDC
    if (USB_Configuration) 
    {
      cdcBufferWrite(c);
      // Check if we can flush the buffer now or if we need to wait
      unsigned int currentTick = systickGetTicks();
      if (currentTick != lastTick)
      {
        uint8_t frame[64];
        uint32_t bytesRead = 0;
        while (cdcBufferDataPending())
        {
          // Read up to 64 bytes as long as possible
          bytesRead = cdcBufferReadLen(frame, 64);
          // debug_printf("%d,", bytesRead);
          USB_WriteEP (CDC_DEP_IN, frame, bytesRead);
          systickDelay(1);
        }
        lastTick = currentTick;
      }
    }
  #endif
0 Kudos

715 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ian201 on Tue Feb 01 14:30:00 MST 2011
Correction:
void ser_AvailChar (int *availChar) {
*availChar = 1;
}
0 Kudos