Re-invoke old post https://community.cypress.com/thread/37344

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

cross mob
bhchc_3447926
Level 2
Level 2

There are some persons over cypress forum which close the thread. I don't know why the moderator allows them.

I would like to reinvoke this post,

FX3 Interrupt Endpoint + Custom Linux Driver weird behaviors

Recently I came across this problem once again and after debugging carefully I found two major points.

1) The fast interrupt which is working fine with our custom Linux and Windows Device Driver, the driver can receive interrupt data on interrupt EP.

Here fast interrupt means, when I perform some activity on our hardware board to generate an interrupt, it produced within a couple of micro/mili seconds.

For example, FPGA+microcontroller subsystem on board, let say I2C/SPI peripheral attached to the microcontroller and I need to configure that peripheral so for that, I need to write 1st on FPGA register and FPGA logic will start communication with Microcontroller and ultimately microcontroller will start to initiate I2C/SPI xfer. After complete such xfer, it will raise interrupt to FPGA and FPGA toggle GPIO to FX3 chip and put interrupt hex code toward interrupt Endpoint. such operation in my case takes few milliseconds.

2) The slow interrupt which is not working fine with our custom Linux and Windows Device Driver, the driver cannot receive interrupt data on interrupt EP.

Here slow interrupt means, when I perform some activity on our hardware board to generate an interrupt, it produced after a couple of seconds.

For example, If I have DDR4 memory attached on board and I need to scan entire memory to validate that memory is working fine or not. For that I have to configure register on board to start scanning, now custom FPGA logic will start scanning and after 7-8 seconds it will produce test done interrupt via GPIO toggle to FX3 chip.

To eliminate above problem I have two solution.

Each solution is to raise a question for me, I would expect an answer respectively from this forum.

1) Solution - 1 (Actaully workaround for me as of now):

If I fire below version of dummy vendor command before generating a slow interrupt(DDR4), I can receive interrupt on interrupt endpoint(DDR4 test done interrupt).

                    case 0xBF:

                        CyU3PDebugPrint(4,"Dummy 0xBF cmd received\r\n");

without request completion.

the interesting fact over here is that, if I fire below version,

                    case 0xBF:

                        CyU3PDebugPrint(4,"Dummy 0xBF cmd received\r\n");

                        CyU3PUsbAckSetup();

with request completion than on interrupt endpoint, the slow interrpt is not received.

The fast interrupt is working fine if I fire or not fire. Which is actually expected.

Q - What is the relationship between vendor command with no request completion and a slow interrupt is coming to host/PC?

2) Solution-2 (I believe this is an actaul solution):

If I change bInterval field of endpoint descriptor from 0x04 to 0x0B then all interrupt coming fine and I don't need above kind of workaround.

    /* Endpoint descriptor for consumer EP2 (0x82) */

0x07,                           /* Descriptor size */

CY_U3P_USB_ENDPNT_DESCR,        /* Endpoint descriptor type */

CY_FX_EP_2_IN,              /* Endpoint address and description */

CY_U3P_USB_EP_INTR,             /* Bulk endpoint type */

0x02,0x00,                      /* Max packet size = 32 bytes */

//0x04, OLD one which is not working fine for slow interrupt

    0x0B,                           /* Working fine for both fast and slow interrupt ... Servicing interval for data transfers : 1 - Every micro-frame. */

/* Super speed endpoint companion descriptor for consumer EP2 (0x82) */

0x06,                           /* Descriptor size */

CY_U3P_SS_EP_COMPN_DESCR,       /* SS endpoint companion descriptor type */

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

0x00,                           /* Max streams for bulk EP = 0 (No streams) */

0x02,0x00,                      /*  Bytes per Service interval for the Int EP : 0 for bulk */

Now above solution raise question,

Q - Why the higher value of polling interval working fine for slow interrupt?

I know 0x04 bInterval value means 1ms as per USB 3.0 spec. formula (2^(bInterval -1) * 125uS)

and 0x0B bInterval value means 128ms.

Why it is affacting and all kind of interrupt I can received on interrupt pipe is mystery for me.

I hope this time I can get good answer!

0 Likes
1 Solution

Finally I found the answer for such problems.

After carefully looking at code(basically I derivied my code from BulkSrcSink example.) I found that the MainAppThread function setup command event wait timeout is 10ms seconds. and during this time FX3 is inside U2 state of LPM and then after it will go into active power state called U0. due to this reason my interrupt pipe with below 10ms interrupt arrival will work fine but more than 10ms size of interrupt able to detect by GPIO thread but during this time FX3 inside power down mode Host will not received IN packets.

As a final soultion, I have use CyU3PUsbLPMDisable() API at SET_CONF setup reqst at the time of enumuration. So everythings works perfectly fine. My USB device is self powered so I dont required power down feature in my product.

View solution in original post

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

Hi,

Apologies for locking the thread. After the project was shared I assumed that, with the Linux driver code modification, you were able to get the interrupt data.

As the problem still persists we can work for finding the root cause.

I note that when the servicing interval is 0x0B (which would be 250mS) the interrupt endpoint data is received by the Windows/Custom Driver.

Can you please let me know if you already made sure that the Interrupt endpoint data, is not sent out by the device, even though you call CyU3PDmaChannelCommitBuffer() API. (I mean the interrupt data that is generated after 7-8 Sec)

- If not is it possible for you to take a USB trace(using Hardware analyzer if available/Software Analyzer) and check whether that data is sent out over Interrupt Endpoint or not?

Regards,

Hemanth

Hemanth
0 Likes

Hey HemanthR_06

First of all big thanks for coming to the discussion once again.

So I have tried all values 1-16 for bInterval field, and things are working fine after value 11 or 0x0B.

CASE -1 :

So 1st of all... let's talk about the value of bInterval  from 1 to 10,

In this case, when I use Lecroy Voyager M3i USB Analyser, I have always seen NAK packets from Device Even though at the time when an interrupt comes from FPGA via GPIO and CyU3PDmaChannelCommitBuffer() do their job and debug print also say that interrupt has been sent toward specified UIB socket. but why USB analyzer show me NAK that I don't know. For fast interrupt, I can see Interrupt IN packets on analyzer software but slow interrupt has NAK packet only.

Here interesting point is that either Linux or Windows driver both facing NAK packets when interrupt IN packet not avail from device and Interrupt IN packet avail. from the device when fast interrupt delivered from device to host. problem is only with the slow interrupt. So no question or doubt about host controller driver whether the host is polling perfectly or not.

CASE -2 :

At value 11,

In this case, I can receive interrupt IN packet at the time when device delivers interrupt data to host else it will send NAK. which is I think expected.

Although, I thought about higher polling frequency(lower bInterval )have less error to miss any interrupt IN packet but here less frequency(higher bInterval ) have more accuracy(Maybe I'm wrong for this sentence ... correct me if I wrong.)

But why all these happened by just changing polling interval and "what the hell this TIMING" issue is I really don't know. I have also looked into TRM doc to find registers but that task becomes too much complicated I believe.

0 Likes

Hi HemanthR_06

I'm trying to correlate Below link with my problem. Is it right path of debugging this problem.

https://www.renesas.com/in/en/solutions/key-technology/connectivity-wired/usb/about-usb/usb1-1/usb1-...

0 Likes

Hi,

The above link only talks about the USB 2.0 packet organization.

Can you please attach here the USB trace that you have taken where the Interrupt data is missing: That means, while you are recording the USB trace, CyU3PDmaChannelCommitBuffer() should be called corresponding to 'slow interrupt' that you are referring to.

Regards,

Hemanth

Hemanth
0 Likes
lock attach
Attachments are accessible only for community members.

Below is a snapshot of fast interrupt which receives 2-byte data.

fast_interrupt.PNG

and below is related Slow interrupt which has all the time NAK from the device even Commitbuffer API done their job.

slow_interrupt.PNG

Also attaching the entire log during recording buffering on. I have filter it down to 0x82 interrupt endpoint only.

0 Likes

Finally I found the answer for such problems.

After carefully looking at code(basically I derivied my code from BulkSrcSink example.) I found that the MainAppThread function setup command event wait timeout is 10ms seconds. and during this time FX3 is inside U2 state of LPM and then after it will go into active power state called U0. due to this reason my interrupt pipe with below 10ms interrupt arrival will work fine but more than 10ms size of interrupt able to detect by GPIO thread but during this time FX3 inside power down mode Host will not received IN packets.

As a final soultion, I have use CyU3PUsbLPMDisable() API at SET_CONF setup reqst at the time of enumuration. So everythings works perfectly fine. My USB device is self powered so I dont required power down feature in my product.

0 Likes

Hi,

Good to know that the issue is root caused. Calling CyU3PUsbLPMDisable() in SET_CONF handling may cause the USB Compliance test to fail (if you going for USB certification for your product).

So, you can call CyU3PUsbLPMDisable() when you start making data transfers and enable it back when you stop doing the data transfers.

You can refer to source code of the below App Note to see how it is done:

https://www.cypress.com/documentation/application-notes/an75779-how-implement-image-sensor-interface...

Regards,

Hemanth

Hemanth

Sure... I will go with your recommendation

0 Likes