cancel
Showing results for 
Search instead for 
Did you mean: 

SGONAK does not trigger global OUT NAK status in RxFIFO or GONAKEFF interrupt

drmadill
Associate

I have a situation where a USB endpoint stops working due to a control packet being NAKed in the handshake phase. I've traced the problem down to the STM USB stack setting DCTL.SGONAK = 1 in response to an INCOMPISOOUT event, yet in the case when it fails, no global OUT NAK status notification appears in the RxFIFO and the GINTSTS.GONAKEFF interrupt status never occurs. However, the DCTL.GONSTS bit does change from 0 to 1 after SGONAK is set.

Yet, according to the reference manual for the STM32H757 (RM0399 Rev 4, page 2908):

  • Setting the global OUT NAK Internal data flow:
  1. When the application sets the Global OUT NAK (SGONAK bit in OTG_DCTL), the core
    stops writing data, except SETUP packets, to the receive FIFO. Irrespective of the
    space availability in the receive FIFO, non-isochronous OUT tokens receive a NAK
    handshake response, and the core ignores isochronous OUT data packets.
  2. The core writes the Global OUT NAK pattern to the receive FIFO. The application must
    reserve enough receive FIFO space to write this data pattern.
  3. When the application pops the Global OUT NAK pattern word from the receive FIFO,
    the core sets the GONAKEFF interrupt (OTG_GINTSTS).
  4. Once the application detects this interrupt, it can assume that the core is in Global OUT
    NAK mode. The application can clear this interrupt by clearing the SGONAK bit in
    OTG_DCTL.

It appears that a SETUP packet arrives immediately after the INCOMPISOOUT so the top of the RxFIFO contains a "setup data packet received" notification instead of a "global OUT NAK" status notification. Yet, no "global OUT NAK" is ever popped from the RxFIFO in subsequent interrupts and because no GONAKEFF interrupt occurs, the global OUT NAK status (reflected in DCTL.GONSTS) is never cleared and all OUT packets (including those involved in the handshake phase of control packets) are NAKed and USB communication breaks down.

Despite what the reference manual says, an AI search claims that setting DCTL.SGONAK = 1 does NOT insert a "global OUT NAK" status notification in the RxFIFO but should cause a GONAKEFF interrupt (provided the core was not already in the global OUT NAK state, but I already confirmed that DCTL.GONSTS was 0 upon entry to the interrupt which set DCTL.SGONAK to 1).

Yet, whichever is true, the reality is that GINTSTS.GONAKEFF is never set when failure occurs. Note that in previous handling of INCOMPISOOUT, everything seemed to work fine, as expected. It is only in the failure case that the GONAKEFF interrupt never occurs, and this failure seems to be related to a SETUP packet arriving at an inopportune time.

Any clarification on the actual flow of the USB core and help resolving the issue would be appreciated.

Sincerely,

Dan

0 REPLIES 0