XferData() may return FALSE in short-packet BULK IN application

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

cross mob
GlWa_4148656
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

Hi all

Here`s a strange problem, XferData() may failed when slave endpoint sent a short packet with a particular length.

we`re trying to transfer data from FPGA to PC host by FX3, FX3 runs with a slave FIFO firmware, EP2 IN(0x82) is initiated in FX3 for BULK IN transferring, in each transfer test, firstly, PC host invoke XferData() to generate a BULKIN transfer(bufLen is always set 16384, pktMode is set TRUE) and waiting for a packet from FX3, then our FPGA send a short packet to FX3, at each test,packet length is different, short packet is ended by asserted the PKT_END pin .

XferData() return TRUE in most of tests, but failed at  several test, after research of these failed tests, we found that if FPGA send packet with length of 2048,4096 or 8192, XferData() retrun FALSE and timed out happened, such a werid thing. any body can help me ?

BTW,  these two results may help you:

1.XferData() can be successful when actual length is 8191 or 8193, but if FPGA send 8192 bytes to FX3, XferData() must be failed.

2.if we set 8192 to bufLen parameter, XferData() return TRUE when FPGA send 8192 bytes to FX3.

here`s main part of BULKIN transfer code at PC host side(VS2013):

q.JPG

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

Hi,


1. can the "multiple of 1024" rule be broken by modifing any MCU setting in firmware?  or it is a hard rule belong to USB3.0 and must be obeyed ?


>> This cannot be changed and is common with any USB microcontroller


2. as method described in that link, BULK OUT partial packet can be successfully transferred from host to GPIF II only if host attach a ZLP after sending partial packet, can the ZLP method be used in BULK IN to break the "multiple of 1024" rule ?


>> In this question, by partial packet I think you mean less than requested data (in your case 16K) and multiple of 1024. In that case, yes, you can send a ZLP at the end so that the partial data is returned by the API.

Note: In GPIF state machine, when you use COMMIT action along with last IN_DATA, then partial data will be committed (for ex 8192bytes, when buffer size is 16K).  But if you do COMMIT action alone in a separate state after the state in which you did IN_DATA to acquire 8K, then 8K will be committed and an extra buffer (ZLP) will be committed.

            For example: When Host requested 16K, FX3 sent 8K followed by ZLP, then xferdata will return with 8K data.

See: https://community.cypress.com/t5/USB-Superspeed-Peripherals/Receiving-a-Zero-Length-Packet-for-every...


3. if "multiple of 1024 data must be lost" is a hard rule and must be avoided,  are there some usual ways to solve this problem ?  separate bad-length packet into small good-length packet ?  or extend partial packets to full packet by attaching 0 after valid data ?(that may slow the speed of usb transfer)


I think answer to question 2 will answer this. And also note that using ZLPs often will reduce the USB throughput. But consider this case: You request 16K from host. In fx3 valid data is only 8K. In this case if you append rest 8K with zeros and commit as you said, then xferdata api would get the requested amount. But you will have to manage a way to find out howmuch valid data it has.

Regards,

Hemanth

View solution in original post

0 Likes
9 Replies
GlWa_4148656
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

we checked NtStatus when XferData() failed, the value was 0xC0000120, in windows error code, it means "The I/O request was canceled".

 

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

Hi,

The behavior is expected. You can refer to following lines of below KBA:


In this configuration, the buffer would be committed to GPIF when any of the following conditions are met:
a. Entire 16 KB buffer is filled by USB.
b. A partial packet is received from USB (Note: When this happens the amount of data filled in the buffer will not be a multiple of
1024 bytes for USB 3.0 and 512 bytes for USB 2.0).
c. A zero-length packet is received from USB.


KBA: https://community.cypress.com/t5/Knowledge-Base-Articles/Data-sent-from-Host-over-USB-is-not-Committ...

Above KBA is for transfer direction Host PC to FX3. But above quoted lines applies to FX3 to Host as well. Above lines should be interpreted as - Xfer data returns in the mentioned three conditions - a. entire requested data is obtained from fx3 b. short packet is received (not max pkt size multiple) c. ZLP is received

Hope it is clear.

Regards,

Hemanth
0 Likes

thanks for reply, but mine is BULK IN application, not BULK OUT, all things in above link talk about BULK OUT,  and i still don`t figure out a way ,which can solve my problem, from that link. if you can explain those  FX3 rules based on my BULK IN problem, that will be fine for me.

and after reading content from above link, "zero-length packet" seems to be a important part for  partial packet transfer,  how does the ZLP work ?

 

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

Hi,

What I meant is as follows:

For Bulk IN transfers,

XferData returns without timeout error under below conditions:

a. entire requested data (in your case 16384) is received

b. short packet is received (which is < 1024 size packet)

c. zero length packet.

But, for example, fx3 sends a multiple of 1024 and less than 16384, like 8192, then host API will return error after timeout set expires.

Regards,

Hemanth
0 Likes

thanks Hemanth, your answer clearly explain problem that i met.

based on your answer, those are three my considerations that i wish you could give me your answers or suggestions : 

1. can the "multiple of 1024" rule be broken by modifing any MCU setting in firmware?  or it is a hard rule belong to USB3.0 and must be obeyed ?

2. as method described in that link, BULK OUT partial packet can be successfully transferred from host to GPIF II only if host attach a ZLP after sending partial packet, can the ZLP method be used in BULK IN to break the "multiple of 1024" rule ?

 

3. if "multiple of 1024 data must be lost" is a hard rule and must be avoided,  are there some usual ways to solve this problem ?  separate bad-length packet into small good-length packet ?  or extend partial packets to full packet by attaching 0 after valid data ?(that may slow the speed of usb transfer)

 

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

Hi,


1. can the "multiple of 1024" rule be broken by modifing any MCU setting in firmware?  or it is a hard rule belong to USB3.0 and must be obeyed ?


>> This cannot be changed and is common with any USB microcontroller


2. as method described in that link, BULK OUT partial packet can be successfully transferred from host to GPIF II only if host attach a ZLP after sending partial packet, can the ZLP method be used in BULK IN to break the "multiple of 1024" rule ?


>> In this question, by partial packet I think you mean less than requested data (in your case 16K) and multiple of 1024. In that case, yes, you can send a ZLP at the end so that the partial data is returned by the API.

Note: In GPIF state machine, when you use COMMIT action along with last IN_DATA, then partial data will be committed (for ex 8192bytes, when buffer size is 16K).  But if you do COMMIT action alone in a separate state after the state in which you did IN_DATA to acquire 8K, then 8K will be committed and an extra buffer (ZLP) will be committed.

            For example: When Host requested 16K, FX3 sent 8K followed by ZLP, then xferdata will return with 8K data.

See: https://community.cypress.com/t5/USB-Superspeed-Peripherals/Receiving-a-Zero-Length-Packet-for-every...


3. if "multiple of 1024 data must be lost" is a hard rule and must be avoided,  are there some usual ways to solve this problem ?  separate bad-length packet into small good-length packet ?  or extend partial packets to full packet by attaching 0 after valid data ?(that may slow the speed of usb transfer)


I think answer to question 2 will answer this. And also note that using ZLPs often will reduce the USB throughput. But consider this case: You request 16K from host. In fx3 valid data is only 8K. In this case if you append rest 8K with zeros and commit as you said, then xferdata api would get the requested amount. But you will have to manage a way to find out howmuch valid data it has.

Regards,

Hemanth
0 Likes

Hi Hemanth

thanks for your answers  and suggestions, at least i find a way to transfer data stably by padding 0 after valid data, and valid data will be packeted to frame.

i also tried the ZLP way: in each ZLP-send transfer, FPGA send a ZLP after sending partial data(length is 2048), host app initiate xferData() to receive data and printf the length or error information.

i repeated above transfer three times, results are weird, here`s  print of results :

packet_with_zlp_results.JPG

1st transfer : host app only received one packet of correct 2048 data.

2nd transfer : host app received a ZLP after a packet of correct 2048 data.

3rd transfer : xferData returned FALSE and transfer failed, i also read "pUSB->BulkInEndPt->NtStatus", it showed 0xC0000001.

 

in all transfers, i have checked GPIF-II timing on FPGA side and confirmed timing are all OK.

do you know why ?

here`s a part of my app test code associated with BULK IN tranfser :

bulk in of host code.JPG

here`s slave FIFO state machine of GPIF II :

FSM_GPIF_II.JPG

 

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

Hi,

I think your DMA buffer size is 16K bytes. In that case, if FPGA writes 2Kbytes data to buffer and then execute ZLP state, then 2 buffers will be committed to USB. First with 2K bytes. Second a zero length buffer. But on the host side xferdata call with 16K request, will return with only 2Kbytes.

What is the DMA buffer count in your firmware?

In above test, please give me more details about the three transfers (like what was done on GPIF interface etc)

Regards, 

Hemanth
0 Likes

Hi Hemanth

You`re right, DMA buffer size is 16kB in firmware, and finally i decided to abort the ZLP way to transfer partial length packet since it`s tough to handle rules in firmware and it also wasted me a lot of time.

Now i`m using the easy padding way, which extend partial data to full 16kB data with padding 0s, to transfer data , it works very well.

Thanks again, your previous explaining about  length rules of USB transfer is accurate and usefull,  it help me to choose the right way for my USB transfer, and  i`ll choose that reply as the right answer.

0 Likes