Issues with isoc.FinishDataXfer(ref cBufs[k], ref xBufs[k], ref len, ref oLaps[k], ref pktsInfo[k]))

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
maVa_1182686
Level 3
Level 3
Welcome!

Hi,

I had a spartan 7 fpga dumping data into the FX3 and was reading the data with a modified version of STREAMER C#.

The protocol was BULKtransfer. I was seeing some dataloss on some computers so I needed to move Isochronous protocol.

In bulk i was using 64*1024byte DMA buffers.

In bulktransfer the data that gets put into xBufs is always exactly the amount of data I suspect =>

The amount of Packets per Xfer*1024.

For my current application that was 19 packets of 1024. Worked like a charm

Just go USB_data_frame = xBufs

Now that I've changed the FX3 code to ISOCHRONOUS this is not longer true.

I had to increase the DMA buffer size as isochronous is really slow with small buffers.

Currently I still need to send dataframes of 19kB but I have to send at least 8 packets per Xfer (isochronous demands this) but i also had to increase the buffersize to 4KB instead of 1024.

Therefore, I'm sending at least 32KB every Xfer.

This is not a problem. I can deal with this on another level.

I do notice however that the packets that are coming in through

isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))

aren NOT 32 KB anymore.

They're alternating between 8KB and 12KB which makes me think it's sending either 2 or 3 bursts of the 4KB dma buffers.

To makes things worse, it seems that the data is skipping randomly.

Does that have anything to do with the "overlaps"?

USB_data_frame = xBufs  does not work for sure

I only have been programming C# since last week so I'm quite in over my head.

Can anybody point me in the right direction as far as the inner workings of isoc.FinishDataXfer goes.

The manual is sooo incredibly short and explains nothing.

Thank You!!!!!!!!!!!!!!!!!!!!!

0 Likes
1 Solution
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Mattijs,

Please program the firmware that I have given you yesterday ( with which the issue is reproduced - I hope Thread(1000) is not changed when the issue is seen)

Then run the attached streamer application which creates FinishData.bin in the same directory where the application is.

-> Choose IN Endpoint; Choose 8 as PPX and 1 in Queue.

Note:

1. Every time you run this application, if FinishData.bin file exists it deletes and creates new. (Letting you know in case you have some other file with same name)

2. open the FinishData.bin file after closing Streamer.

Please test and let me know if the pattern obtained in the file is correct.

Regards,

Hemanth

Hemanth

View solution in original post

0 Likes
47 Replies
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Please provide the below info:

1. What is the packets per xfer setting?

2. ISOC Endpoint and Endpoint Companion Descriptor.

3. USB trace (if possible - You can take a USB trace using Wireshark).

Regards,

Hemanth

Hemanth
0 Likes

Hi,

I seemed to have replied not to you but to my original question.

I also failed to answer correctly and assumed you asked me about the amount of data in my uFrames when instead you asked for Xfer per packet.

In my app that would be 8 xfers per packet.

In my colleques, i'm not sure.

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

- In your firmware, what are the parameters passed to CyU3PDeviceCacheControl()?

- Can you please take an USB trace when you see the problem?

- Try with 7 burst and 0 mult setting. Packets per xfer =8 and 8KB DMA buffer size.

Regards,

Hemanth

Hemanth
0 Likes

Hi,

What is "mult" setting?

Thanks

0 Likes

I've tried all sorts of cache combinations also. Now it is set to:

status = CyU3PDeviceCacheControl (CyTrue, CyFalse, CyFalse);

We don't care about firmware performance and good caching. It's set and forget in firmware.

How can the DMA buffer size be 8K when you the multiplier is 0, CY_FX_ISO_BURST = 7  and CY_FX_ISO_PKTS is 1,2 or 3

Will the buffer not be either 7, 14 or 21 KB because of which of the latler you choose?

0 Likes

Hi,

I've installed the USB cap functionality in wireshark and with the following settings:

#define CY_FX_DMA_BUF_COUNT      (2)

#define CY_FX_DMA_TX_SIZE        (0)    /* DMA transfer size is set to infinite */

#define CY_FX_ISO_PKTS                  (1)    /* Number of bursts per microframe. */

#define CY_FX_ISO_BURST                 (8)    /* Number of packets per burst. */

#define CY_FX_DMA_SIZE_MULTIPLIER       (1)

I get packets of 16kB and 24kB. This is weird to me as I thought setting ISO PKTS would prohibit USB making 2* or 3* uFrames.

In my Descriptor file I also seem to indicate that USB can't make bigger than 8KB Frames.

0x06,                           /* Descriptor size */

    CY_U3P_SS_EP_COMPN_DESCR,       /* SS endpoint companion descriptor type */

    (CY_FX_ISO_BURST - 1),          /* Max no. of packets in a burst(0-15) - 0: burst 1 packet at a time */

    0,                              /* Only one 16KB burst per micro-frame. */

    0x00, (0x04 * CY_FX_ISO_BURST), /* Bytes per interval : 1024 * 1 * burst */

Here is my Wireshark screendgrab showing the 16 and 24kB

Could this be the reason that my DMA engine is sending weird out of order data? It's grabbing two or three times more data from the buffers than it shoudl?

wireshark screengrab.jpg

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Can you please share the wireshark trace file (corresponding to the image posted above)?

Regards,

Hemanth

Hemanth
0 Likes

Hi HemanthR.

I have completely started from scratch and made a new test setup with an FPGA connected to on of the FX3 devkits.

I started with very simple testcode on the FPGA and a completely new firmware on the FX3.

It's the syncslaveFIFO example from the application note but turned into a ISO souce of testdata.

Every 1024 byes i increment a counter with the FPGA and i'm dumping into 16*1024*1 DMA buffers.

I know now that there is nothing wrong with the transmission.

You can clearly see the right data is being sent from the FPGA through the FX3 to the computer: wireshark 1.png

wireshark 2.pngwireshark 3.png

As you can see, the packets are 16kB and because i increment the data every 1KB there is a 16 jump in the data from 16KB packet to the next.

(I'm not sending fast enough to have them aggregated. When i send data faster the packets become 8 times bigger)

Eitherway, when I print the test byte in the streamerexample in C# like so:

USBpacket = xBufs;

Console.WriteLine(USBpacket[2000].ToString());

inside the

if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo)) - LOOP

The result is completely erratic (RED)

I expect there to be a nice increment of 16 every new time I go through the loop and

if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))    len is 16k

length pkts=

16384

test:

162

length xBuf=

131072

length pkts=

16384

test:

242

length xBuf=

131072

length pkts=

0

length xBuf=

131072

length pkts=

16384

test:

114

length xBuf=

131072

length pkts=

0

length xBuf=

131072

length pkts=

16384

test:

2

length xBuf=

131072

length pkts=

16384

test:

34

length xBuf=

131072

This makes me conclude that i fail to understand how isoc.FinishDataXfer works.

I added the trace too.

I hope you can help me!

Thanks.

0 Likes

I noticed that when i send at full speed and maximize the allocated bandwidth the DATA does make sense!

I increased the speed on the 16bit GPIFII bus from 5 to 75Mhz.

I'm asking for 8 Xfers per packet.

When I'm sending data into the FX3 at 5 Mhz the packets on USB are only 16kB (the size of the buffer, n ot the size of 8 buffers - Xfers per packet) .

When I'm saturating the GPIF the packets are in fact 8*16KB instead of 1*16kB.

The data makes perfect sense:

  for (int i = 0; i < 8; i++)  //8 packets per Xfer

                            {

                                a = (USBpacket[2000 + i * 16 * 1024]);

//scanning the data to see if every 1024 bytes there is an increment

                                Console.WriteLine((a/16).ToString());

//devide the incremented data by 16 to remove increment of 16 and make it increment of 1

                            

                            }

Yields

length pkts=

131072

test:

0

1

2

3

4

5

6

7

length xBuf=

131072

length pkts=

131072

test:

8

9

10

11

12

13

14

15

length xBuf=

131072

Consistend behaviour inside a 131072 uFRAME (0 = > 7 ) and from one uFrame to the next (7 => 😎

So the question remains...

How do you use isoc.FinishDataXfer when you are not saturating the usb bus and "incomplete" Xfers occur that are not

packets per Xfer * DMA buffer

in size but smaller.

Either 1*DMA buffer size or anything in between 1 and packets per Xfer - 1

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

In ISOC transfers, it is necessary to make sure that the data is available at the device to match the rate at which Host is asking (which is according to the configuration we choose during enumeration - burst and mult). If data is not available at that rate, then we are not sure as of now about the Windows OS behavior - it has to be tested.

From the cyusb3 driver point of view, an URB is submitted with the request equal to the size mentioned in BeginDataXfer. After the URB is submitted, then if the data is not available from the device for the requests made, then we cannot predict howmuch FinishDataXfer will return.

So, we need to modify the endpoint configuration as per the data availability. Let me know your comments on this.

Regards,

Hemanth

Hemanth
0 Likes

Hi,

When i'm not reaching the correct bandwidth and the packets are smaller than expected, they still ARE coming into the computer in a logical fashion.

Wireshark sees them and the data in them is correct. There does not seem to be a problem with this at all.

How can it be that it is not possible to get them out of the API  in a reliable manner when wireshark sees them without a problem?

I don't get this.

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Can you please let me know what is the problem with the FinishDataXfer() call with respect to those small packets? (Did the call fail?)

Regards,

Hemanth

Hemanth
0 Likes

I'm not sure what's happening. As you know, i have a simple counter in the data. That is how I know that the content of the smaller packages is completely logical and correct coming from the FPGA => FX3 => host (wireshark)

When read the data with the FinishDataXfer() function the data seems to be there at least partially...but the order is completely random.

As i Increase a counter in the data  from x0000 to x00FF in 0001 increments, every 1024 bytes.

You expect to see that reflected in the data. Every new 1024 bytes the counter has to increase.

You see this happen perfectly fine in wireshark.

The data coming from FinishDataXfer() is random. It's all over the place jumping seemingly random from one number to the next.

0 Likes

(but the data IS a counter...so it IS the data from the FPGA...it's not random data as such...it's just that the order in which it comes out of FinishDataXfer() is non sensical)

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Did you make sure that there is no error with respect to any index of the Finish circular queue and that you are looking at the data in the right order? Can you please share your code?

Regards,

Hemanth

Hemanth
0 Likes

I assume that when

  if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))

len > 0

the data at the start of xBufs is the correct data from position 0 to position len

For the moment i don't really do anything with it other than printing it to the console to check if it's correct.

  if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))

                    {

                        //XferBytes += len;

                        //Successes++;

                        Console.WriteLine("length pkts=");

                        Console.WriteLine(len.ToString());

                        PacketLength = len;

                        ISO_PKT_INFO[] pkts = pktsInfo;

                        for (int j = 0; j < PPX; j++)

                        {

                            if (pkts.Status == 0)

                            {

                                XferBytes += pkts.Length;

                                Successes++;

                            }

                            else

                                Failures++;

                            pkts.Length = 0;

                        }

                        USBpacket = xBufs;

                        //for (int i = 0; i < PacketLength / 1024; i++)

                        if (PacketLength > 0)

                       

                        {

                                    int a = 0;

                                    Console.WriteLine("test:");

                                    for (int i = 0; i < 8; i++)  //8 packets per Xfer

                                    {

                                          a = (USBpacket[ i * 1 * 4096]);  //scanning the data to see if every 1024 bytes there is an increment

                                          Console.WriteLine((a/4).ToString());   //devide the incremented data by 16 to remove increment of 16 and make it increment of 1

                              

                                    }

                                  

                         }

}

This is the code i used to test the firmware with 4 bursts of 1024 (4kB DMA buffer size)

I always expect 32kB chunks but in the problematic case where the fpga is held back and incomplete (<32kB ) are sent I still plot the entire xBuf, just to try to see the pattern in the data.

The fpga data counter is put in int a and as the DMA is 4kB large...the data is incremented 4 times in one 4kB packet.

That's why i divide a by 4 so I can clearly see if the data was correct 1,2,3,4,...,64,1,2,3,4,...,64,, or incorrect...1,2,3,4,55,56,57,58,22,23,24,25

How are you supposed to work with xBuf when data is not complete????

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

1. When you mention "4 bursts of 1024" is the burst setting in the descriptor 4? What is the mult setting at that time? - It would be helpful if you post the endpoint descriptor and its companion descriptor?

2. Regarding your comments:

"

When

len > 0

the data at the start of xBufs is the correct data from position 0 to position len"

>> Lets take an example when k=1 and len = 2048

I think you are aware that you can check USBpacket[] from index 0 to 2047 (since the length of the data returned for this particular Finish is 'len').

When you mentioned - "I still plot the entire xBuf, just to try to see the pattern in the data." did you check for xBuf[1] past USBPacket[2047]?

3. Can you put 'else' statement to the if(isoc.FinishDataXfer) and check if there were any failures?

Regards,

Hemanth

Hemanth
0 Likes

I check for failures with the normal streamer code:

for (int j = 0; j < PPX; j++)

                        {

                            if (pkts.Status == 0)

                            {

                                XferBytes += pkts.Length;

                                Successes++;

                            }

                            else

                                Failures++;

                            pkts.Length = 0;

                        }

There are no failures.

When len = 2048 i assume indeed that when USBpacket = xBuf, USBpacket[0] => USBpacket[2047]

Is the correct data. This is not the case.

I check the complete xBUF just to try to see a pattern...if there would be one.

I always check the entire thing (and like you asked indeed past your hypothetical 2048) just to be sure.

It is NOT the case that the data is OK in the zone indexed by [0..len] and not OK outside.

That would make sense but it is not the case.

I use, There is no multiplier:

#define CY_FX_ISOSRC_DMA_BUF_COUNT      (16)    /* Number of buffers in the DMA channel. */

#define CY_FX_ISO_PKTS                  (1)    /* Number of bursts per microframe. */

#define CY_FX_ISO_BURST                (4)    /* Number of packets per burst. */

(this code works perfectly when all packets are 32kB - when put differently, the FPGA is not held back and can saturate the GPIFII)

and for descriptors:

/*

## Cypress USB 3.0 Platform header file (cyfxisodscr.c)

## ===========================

##

##  Copyright Cypress Semiconductor Corporation, 2010-2018,

##  All Rights Reserved

##  UNPUBLISHED, LICENSED SOFTWARE.

##

##  CONFIDENTIAL AND PROPRIETARY INFORMATION

##  WHICH IS THE PROPERTY OF CYPRESS.

##

##  Use of this file is governed

##  by the license agreement included in the file

##

##    <install>/license/license.txt

##

##  where <install> is the Cypress software

##  installation root directory path.

##

## ===========================

*/

/* This file contains the USB enumeration descriptors for the ISO source application example.

* The descriptor arrays must be 32 byte aligned and multiple of 32 bytes if the D-cache is

* turned on. If the linker used is not capable of supporting the aligned feature for this,

* either the descriptors must be placed in a different section and the section should be

* 32 byte aligned and 32 byte multiple; or dynamically allocated buffer allocated using

* CyU3PDmaBufferAlloc must be used, and the descriptor must be loaded into it. The example

* assumes that the aligned attribute for 32 bytes is supported by the linker. Do not add

* any other variables to this file other than USB descriptors. This is not the only

* pre-requisite to enabling the D-cache. Refer to the documentation for

* CyU3PDeviceCacheControl for more information.

*/

#include "cyfxslfifosync.h"

/* Standard device descriptor for USB 3.0 */

const uint8_t CyFxUSB30DeviceDscr[] __attribute__ ((aligned (32))) =

{

    0x12,                          /* Descriptor size */

    CY_U3P_USB_DEVICE_DESCR,        /* Device descriptor type */

    0x10,0x03,                      /* USB 3.1 */

    0x00,                          /* Device class */

    0x00,                          /* Device sub-class */

    0x00,                          /* Device protocol */

    0x09,                          /* Maxpacket size for EP0 : 2^9 */

    0xB4,0x04,                      /* Vendor ID */

    0xF1,0x00,                      /* Product ID */

    0x00,0x00,                      /* Device release number */

    0x01,                          /* Manufacture string index */

    0x02,                          /* Product string index */

    0x00,                          /* Serial number string index */

    0x01                            /* Number of configurations */

};

/* Standard device descriptor for USB 2.0 */

const uint8_t CyFxUSB20DeviceDscr[] __attribute__ ((aligned (32))) =

{

    0x12,                          /* Descriptor size */

    CY_U3P_USB_DEVICE_DESCR,        /* Device descriptor type */

    0x10,0x02,                      /* USB 2.10 */

    0x00,                          /* Device class */

    0x00,                          /* Device sub-class */

    0x00,                          /* Device protocol */

    0x40,                          /* Maxpacket size for EP0 : 64 bytes */

    0xB4,0x04,                      /* Vendor ID */

    0xF1,0x00,                      /* Product ID */

    0x00,0x00,                      /* Device release number */

    0x01,                          /* Manufacture string index */

    0x02,                          /* Product string index */

    0x00,                          /* Serial number string index */

    0x01                            /* Number of configurations */

};

/* Binary device object store descriptor */

const uint8_t CyFxUSBBOSDscr[] __attribute__ ((aligned (32))) =

{

    0x05,                          /* Descriptor size */

    CY_U3P_BOS_DESCR,              /* Device descriptor type */

    0x16,0x00,                      /* Length of this descriptor and all sub descriptors */

    0x02,                          /* Number of device capability descriptors */

    /* USB 2.0 extension */

    0x07,                          /* Descriptor size */

    CY_U3P_DEVICE_CAPB_DESCR,      /* Device capability type descriptor */

    CY_U3P_USB2_EXTN_CAPB_TYPE,    /* USB 2.0 extension capability type */

    0x1E,0x64,0x00,0x00,            /* Supported device level features: LPM support, BESL supported,

                                      Baseline BESL=400 us, Deep BESL=1000 us. */

    /* SuperSpeed device capability */

    0x0A,                          /* Descriptor size */

    CY_U3P_DEVICE_CAPB_DESCR,      /* Device capability type descriptor */

    CY_U3P_SS_USB_CAPB_TYPE,        /* SuperSpeed device capability type */

    0x00,                          /* Supported device level features  */

    0x0E,0x00,                      /* Speeds supported by the device : SS, HS and FS */

    0x03,                          /* Functionality support */

    0x00,                          /* U1 Device Exit latency */

    0x00,0x00                      /* U2 Device Exit latency */

};

/* Standard device qualifier descriptor */

const uint8_t CyFxUSBDeviceQualDscr[] __attribute__ ((aligned (32))) =

{

    0x0A,                          /* Descriptor size */

    CY_U3P_USB_DEVQUAL_DESCR,      /* Device qualifier descriptor type */

    0x00,0x02,                      /* USB 2.0 */

    0x00,                          /* Device class */

    0x00,                          /* Device sub-class */

    0x00,                          /* Device protocol */

    0x40,                          /* Maxpacket size for EP0 : 64 bytes */

    0x01,                          /* Number of configurations */

    0x00                            /* Reserved */

};

/* Standard super speed configuration descriptor */

const uint8_t CyFxUSBSSConfigDscr[] __attribute__ ((aligned (32))) =

{

    /* Configuration descriptor */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_CONFIG_DESCR,        /* Configuration descriptor type */

    0x3E,0x00,                      /* Length of this descriptor and all sub descriptors */

    0x01,                          /* Number of interfaces */

    0x01,                          /* Configuration number */

    0x00,                          /* COnfiguration string index */

    0x80,                          /* Config characteristics - Bus powered */

    0x32,                          /* Max power consumption of device (in 8mA unit) : 400mA */

    /* Interface 0, Alt. Setting 0: No endpoints */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface Descriptor type */

    0x00,                          /* Interface number */

    0x00,                          /* Alternate setting number */

    0x00,                          /* Number of end points */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Interface 0, Alt. Setting 1: One ISO IN endpoint with single burst per uFrame. */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface Descriptor type */

    0x00,                          /* Interface number */

    0x01,                          /* Alternate setting number */

    0x01,                          /* Number of end points */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Endpoint descriptor for IN EP */

    0x07,                          /* Descriptor size */

    CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */

    CY_FX_EP_CONSUMER,              /* Endpoint address and description */

    CY_U3P_USB_EP_ISO,              /* ISO endpoint type */

    0x00,0x04,                      /* Max packet size = 1024 bytes */

    0x01,                          /* Servicing interval for data transfers : 1 uFrame */

    /* Super speed endpoint companion descriptor. */

    0x06,                          /* Descriptor size */

    CY_U3P_SS_EP_COMPN_DESCR,      /* SS endpoint companion descriptor type */

    (CY_FX_ISO_BURST - 1),          /* Max no. of packets in a burst(0-15) - 0: burst 1 packet at a time */

    0,                              /* Only one 16KB burst per micro-frame. */

    0x00, (0x04 * CY_FX_ISO_BURST), /* Bytes per interval : 1024 * 1 * burst */

    /* Interface 0, Alt. Setting 2: One ISO IN endpoint with multiple bursts per uFrame. */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface Descriptor type */

    0x00,                          /* Interface number */

    0x02,                          /* Alternate setting number */

    0x01,                          /* Number of end points */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Endpoint descriptor for consumer EP */

    0x07,                          /* Descriptor size */

    CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */

    CY_FX_EP_CONSUMER,              /* Endpoint address and description */

    CY_U3P_USB_EP_ISO,              /* ISO endpoint type */

    0x00,0x04,                      /* Max packet size = 1024 bytes */

    0x01,                          /* Servicing interval for data transfers : 1 uFrame */

    /* Super speed endpoint companion descriptor. */

    0x06,                          /* Descriptor size */

    CY_U3P_SS_EP_COMPN_DESCR,      /* SS endpoint companion descriptor type */

    (CY_FX_ISO_BURST - 1),          /* Max no. of packets in a burst(0-15) - 0: burst 1 packet at a time */

    (CY_FX_ISO_PKTS - 1),          /* Mult.: Max number of packets : CY_FX_ISO_PKTS */

    0x00,(0x04 * CY_FX_ISO_PKTS * CY_FX_ISO_BURST), /* Bytes per interval : 1024 * isoPkts * burst */

};

/* Standard high speed configuration descriptor */

const uint8_t CyFxUSBHSConfigDscr[] __attribute__ ((aligned (32))) =

{

    /* Configuration descriptor */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_CONFIG_DESCR,        /* Configuration descriptor type */

    0x22,0x00,                      /* Length of this descriptor and all sub descriptors */

    0x01,                          /* Number of interfaces */

    0x01,                          /* Configuration number */

    0x00,                          /* COnfiguration string index */

    0x80,                          /* Config characteristics - bus powered */

    0x32,                          /* Max power consumption of device (in 2mA unit) : 100mA */

    /* Interface 0, Alt. Setting 0: No endpoints. */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface Descriptor type */

    0x00,                          /* Interface number */

    0x00,                          /* Alternate setting number */

    0x00,                          /* Number of endpoints */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Interface 0, Alt. Setting 1: ISO IN endpoint. */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface Descriptor type */

    0x00,                          /* Interface number */

    0x01,                          /* Alternate setting number */

    0x01,                          /* Number of endpoints */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Endpoint descriptor for consumer EP */

    0x07,                          /* Descriptor size */

    CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */

    CY_FX_EP_CONSUMER,              /* Endpoint address and description */

    CY_U3P_USB_EP_ISO,              /* ISO endpoint type */

    0x00,(0x04 | ((CY_FX_ISO_PKTS - 1) << 3)),  /* Max packet size = 1024 bytes, mult CY_FX_ISO_PKTS */

    0x01                            /* Servicing interval for data transfers */

};

/* Standard full speed configuration descriptor */

const uint8_t CyFxUSBFSConfigDscr[] __attribute__ ((aligned (32))) =

{

    /* Configuration descriptor */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_CONFIG_DESCR,        /* Configuration descriptor type */

    0x22,0x00,                      /* Length of this descriptor and all sub descriptors */

    0x01,                          /* Number of interfaces */

    0x01,                          /* Configuration number */

    0x00,                          /* COnfiguration string index */

    0x80,                          /* Config characteristics - bus powered */

    0x32,                          /* Max power consumption of device (in 2mA unit) : 100mA */

    /* Interface 0, Alt. Setting 0: No endpoints. */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface descriptor type */

    0x00,                          /* Interface number */

    0x00,                          /* Alternate setting number */

    0x00,                          /* Number of endpoints */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Interface 0, Alt. Setting 1: ISO IN endpoint. */

    0x09,                          /* Descriptor size */

    CY_U3P_USB_INTRFC_DESCR,        /* Interface descriptor type */

    0x00,                          /* Interface number */

    0x01,                          /* Alternate setting number */

    0x01,                          /* Number of endpoints */

    0xFF,                          /* Interface class */

    0x00,                          /* Interface sub class */

    0x00,                          /* Interface protocol code */

    0x00,                          /* Interface descriptor string index */

    /* Endpoint descriptor for consumer EP */

    0x07,                          /* Descriptor size */

    CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */

    CY_FX_EP_CONSUMER,              /* Endpoint address and description */

    CY_U3P_USB_EP_ISO,              /* ISO endpoint type */

    0x40,0x00,                      /* Max packet size = 64 bytes */

    0x01                            /* Servicing interval for data transfers */

};

/* Standard language ID string descriptor */

const uint8_t CyFxUSBStringLangIDDscr[] __attribute__ ((aligned (32))) =

{

    0x04,                          /* Descriptor size */

    CY_U3P_USB_STRING_DESCR,        /* Device descriptor type */

    0x09,0x04                      /* Language ID supported */

};

/* Standard manufacturer string descriptor */

const uint8_t CyFxUSBManufactureDscr[] __attribute__ ((aligned (32))) =

{

    0x10,                          /* Descriptor size */

    CY_U3P_USB_STRING_DESCR,        /* Device descriptor type */

    'C',0x00,

    'y',0x00,

    'p',0x00,

    'r',0x00,

    'e',0x00,

    's',0x00,

    's',0x00

};

/* Standard product string descriptor */

const uint8_t CyFxUSBProductDscr[] __attribute__ ((aligned (32))) =

{

    0x08,                          /* Descriptor size */

    CY_U3P_USB_STRING_DESCR,        /* Device descriptor type */

    'F',0x00,

    'X',0x00,

    '3',0x00

};

/* Place this buffer as the last buffer so that no other variable / code shares

* the same cache line. Do not add any other variables / arrays in this file.

* This will lead to variables sharing the same cache line. */

const uint8_t CyFxUsbDscrAlignBuffer[32] __attribute__ ((aligned (32)));

/* [ ] */

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

There is no 'else' statement for:

if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))

Can you please use one more variable and check if the 'else' is executed at any point of time.

Regards,

Hemanth

Hemanth
0 Likes

there is a failures++ there...I can tell from the fact that failures is not increasing that I never go to that part of the code.

When no data is ready the code still goes into if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))

but len = 0

I test for that  doing

  if (PacketLength > 0){

}


I added code now that prints "empty pack" and depending on how much I throttle the FPGA that happens a lot or not.

This is the output for example of 8 packets per Xfer and a 2 bursts of 1024

Console.WriteLine("test")

for (int i = 0; i < PacketLength / 2048; i++)  //8 packets per Xfer

                            {

                                a = (USBpacket[i * 1 * 2048]);  //scanning the data to see if every 1024 bytes there is an increment

                                Console.WriteLine((a / 2).ToString());   //devide the incremented data by 16 to remove increment of 16 and make it increment of 1

                            }

As you can see...the testdata is not correct.******..(when xBuf == pkts all the time, the testdata is always ok 1,2,3,....)

length xBuf=  16384

length pkts=  10240

k= 1

test:

7****

8*****

36*****

9*****

100*****

*************************

length xBuf=  16384

length pkts=  10240

k= 2

test:

12

40

13

14

42

*************************

length xBuf=  16384

length pkts=  10240

k= 3

test:

107

17

18

46

19

*************************

These are the empty packages...

isoc.FinishDataXfer still returns TRUE...but len = 0

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

empty pack

*************************

In the next sequence the FPGA did have enough data ready so the xFer went OK

length xBuf=  16384

length pkts=  16384

k= 2

test:

22

23

24

25

26

27

28

29

*************************

length xBuf=  16384

length pkts=  16384

k= 3

test:

30

31

32

33

34

35

36

37

*************************

My complete relevant code ==

for (; bRunning; )

            {

                nIteration++;

                // WaitForXfer

                unsafe

                {

                    //fixed (byte* tmpOvlap = oLaps)

                    {

                        ovData = (CyUSB.OVERLAPPED)Marshal.PtrToStructure(handleOverlap.AddrOfPinnedObject(), typeof(CyUSB.OVERLAPPED));

                        if (!EndPoint.WaitForXfer(ovData.hEvent, 500))

                        {

                            EndPoint.Abort();

                            PInvoke.WaitForSingleObject(ovData.hEvent, 500);

                        }

                    }

                }

                if (EndPoint.Attributes == 1)

                {

                    CyIsocEndPoint isoc = EndPoint as CyIsocEndPoint;

                    // FinishDataXfer

                    if (isoc.FinishDataXfer(ref cBufs, ref xBufs, ref len, ref oLaps, ref pktsInfo))

                    {

                     

                        PacketLength = len;

                        ISO_PKT_INFO[] pkts = pktsInfo;

                        for (int j = 0; j < PPX; j++)

                        {

                            if (pkts.Status == 0)

                            {

                                XferBytes += pkts.Length;

                                Successes++;

                            }

                            else

                                Failures++;

                            pkts.Length = 0;

                        }

                        //if (PacketLength > 20480) { PacketLength = 20480; }

                        //INTERMEADIATE = xBufs;

                        USBpacket = xBufs;

                        //for (int i = 0; i < PacketLength / 1024; i++)

                        if (PacketLength > 0)

                        {

                            Console.WriteLine("length xBuf=  " + xBufs.Length.ToString());

                            Console.WriteLine("length pkts=  " + len.ToString());

                            Console.WriteLine("k= " + k.ToString());

                            Header_found = 0;

                   

                            Index = 0;

                      

                            for (int i = 0; i < 1024 * 8; i++)

                            {

                                USBpacket_rearranged_ISO = USBpacket;

                            }

                            countertje += 1;

                            int a = 0;

                            //SendUdp(65432, "127.0.0.1", 65432, USBpacket_rearranged_ISO);

                            Console.WriteLine("test:");

                            //Console.WriteLine(USBpacket_rearranged_ISO[200].ToString());

                            for (int i = 0; i < PacketLength / 2048; i++)  //8 packets per Xfer

                            {

                                a = (USBpacket[i * 1 * 2048]);  //scanning the data to see if every 1024 bytes there is an increment

                                Console.WriteLine((a / 2).ToString());   //devide the incremented data by 16 to remove increment of 16 and make it increment of 1

                            }

                            //Console.WriteLine(countertje.ToString());

                            //Thread.Sleep(1);

                            double variable = 3;

                            for (int i = 0; i < blocktime; i++)

                            {

                                variable = Math.Cosh(variable);

                            }

                        }

                        else

                        {

                            Console.WriteLine("empty pack");

                          

                        }

                        Console.WriteLine("*************************");

                        Console.WriteLine();

                     

                    }

                    else

                        Failures++;

0 Likes

BTW...I experimented a little with Thread.sleep(x) and a blocking routine to slow down the host.

That's what this was for.  

  for (int i = 0; i < blocktime; i++)

                            {

                                 variable = Math.Cosh(variable);

                            }

I was just stalling the cpu for an arbitrary time...

You can do some flow control inn this way but only when you only allow 1 xFer to Queue which leads to other problems.

Definely not a solution

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Please find the attachments.

1. In the attached project, CY_FX_ISO_PKTS = 1, CY_FX_ISO_BURST =4, DMA Buffer Size = 4KB, Number of DMA Buffers = 3.

1st packet (1024 byte) of 4KB buffer is filled with 0xAA, second with 0xAB, third 0xAC and fourth 0xAD. Other 2 DMA buffers are filled in the similar fashion.

2. When a DMA Buffer is committed to USB Socket, the data locations - 0, 1024, 2048 and 3072 are incremented by 1. I mean: For the first DMA buffer committed, those locations will have 0, 1, 2 and 3. For the 2nd DMA Buffer committed the locations would be 4, 5, 6, 7.

In the figure ZLP_starts.png, Transfer 32 is 3rd DMA buffer from the beginning of the test. So, you can see that the last packet of this DMA buffer has 0x0B as the first byte.

In the same figure, in Transfer 33, you can see that FX3 has no data after the 3rd DMA buffer. So ZLP is being sent. I have made this as Time Stamp 0. In the figure Next_data_packet.png you can see that the next data comes in. And the data is as expected - first byte being 0x0C and the data being 0xAA. You can see that this data packet arrived after 436mS (so FX3 is not occupying full bandwidth it requested for).

3. On the Host side, I start writing the first data byte of each 1024 packet into a file FinishData.bin. First_data_byte.png shows the screen shot of the same. The sequence is as expected.

In another version of the Host App, I print the second byte of the 1024 byte packet too along with the first one. Also I write 0xCC followed by number of ZLPs occurred. (FYI: ZLPs occurred when 0xCC is seen in the file is the number followed by 0xCC * 256)

First_and_second_data_byte_along_with_zlp_count_after_0xCC.png shows the same. You can see that the underlined byte after k th packet is the content of that k th packet. (0xCC 0x0D indicates 0x0D * 256 ZLPs occurred - you can ignore this as of now).

I am also attaching Form1.cs (Modified Streamer)

Note:

1. If you want to use the file, you need to

Create a file FinishData.bin in the path that you mention in the attached file (Refer to /****************add path below***********/ in the file attached)

2. If you want to write the number of ZLPs into the file, then you need to uncomment the code in /****************modify if required***********/

Regards,

Hemanth

Hemanth
0 Likes

I will run the code and try to understand what you are doing. I will report back immediately. 

0 Likes

Hi,

I've programmed my devkit with the .IMG from your code.

All transmissions I see are exactly the same size.

When I choose 8 packets per Xfer the packets are all 32kB (like you expect when you have no bottleneck)

pastedImage_3.png

The throughput of the transmission is +- 32MB/s if you have at least 2 Xfers in your Queue:

pastedImage_7.png

When I increase the Packets per Xfer the chunks seen in wireshark increase accordingly (16 Packets per Xfer):

pastedImage_8.png

The throughput does not increase though:

pastedImage_9.png

I think the rate at which you produce data is too fast to encounter my problem!

The Data producer is held back by the maximum speed you are able to attain with the settings chosen ( CY_FX_ISO_PKTS = 1, CY_FX_ISO_BURST =4, DMA Buffer Size = 4KB )

Indeed every 125uS a packet of size 4KB can be transmitted which is 8 times per mS and thus 4kB*8/mS =>  32MB/s

Your data "producer" is therefor still bottle necked by the USB busd and you do not encounter my problem. All transmissions are completely "filled" and "len" is always equal to size of xBuf

My problem only occurs when you produce LESS then the maximum attainable speed at the chosen settings.

For example, in my application i want to transmit at 9.6MB/s (I have applications which require much more but that's beside the point) and that is the amount of data my FPGA produces.

When I use your settings ( CY_FX_ISO_PKTS = 1, CY_FX_ISO_BURST =4, DMA Buffer Size = 4KB ) the throughput will be comprised of

- correct packets where len = size of xBuf (32kB in this case)   <= no problem

- empty packets where len = 0   <= no problem

- half packets where len =! 0 and < size of xBuf   <= PROBLEM

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

I think you have chosen ISOC OUT Endpoint instead of IN. Please check.

Regards,

Hemanth

Hemanth
0 Likes

ow...silly me...I'm not used to still have an OUT and IN so I didn't notice, sorry for that!

I choose the right one now but all i;m seeing is this:

pastedImage_0.png

Is that correct?

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

Yes.This looks correct. FX3 sends 4kB for every second. Record the trace for few seconds and analyze.

Regards,

Hemanth

Hemanth
0 Likes

Hi,

I have analyzed the data and see the packets you sent every second and the pattern that you put in them.

I doesn't reproduce my situation as there no empty or incomplete(not full) packets.

I'm not sure what I'm supposed to take away from this?

Does it mean that the  API indeed does not allow you to reliable get the data out of my streams

(even though in wireshark my data is completely logical) ?

Does this mean that I have to reprogram my FX3 to never ever send anything "incomplete"...which would make it behave more like your application?

That's what I need to know...Is my problem intended behaviour or not???

And if it is intended behaviour (which would be really weird in my opinion), what is the most efficient way to keep the FX3 from sending incomplete chunks?

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi,

In my test, I always send 4KB whereas requested data is 8(ppx) * 4KB = 32KB. So the data sent is not as requested. But I do not have non-1024 byte packets in the data. Do you have non-1024 byte sized packets in your stream? If so, I need to incorporate that in the test.

What can be found from this test is:

- If you send data less than requested in one transfer (which is equal to PPX*CY_FX_ISO_PKTS*CY_FX_ISO_BURST*1024) and is equal to 1K multiple, then FinishDataXfer behaves correctly.

a. Can you please also let me know which OS are you testing on? (If Windows 10 what is the build number?)

b. What is the version of cyusb3 driver that you are using?

Regards,

Hemanth

Hemanth
0 Likes

Hi,

I do not have non 1024 packets in my stream. Always multiples of 1024 or empty packets.

What can be found from this test is:

- If you send data less than requested in one transfer (which is equal to PPX*CY_FX_ISO_PKTS*CY_FX_ISO_BURST*1024) and is equal to 1K multiple, then FinishDataXfer behaves correctly.

I disagree. You only have 4kB messages which are that long becaus the FX3 firmware keeps them that small. I understand this can work but i do not know how to achieve this in a real world scenario which has a real GPIFII state machine attached to it.

If the solution to my problem is in fact changing the FX3s firmware...ok...so be it. I just can not get however that the API is not able to handle my data stream.

In the end, I do the same thing:  I send data less than requested but also equal to multiples of 1kB and while the data isn't in chunks of the same size, wireshark clearly shows the data inside to be perfectly normal.

I do not know why the GPIFII in my FX3 does not "save up" and waits to send anything before a enough data has been produced so that all it sends are either the "right" size or size 0 (when there is no data)

I just want to know why the API does not work like that when clealy the data is correct over the USB bus.

a. Can you please also let me know which OS are you testing on? (If Windows 10 what is the build number?)

I have seen the issue on all my computers. They all are windows 10 though and the one i'm on now is

pastedImage_3.png

b. What is the version of cyusb3 driver that you are using?

1.2.3.23

Best regards,

Mattijs

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Mattijs,

Can you please suggest the data size sequence that you might find in your application(assuming ppx=8; CY_FX_ISO_PKTS=1; CY_FX_ISO_BURST=4; DMA Buffer Size=4KB)? So that I will try to achieve the same to reproduce the problem?

Regards,

Hemanth

Hemanth
0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Mattijs,

I will try for this sequence - 1K, 2K, 3K, 4K, 1K...and let you know.

Regards,

Hemanth

Hemanth
0 Likes

Hi Hemanth,

I'm not sure that achieves my issue.

With a 1K (or <4kB) payload you are taking only a part of a DMA buffer (4burst*1024)

In my situation there is  logical and sequential data in chunks that are multiples of the size of the DMA buffer (4kB), but fewer than 8 of those (if you set packets per Xfer to 8 ).

Best Regards,

Mattijs

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Hi Mattijs,

Then I can try sending 4K, 8K, 12K, 16K, 4K,..which is 1 buffer, 2 buffers, 3 buffers, 4 and 1 again. Would this be okay?

Regards,

Hemanth

Hemanth
0 Likes

Hi,

I'm not sure. I hope so!

Regards,

Mattijs

0 Likes

I'm running your Firmware and changed it so it has a throughput more like my application (+-8MB/s) by changing your sleep(1000) statement to sleep(1) in the IsoSrcSinkAppThread_Entry loop.

The higher throughput makes it slightly easier to see what's going on in wireshark.

What I find a little strange is that there are so many failed transmissions?

pastedImage_2.png

Have you tested the sequence with your streamer app?

I will rewrite mine and see if I can get the pattern out of your data.

If i can't it means you reproduced my situation so i'm hoping i can't !

Regards,

Mattijs

0 Likes
Hemanth
Moderator
Moderator
Moderator
First like given First question asked 750 replies posted

Below is my streamer screenshot:

pastedImage_0.png

And the data taken out from FinishDataXfer:

pastedImage_1.png

Regards,

Hemanth

Hemanth
0 Likes