USB_EVT_OUT and Buffer Size

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

USB_EVT_OUT and Buffer Size

841 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by etunnel on Fri Sep 19 00:48:55 MST 2014
I am learning about writing USB bulk transfer.  I noticed something that I don't understand.

On LPC4370 (the device), I setup a 4KB transfer buffer.  I found in debugger that I have to issue 1KB transfer 4 times on the PC host (running in Windows 7 using WINUSB API) before the EP OUT event handler is called with USB_EVT_OUT on the device.  Each time when 1KB transfer is issued, the host function call returns successful.  When I change the transfer size to be an odd size, for example 1000 bytes.  Immediately, EP OUT event handler is called with USB_EVT_OUT.  Is this an expected behavior?

Is there a flag I can modify the behavior such that the event handler is called for each 1KB transfer?

Should I design a data flow protocol to send a small packet containing the length of transfer from host first?  Then, setup the transfer size in exact size on the LPC43xx device, subject to the max dma buffer allowed.  Finally, initiate the data transfer from the host.


Thanks!
Labels (1)
0 Kudos
5 Replies

713 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mch0 on Tue Sep 23 01:46:02 MST 2014
The reason is indeed performance.

A ZLP (Zero Length Packet) is another packet on the USB bus, taking some time.
It is indeed shortened a lot, but nevertheless there is overhead around the "pure token".
For that reason some well-known classes like Mass Storage explicitely do not use ZLP termination.
This is most probably also the reason why it is turned off by default in WinUsb.

Best regards,

Mike

0 Kudos

713 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by etunnel on Tue Sep 23 00:07:43 MST 2014
I stumbled onto something that is quite useful for this situation.

For WinUSB API, there is a policy controlling how data write works as described below:

0x01SHORT_PACKET_TERMINATESends a zero length packet for a write request in which the buffer is a multiple of the maximum packet size supported by the endpoint.

It applies to Bulk (OUT) Interrupt (OUT).  By default, it is FALSE.  This policy is set with function, WinUsb_SetPipePolicy().

It changed it to be TRUE in my test program.  Now, I am getting USB_EVT_OUT event call back just as I originally hoped for.  This zero length packet doesn't add on to the read length returned.

I don't know what is the performance impact of enabling this.  I think the benefit of simplified data packetization algorithm outweighs any performance degradation.  I wonder why the default is the other way.  Is it due to some USB device's lack of zero length packet support?  Anyway, it works for LPC4370.

I imagine there is equivalent capability in libusb API as well.


0 Kudos

713 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by etunnel on Fri Sep 19 23:30:31 MST 2014
Hi Mike,

I think you are right.  The wMaxPacketSize of the EP is set to be 64 bytes.  I experimented with changing the buffer size in the device.  This change has no effect on how USB_EVT_OUT event is generated.  It must be wMaxPacketSize.

I guess I have to be careful in constructing the transfer size in order to get somewhat synchronous response from the device. 

One interesting observation when using USBD_API->hw->ReadEP():  If I issue a transfer that is larger than the device buffer, this API cannot read out the data into the buffer at all, but return read size of 0.  The device doesn't split the data into two read.  At the same time, the host indicates that the transfer is completed successfully.  Effectively, the data is lost.

I haven't experimented with the lower level DMA DTD descriptor setup in this case.  I hope there is status information about this situation.

Thanks a lot for this pointer.
0 Kudos

713 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mch0 on Fri Sep 19 04:26:03 MST 2014
This may have to something with the size of your OUT endpoint.
Typically these are set to multiples of 2, like 64 or 512.
You find that information in the USB endpoint descriptor.
Now if you tranfser a larger block like 4096 the host splits them into packets of max. size.
If the last packet has less than EPSIZE bytes then this indicates an end of the transfer.

I think this is th reason you see an EP_EVT with 1000 bytes immediatley. The last packet is of less than max size and this particular transfer is considered to be finished.

With 1024 there  is no remainder and the transfer continues until the buffer you have set up is full.

I may be wrong, of course.

You could test that by setting the OUT endpoint size to an integer fraction of 1000, e.g. 50 instead of 64 or 500 instead of 512.

Mike
0 Kudos

713 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by etunnel on Fri Sep 19 00:54:32 MST 2014
I missed one important piece of information:

I am using the custom class with bulk transfer endpoint.  I experimented two examples provided in LPCOpen:   usbd_rom_libusb and usbd_rom_bwtest.  Both examples using different sets of APIs exhibit the same behavior.  I am developing using LPCXpresso.
0 Kudos