Re: Missing isochronous packets

Chris E <[email protected]> Fri, 24 Jul 2015 11:13:17 +1000
Newsgroups gmane.comp.lib.libusb.devel.windows
Message-ID <CALmGtgSYC0NauT9nSLrhMyz8Q=EZ0TbJNYmP-y93uZOoN1vchA@mail.gmail.com>
ASF USB stack is fast enough for Full Speed USB (although probably slow for
High Speed!).  I suspected about 100 to 200 cycles per call to
udi_vendor_iso_in_run.
The callback itself should be very fast.  It just adds a function call into
the interrupt that's generated when the USB transceiver asserts
"transaction receieved".

Yeah, that's what I meant by double buffering.  It eats up RAM, but I found
it's needed for smooth iso transactions.

My code runs at 375kB/s.  I could go a bit higher if I wanted to, but I'm
forced to run my endpoint at a speed of 24MHHz/(2^n) and fit everything in
2k of RAM.
Do keep in mind that I'm using Full Speed USB, though.

500kB/s is good for Full Speed but terrible for High Speed.
I suspect you may be running your device in Full Speed mode.
What is the contents of your conf_usb.h?  Are you explicitly set your USB
transceiver to work in High Speed mode?
Have you sniffed your bus using something like USBPcap to make sure you're
getting more than one transfer per ms? (note: if you see a random 7 or 8 ms
delay per transfer, ignore it.  It's a USBPcap bug and doesn't exist in
real life.)

Also, on a side note, I found that, only for some values of
UDI_VENDOR_EPS_SIZE_ISO_FS, it will glitch out if you try to request the
maximum packet size per frame.  ie, if you #define
UDI_VENDOR_EPS_SIZE_ISO_FS 375 and you request a 375 byte transfer each
frame, you get garbage.  But #define it to 500 and everything works fine.
God bless USB/Atmel.

~Chris



On 24 July 2015 at 05:04, Tim Hutt <[email protected]> wrote:

> Hi Chris,
>
> I suspected as much. I didn't want to use the callback because I suspected
> it would be too slow (I suspect the whole ASF USB stack might be relatively
> slow actually). Anyway tried using it as follows (I couldn't set the
> buffers to volatile, but it doesn't seem to matter; also is this what you
> meant by double buffering?)
>
> volatile int count = 0;
>
> uint8_t bufferA[UDI_VENDOR_EPS_SIZE_ISO_HS]; // 64 bytes.
>
> uint8_t bufferB[UDI_VENDOR_EPS_SIZE_ISO_HS]; // 64 bytes.
>
> bool bufferPol = false;
>
> void IsoTransferCallback(udd_ep_status_t status, iram_size_t nb_transfered, udd_ep_id_t ep)
>
> {
>
> 	bufferPol = !bufferPol;
>
> 	++count;
>
> 	if (bufferPol)
>
> 	{
>
> 		bufferA[0] = count & 0xFF;
>
> 		bufferA[1] = (count >> 8) & 0xFF;
>
> 		udi_vendor_iso_in_run(bufferA, sizeof(bufferA), IsoTransferCallback);
>
> 	}
>
> 	else
>
> 	{
>
> 		bufferB[0] = count & 0xFF;
>
> 		bufferB[1] = (count >> 8) & 0xFF;
>
> 		udi_vendor_iso_in_run(bufferB, sizeof(bufferB), IsoTransferCallback);
>
> 	}
>
> }
>
>
> This now means I don't have any dropped packets. The problem is that the
> throughput is only about 500 kB/s which is orders of magnitude below what
> it should be. Any ideas? What speed do you get?
>
> You might be right about this not being the right forum, but I'm still not
> 100% sure whether the problem is with the SAM3X or libusbK. I reckon there
> are way more USB experts on this list than any Arduino forum!
>
> Cheers,
>
> Tim
>
>
>
> On 23 July 2015 at 08:50, Chris E <[email protected]> wrote:
>
>> G'day Tim.
>> I recently did a similar project: a 375 byte iso packets using an XMEGA,
>> also in ASF!
>> (The same one I posted about before, Xiaofan, and I got it to work!)
>>
>> udi_vendor_iso_in_run(buffer, sizeof(buffer), nullptr) does not cause the
>> microcontroller to wait!  It just tells the USB controller "on the next iso
>> request, I want you to transmit sizeof(buffer) bytes, starting at address
>> buffer and then do nothing when the transaction finishes".  (Note: if a
>> transaction has already been requested, the function may simply return
>> without doing anything.  I'm not 100% sure but I think I remember the
>> source code implying that.)
>> So your increments a huge number of times between transactions, since
>> there's nothing blocking it!
>>
>> To fix this, take everything out of the loop!
>> Run udi_vendor_iso_in_run() only once, and pass in a callback to a
>> function rather than the NULL ptr.
>> Then, in the callback function, increment the number and then call
>> udi_vendor_iso_in_run() again - also with callback!
>> The callback function will only run once per transaction, after it's
>> complete.
>>
>> Also, you'll want the buffer to be volatile.  If it's not volatile, the
>> CPU might not write back the data to memory when it's done.  This will
>> cause hell with the USB's DMA!
>> One last thing: this probably isn't a LibUSBK question.  An Atmel forum
>> such as AVRFreaks (or possibly an Arduino forum) would be much more
>> helpful.  Although, that being said, I get an email notification if you
>> post here and I've probably just been through the same stuff that you're
>> going through.  :P
>>
>> Oh, and P.P.S: If you run into problem with data transfer not being
>> smooth in the future: double buffer things on both the micro and PC side,
>> and run two separate, interleaved Iso Contexts and OvlK Handles PC side.
>> The callback method works fine for continuous streaming on my XMEGA, just
>> make sure you swap buffers each time!
>>
>> Good luck, mate!
>> ~Chris
>>
>> On 23 July 2015 at 17:12, Tim Hutt <[email protected]> wrote:
>>
>>> I'm trying to transmit 64 byte isochronous USB packets over a USB high
>>> speed link from a SAM3X (in an Arduino Due) to a libusbk program (basically
>>> the example benchmark program it comes with).
>>>
>>> I have one isochronous endpoint on the device and it sends data in a
>>> tight loop like this (using Atmel's SDK):
>>>
>>> uint8_t buffer[UDI_VENDOR_EPS_SIZE_ISO_HS]; // 64 bytes.for (int i = 0; i < sizeof(buffer); ++i)
>>>     buffer[i] = i;for (;;){
>>>     led = !led;
>>>     udi_vendor_iso_in_run(buffer, sizeof(buffer), nullptr);
>>>     // TODO: How to wait until it is finished?
>>>     buffer[0]++;
>>>     if (buffer[0] == 0)
>>>         buffer[1]++;}
>>>
>>> The receiving program is basically the example iso read program from
>>> libusbk. It writes data to a log file, including the first two bytes of
>>> each packet which I increment as shown above. It requests 128 packets per
>>> frame, and outputs data like this:
>>>
>>> #6: StartFrame=00DDE360h LastFrameCount=16 TransferLength=8192 BPS-average:390409.30
>>>   #0000: Length=64 C0h 3Dh
>>>   #0001: Length=64 E1h 3Dh
>>>   #0002: Length=64 01h 3Eh
>>>   #0003: Length=64 23h 3Eh
>>>   #0004: Length=64 44h 3Eh
>>>   #0005: Length=64 64h 3Eh
>>>   #0006: Length=64 85h 3Eh
>>>   #0007: Length=64 A6h 3Eh
>>>   #0008: Length=64 C7h 3Eh
>>>  ... snip ...
>>>   #0120: Length=64 34h 4Dh
>>>   #0121: Length=64 55h 4Dh
>>>   #0122: Length=64 76h 4Dh
>>>   #0123: Length=64 97h 4Dh
>>>   #0124: Length=64 B8h 4Dh
>>>   #0125: Length=64 D9h 4Dh
>>>   #0126: Length=64 FAh 4Dh
>>>   #0127: Length=64 1Bh 4Eh
>>>
>>> As you can see, it works but is skipping loads of the packets. I'd like
>>> to know why! The data rate is really low compared to what USB 2 can do. I'm
>>> kind of at a loss here as I don't know how to wait until a transfer is
>>> completed in a tight loop on the SAM3X. Also... it should work right?
>>>
>>> Here are the USB descriptors (I snipped some unused endpoints):
>>>
>>> Device Power State:               PowerDeviceD0
>>>
>>>        ---===>Device Information<===---English product name: ""
>>> ConnectionStatus:                  Current Config Value:              0x01  -> Device Bus Speed: HighDevice Address:                    0x05Open Pipes:                           0*!*ERROR:  No open pipes!
>>>
>>>           ===>Device Descriptor<===
>>> bLength:                           0x12
>>> bDescriptorType:                   0x01
>>> bcdUSB:                          0x0200
>>> bDeviceClass:                      0x00  -> This is an Interface Class Defined Device
>>> bDeviceSubClass:                   0x00
>>> bDeviceProtocol:                   0x00
>>> bMaxPacketSize0:                   0x40 = (64) Bytes
>>> idVendor:                        0x1111 = Dade Behring, Inc.  // Screw the USB-IF!
>>> idProduct:                       0x2223
>>> bcdDevice:                       0x0100
>>> iManufacturer:                     0x01
>>>      English (United States)  ""
>>> iProduct:                          0x02
>>>      English (United States)  ""
>>> iSerialNumber:                     0x00
>>> bNumConfigurations:                0x01
>>>
>>>        ---===>Full Configuration Descriptor<===---
>>>
>>>           ===>Configuration Descriptor<===
>>> bLength:                           0x09
>>> bDescriptorType:                   0x02
>>> wTotalLength:                    0x0045  -> Validated
>>> bNumInterfaces:                    0x01
>>> bConfigurationValue:               0x01
>>> iConfiguration:                    0x00
>>> bmAttributes:                      0x80  -> Bus PoweredMaxPower:                          0x32 = 100 mA
>>>
>>>           ===>Interface Descriptor<===
>>> bLength:                           0x09
>>> bDescriptorType:                   0x04
>>> bInterfaceNumber:                  0x00
>>> bAlternateSetting:                 0x00
>>> bNumEndpoints:                     0x00
>>> bInterfaceClass:                   0xFF  -> Interface Class Unknown to USBView
>>> bInterfaceSubClass:                0xFF
>>> bInterfaceProtocol:                0xFF
>>> iInterface:                        0x00
>>>
>>>           ===>Interface Descriptor<===
>>> bLength:                           0x09
>>> bDescriptorType:                   0x04
>>> bInterfaceNumber:                  0x00
>>> bAlternateSetting:                 0x01
>>> bNumEndpoints:                     0x06
>>> bInterfaceClass:                   0xFF  -> Interface Class Unknown to USBView
>>> bInterfaceSubClass:                0xFF
>>> bInterfaceProtocol:                0xFF
>>> iInterface:                        0x00
>>> (snipped irrelevant endpoints)
>>>
>>>           ===>Endpoint Descriptor<===       <---- This is the endpoint I'm using.
>>> bLength:                           0x07
>>> bDescriptorType:                   0x05
>>> bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
>>> bmAttributes:                      0x01  -> Isochronous Transfer Type, Synchronization Type = No Synchronization, Usage Type = Data Endpoint
>>> wMaxPacketSize:                  0x0040 = 1 transactions per microframe, 0x40 max bytes
>>> bInterval:                         0x01
>>>
>>> Does anyone have any ideas?
>>>
>>> Cheers,
>>>
>>> Tim
>>>
>>>
>>> ------------------------------------------------------------------------------
>>>
>>> _______________________________________________
>>> Libusb-win32-devel mailing list
>>> [email protected]
>>> https://lists.sourceforge.net/lists/listinfo/libusb-win32-devel
>>>
>>>
>>
>>
>> ------------------------------------------------------------------------------
>>
>> _______________________________________________
>> Libusb-win32-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/libusb-win32-devel
>>
>>
>
>
> ------------------------------------------------------------------------------
>
> _______________________________________________
> Libusb-win32-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/libusb-win32-devel
>
>

------------------------------------------------------------------------------

_______________________________________________
Libusb-win32-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libusb-win32-devel