Forum Discussion

RHenr's avatar
RHenr
Icon for Occasional Contributor rankOccasional Contributor
1 day ago

Unable to receive OUT packet on USB in device mode

Hello,

I am trying to use USB on Cyclone V soc with tinyUSB. I am able to receive SETUP transaction and send device descriptor, but then I cannot receive and acknowledge the next OUT transaction.

I see that DOEPINT0.nakintrpt goes to 1, confirming that the device responds NAK to the OUT transaction, but I don't understand why. Here are the settings that are relevant to me :
GAHBCFG.dmaen = 0
DCTL.sgoutnak = 1
GRXFSIZ.rxfdep = 0x50
DOEPMSK.xfercomplmsk = 1
GINTMSK.rxflvlmsk = 1

Written before waiting for OUT packet:
DOEPCTL0.epena = 1
DOEPCTL0.cnak = 1
DOEPTSIZ0.xfersize = 0
DOEPTSIZ0.pktcnt = 1

I am lacking ideas of where to search or what could cause this behaviour. Is there anything to take care ?

Best regards,

Romain

2 Replies

  • RHenr's avatar
    RHenr
    Icon for Occasional Contributor rankOccasional Contributor

    Thanks,

    sorry, DCTL.sgoutnak is 0 and not 1. And I also have GINTSTS.goutnakeff = 0. The sequence you describe is what I do. I have tried setting DCTL.cgoutnak = 1 just in case but this does not change anything.

    The register values just after preparing the transfer are as follows : 

    gotgctl 0xd00c0
    gintsts 0x4000020 : PTxFEmp, NPTxFEmp
    gdfifocfg 0x1f802000
    dctl 0,
    dcfg 0x8100001
    dsts 0x18702
    doepctl0 0x80008000
    doepint0 0
    doeptsiz0 0x80000

  • FawazJ_Altera's avatar
    FawazJ_Altera
    Icon for Frequent Contributor rankFrequent Contributor

    Hello,

    From the register values you posted, the first thing I would check is this: DCTL.sgoutnak = 1

    SGOUTNAK means Set Global OUT NAK. It requests the controller to NAK OUT transactions globally. If this condition is active, the core can NAK the host’s OUT packet even if EP0 OUT has been enabled with: DOEPCTL0.epena = 1      DOEPCTL0.cnak = 1

    For the status stage after sending the device descriptor, the host normally sends an OUT zero-length packet on EP0. Your DOEPTSIZ0 values are reasonable for that case: DOEPTSIZ0.xfersize = 0       DOEPTSIZ0.pktcnt = 1

    However, before expecting the packet to be accepted, you should clear the global OUT NAK condition: DCTL.cgoutnak = 1

    Then check the actual status bit: DCTL.goutnaksts == 0

    A reasonable EP0 OUT status-stage sequence is:

    DOEPTSIZ0 = DOEPTSIZ0_PKTCNT; // pktcnt = 1, xfersize = 0

    DOEPINT0 = 0xffffffff; // clear stale W1C endpoint interrupts

    DOEPCTL0 = read(DOEPCTL0) | EPENA | CNAK;

    DCTL = read(DCTL) | CGOUTNAK; // clear global OUT NAK

     

    After this, verify:

    DCTL.goutnaksts = 0

    DOEPCTL0.naksts = 0

    DOEPCTL0.epena = 1

    DOEPCTL0.stall = 0

     

    The important distinction is that DOEPCTL0.cnak clears the NAK state for EP0 OUT only, while DCTL.cgoutnak clears the controller-level OUT NAK. Both have to allow the transfer.

    So your DOEPINT0.nakintrpt = 1 observation is consistent with the controller still being in an OUT NAK state. I would start by removing the SGOUTNAK from the receive path, issuing CGOUTNAK before waiting for the OUT packet, and checking GOUTNAKSTS rather than assuming the endpoint enable alone is enough.

    Hope this might help,

    Fawaz.