Force Link Training

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

cross mob
GuSc_293616
Level 3
Level 3
5 likes given First like given

Prelude:

Based on USB3.1 spec. ("State Diagram of the Link Training and Status State Machine") a link training is done before link power mode return to U0 from U1/U2. The SDK function CyU3PUsbSetLinkPowerState only allows the return to U0 mode, with the exception of the host requesting the switch to U1/U2 also U1/U2. If the device wants to change, this does not seem possible.

Another way is "Error, Directed", which can be observed via the event CY_U3P_USB_EVENT_LNK_RECOVERY.

Problem:

In our case, if the USB3.1 cable is "bad" with about 40 phy errors / second regular link errors and CY_U3P_USB_EVENT_LNK_RECOVERY messages. After an indefinite time of 2-10h no link errors can be observed (according to CyU3PUsbGetErrorCounts), but still around 20 phy errors / second. Therefore CYU3P_USBEP_SS_RESET_EVT occur frequently, so that the data transfer has to be restarted. As long as the event (CYU3P_USBEP_SS_RESET_EVT) occurs less than once per second, the problem can be compensated by error handling. Afterwards, one cannot transfer any image data stream from our device any more. If you now perform a USB reconnect, the problem of the CYU3P_USBEP_SS_RESET_EVT events will be fixed.

USB-Reconnect:

CyU3PUsbLPMEnable();

CyU3PConnectState(CyFalse, CyTrue);

CyU3PThreadSleep(25);

CyU3PConnectState(CyTrue, CyTrue);

CyU3PUsbLPMDisable();

The assumption is that the USB reconnect solves the problem temporarily through its link training.

Is there any way to force a link training by device, only to be sure it's a missing link training is the problem?

Information:

We use SDK 1.3.3 and also testet with SDK 1.3.4 but this seems less stable than the old one.

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

Hello Heiko,

I have modified the Fx3AppGcc (second stage boot loader) firmware to set the tx swing to 120  and I have added a vendor command  (0x99) in the application firmware to read this register to check whether the register is set with that value or not.

Also, the boot loader settings are such that there will not be re enumeration (on programming with application firmware)

The application firmware that i am using is bulksrcsink.

Please refer to the attachments.

Please let me know if this helps

Regards,

Rashi

Regards,
Rashi

View solution in original post

0 Likes
16 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

For debugging the problem, we would need to the USB event logs.

1) Please use the CyU3PUsbInitEventLog API in your function. From the logs we can know which through which states the USB is going through. Please share the logs. Please refer to the bulksourcesink example in the SDK or the FX3 API Guide.

2) Also, you can try geting the link state when the event CY_U3P_USB_EVENT_LNK_RECOVERY occurs by calling CyU3PUsbGetDevProperty and passing the first argument CY_U3P_USB_PROP_LINKSTATE

3) In the event handler of the CY_U3P_USB_EVENT_LNK_RECOVERY, blocking functions cannot be used (eg: debug prints). Please confirm.

We can force the device through link training by calling the CyU3PConnectState multiple times.

Please let me know the results

Regards,

Rashi

Regards,
Rashi
0 Likes
lock attach
Attachments are accessible only for community members.

Hello,

1.) as requested, I have created a "event log" and attached two cases where no link errors but super speed reset events occur.

2.) there is also a file attached with the states of the link state machine during CY_U3P_USB_EVENT_LNK_RECOVERY .

3.) no blocking function is called within event handler of the CY_U3P_USB_EVENT_LNK_RECOVERY

I have a additional question, CyU3PUsbInitEventLog only work for debug build? All my attempts to use it with our release build firmware, result in a empty event log buffer.

0 Likes

Hello,

Apologies for the late reply.

From the event log i found that there is USB log 0xAB

CYU3P_USB_LOG_EPM_RESET         (0xABu)  /* Endpoint Memory Block Reset. */

And the super speed reset events can be due to this :

Can you try handling this event in the firmware . You can refer to this code snippet in the bulk source sink example.

void

CyFxBulkSrcSinkApplnEpEvtCB (

        CyU3PUsbEpEvtType evtype,

        CyU3PUSBSpeed_t   speed,

        uint8_t           epNum)

{

    /* Hit an endpoint retry case. Need to stall and flush the endpoint for recovery. */

    if (evtype == CYU3P_USBEP_SS_RETRY_EVT)

    {

        glSrcEpFlush = CyTrue;

    }

}

CY_U3P_USB_EVENT_LNK_RECOVERY: This event will not be raised if the recovery is entered as part of a transition from Ux to U0. This event is raised from the interrupt context.

Also, can you try programming the bulksourcesink example from the SDK and check whether it is working or not.

I have a additional question, CyU3PUsbInitEventLog only work for debug build? All my attempts to use it with our release build firmware, result in a empty event log buffer

>>I will confirm it and get back to you

Please let me know the results when programming with bulksourcesink example.

Regards,

Rashi

Regards,
Rashi
0 Likes
lock attach
Attachments are accessible only for community members.

Hello,

>> Can you try handling this event in the firmware . You can refer to this code snippet in the bulk source sink example.

At the moment we use the following handling:

static void CyFxApplnEpCallback(CyU3PUsbEpEvtType evtype, CyU3PUSBSpeed_t usbSpeed, uint8_t epNum)

{

    if (evtype == CYU3P_USBEP_SS_RESET_EVT)

    {

    // EP message FX3->PC consumer or EP data out FX3->PC consumer

    if ((epNum == FX3_EP_MSG) || (epNum == FX3_EP_DOUT) || (epNum == FX3_EP_IMG))

    {

      g_dwSSRE_InEpStall++;          // only to track the count of events

      CyU3PUsbStall(epNum, CyTrue, CyFalse);

    }

    else if ((epNum == FX3_EP_CMD) || (epNum == FX3_EP_DIN))

    {

      g_dwSSRE_OutEpStall++;    // only to track the count of events

      CyU3PUsbStall(epNum, CyTrue, CyFalse);

    }

}

You mentioned only no blocking functions to use, is CyU3PUsbStall blocking function for you?

>> Also, can you try programming the bulksourcesink example from the SDK and check whether it is working or not.

I put the bulksourcesink example on our device (compiled with SDK_1_3_4) and used the "c++ bulkloop application". The transfer became very slow after a very short time (5-10seconds) than mostly only failure transactions occur. After a "reset the pipe" with "USB control center" I can start the "c++ bulkloop application" again with the same behaviour (short time successful transfer then only errors).

I tried it with SDK_1_3_3 also see Error_03_sdk133.pnp.

Regards,

Heiko

0 Likes

Hello Heiko,

From the event logs you shared in previous post, there is a event (0xAB) which is caused due to Endpoint Memory Block Reset and 0xAF (Endpoint under run event)

This event is generated when CyU3PUsbResetEndpointMemories() function is called. This is when there is under run on any of the endpoints or the host has terminated the burst.

Please refer to CyFxApplnUSBEventCB function in GPIF to USB example of SDK or the CyFxBulkLpApplnUSBEventCB  function of cyfxbulklpautomanytoone example.

Please confirm that you are getting this event. Event Data (EVData) will give which endpoint is causing the event.

Can you share the debug prints/logs when programming with Bulksrcsink example and GpifToUsb example.

If possible can you share your firmware so that we can reproduce the the problem at our end.

Regards,

Rashi

Regards,
Rashi
0 Likes
lock attach
Attachments are accessible only for community members.

Hello Rashi,

after some time I see CY_U3P_USB_EVENT_EP_UNDERRUN events. but ignored them till now. Now I call CyU3PUsbResetEndpointMemories like cyfxbulklpautomanytoone example, but without positive effect.

The monitored endpoint underrun events occure every time on control endpoint 0, which I don't use directly (except for

CyFxBulkSrcSinkApplnUSBSetupCB see Bulksrcsink example).

I modified the Bulksrcsink example so it will behave like our device, so you see what and how we do within our firmware. Don't be surprised about the empty states of the GPIF state machine, but I have to remove the hardware dependencies. Also I adapted the Bulkloop example to have a host counterpart to the firmware.

Hopefully this helps..

During my tests I end up with a frozen device. It seem it still receive command packets und process them, because command response messages with the correct size are received, but there content for each byte is 0xFF. The LogDump function which uses the control endpoint also return only 0xFF as data content. If I close the host application I'm unable to restart them because usb descriptors request are also answered with all data bytes set to 0xFF. At this point only a power cycle of the device helps.

Btw: It seem SDK 1.3.3 is much more stable than SDK 1.3.4 in our error cases. (much more stable => it takes longer till freeze)

Maybe it is good to mention that VBUS is about 4.35V with the problematic cable. At slightly higher VBUS voltages of approx. 4.5V there will be no permanent disconnection abort.

Regards,

Heiko

0 Likes

Hello,

Please refer to fourth point of 2.3 of FX3_SDK_troubleshooting_guide i.e. USB Data Corruption

I found that in the firmware bulksrcsink you are handling the CYU3P_USBEP_SS_RESET_EVT by stalling the endpoint. Also this stall needs to be cleared by handling clear feature  request for endpoint.(this is also handled)

Can you check this firmware with newer correct cable and let me know the results.

Regards,

Rashi

Regards,
Rashi
0 Likes
lock attach
Attachments are accessible only for community members.

Hello,

As you were having a bad cable, FX3 is operating on a USB 3.0 link with poor signal quality, and there are anumber of protocol level CRC errors and retries happening leading to CYU3P_USBEP_SS_RETRY_EVT . This could lead to a state where wrong data can be sent  on IN endpoints.This happens due to a known defect in the way the FX3 device handles a pre mature burst transfer termination by the host.

CYU3P_USBEP_SS_RETRY_EVT event is internally handled by doing Endpoint Memory reset (this why you got AB in the event logs) and then CYU3P_USBEP_SS_RESET_EVT. You don't have to handle CYU3P_USBEP_SS_RETRY_EVT in the application.

cyu3usb.h mentions

CYU3P_USBEP_SS_RESET_EVT = 256      /**< USB 3.0 endpoint reset event. A stall recovery is required. */

CYU3P_USBEP_SS_RETRY_EVT = 16,      /**< An ACK TP with the RETRY bit was received on the IN endpoint. */

So, when CYU3P_USBEP_SS_RESET_EVT  event occurs all IN endpoints should be stalled

So you need to handle this in your firmware by including this code in the firmware

Fom gpiftousb example

    if (evtype == CYU3P_USBEP_SS_RESET_EVT)

    {

        if (epNum == CY_FX_EP_CONSUMER)

        {

            CyU3PDebugPrint (2, "Halting USB Streaming EP: %d\r\n", BulkRstCnt++);

            CyU3PUsbStall (CY_FX_EP_CONSUMER, CyTrue, CyFalse);

        }

        if (epNum == CY_FX_EP_LOOP_IN)

        {

            CyU3PDebugPrint (2, "Halting USB Loopback EP: %d\r\n", LoopRstCnt++);

            CyU3PUsbStall (CY_FX_EP_LOOP_IN, CyTrue, CyFalse);

        }

    }

The recommended recovery from the CYU3P_USBEP_SS_RESET_EVT  procedure is to STALL the endpoint, and then stop and restart the DMA data path when the CLEAR_FEATURE request is received.

so you also need to add this code (aatachement)

        * When a clear feature is received,the previous transfer has to be flushed and cleaned up. This is done at the protocol level. Since this is just a loopback operation, there is no higher level protocol. So flush the EP memory and reset the DMA channel associated with it. If there are more than one EP associated with the channel reset both the EPs.

As in your response, you mentioned with good cable the application is stable, it is recommended to use good cable to have good signal quality.

Regards,

Rashi

Regards,
Rashi
0 Likes

Thanks for the detailed explanation and the provided code. I will check and update our firmware application. The thing with the good cable is not so easy, because both are from from the same supplier, one used for quite a while, the other brand new. We have not the problem that it doesn't work in generally, it starts to produce error more often over the time. If the error rate is to high out customer replace the cable. Unfortunately, this is not a permanent solution.

I'm done with the tests I will inform you.

0 Likes

Hello,

Also try using CyU3PUsbSetTxSwing ( uint32_t swing ) API. This API sets the Tx amplitude used by FX3 on the USB 3.0 interface.

This API is expected to be called before calling the CyU3PConnectState() API to enable USB connections. By default the swing value is 90  i.e 0.9V (device is tested with default swing only). swing value should be less than 1.28V (128). You can refer FX3APIGuide in the SDK for more details.

Please let me know if this helps.

Regards,

FRashi

Regards,
Rashi
0 Likes

I still testing all the firmware changes and will answere you end of the week, the advice with CyU3PUsbSetTxSwing seems also have positive effects. A loop test have been started to find a good setting (one with no or few errors) with new and "old" cables... I hope to have all results by the end of the week.

Regards,

Heiko

0 Likes

Hello Rashi,

I'm nearly done with my tests and preparing our final firmware. We generally use a bootloader and start from there the application. The Bootloader connect to the host system (via) and provide update capabilities, on host request the device application is started.
Because USB - connection is already established we can't use CyU3PUsbSetTxSwing at application level without reconnect the device, but within the bootloader SDK I cann't find a function to set TxSwing.

You have I idea to solve this problem?

Regards,

Heiko

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

Hello Heiko,

I have modified the Fx3AppGcc (second stage boot loader) firmware to set the tx swing to 120  and I have added a vendor command  (0x99) in the application firmware to read this register to check whether the register is set with that value or not.

Also, the boot loader settings are such that there will not be re enumeration (on programming with application firmware)

The application firmware that i am using is bulksrcsink.

Please refer to the attachments.

Please let me know if this helps

Regards,

Rashi

Regards,
Rashi
0 Likes

Hallo Rashi,

I see you write the USB3LNK->lnk_phy_tx_trim directly short before you call CyFx3BootUsbConnect.

Code:

*tx_swing =  ((*tx_swing & ~(0x001fc000)) | (swing << 14));

CyFx3BootUsbConnect (CyTrue, CyTrue);

Based on the SDK1.3.1 - BootAPI source files, the FX3 register USB3LNK->lnk_phy_tx_trim is

written within HandleUsbLnkInterrupt(void) function. If I don't misunderstood the code the register

is written on device state "connect" ( if (devState & CY_U3P_UIB_LTSSM_CONNECT) ), which is caused by

calling CyFx3BootUsbConnect or isn't it? So in my opinion on connect event the default BootAPI TxSwing

value is written to USB3LNK->lnk_phy_tx_trim and your changes overwritten.

I wrote a patch for SDK1.3.3 and SDK1.3.4, which modifed the loaded binary of HandleUsbLnkInterrupt

before I call CyFx3BootUsbConnect. The patch replaces the default value at BootAPI code with my TxSwing

value. On connect the modified default value is used.

This seem to work for me. Thanks.

0 Likes

Hello Heiko,

In the SDK 1.3.4, the USB3LNK->lnk_phy_tx_trim in USB Phy is enabled and CyU3PUibLnkIntrEvtHandler.

And as per the Fx3 API guide, CyU3PUsbSetTxSwing API is expected to be called before CyU3PConnectState()

In the firmware i shared, there will be no re-enumeration. This is the result for setting Tx swing to 120. The register is read by passing vendor command 0x99

tx_swing1.PNG

Regards,

Rashi

Regards,
Rashi
0 Likes

Ok, Thanks

0 Likes