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 II

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

15 REPLIES 15
drmadill
Associate II

Thank you for your reply. My current FIFO configuration is:

  • SetRxFifo=512
  • ep: 0x00 SetTxFifo=128
  • ep: 0x81 SetTxFifo=16
  • ep: 0x82 SetTxFifo=124
  • ep: 0x83 SetTxFifo=17
  • ep: 0x84 SetTxFifo=16
  • ep: 0x85 SetTxFifo=16
  • ep: 0x86 SetTxFifo=16
  • ep: 0x87 SetTxFifo=128
  • ep: 0x88 SetTxFifo=24

The TxFIFO sizes are based on the maximum packet size in the USB descriptor for that endpoint (except for the control endpoint, whose maximum packet size is 64 bytes). The total fifo size is 3988 bytes, which is less than the 4096 bytes of USB FIFO RAM available. The endpoint 0 size is larger than 0x10 because for some interfaces I am sending more than 64 bytes for the control packet (understanding that when the host requests more than 64 bytes from a control endpoint that those bytes will be split into multiple 64 byte packets. I thought that making the EP0 TxFifo larger would allow me to prestuff all the data to be sent to the host for the control endpoint into the TxFIFO).

FBL
ST Employee

Hi @drmadill 
Could you specify which EP type (Isochronous, bulk or interrupt) for each?

In my understanding, as you mentioned control endpoint (also called EP0), whose maximum packet size is 64 bytes in USB2 (in HS and in FS) So you cannot allocate more than 16 words which is 0x10 for EP0.

  • ep: 0x00 SetTxFifo=16 word max

I will check with USB expert and get back to you.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Here are the IN endpoint types:

  • ep: 0x00 control
  • ep: 0x81 bulk
  • ep: 0x82 bulk
  • ep: 0x83 bulk
  • ep: 0x84 interrupt
  • ep: 0x85 bulk
  • ep: 0x86 interrupt
  • ep: 0x87 bulk
  • ep: 0x88 isochronous, adaptive

Here are the OUT endpoint types:

  • ep: 0x01 interrupt
  • ep: 0x02 bulk
  • ep: 0x03 bulk
  • ep: 0x04 bulk
  • ep: 0x05 isochronous, adaptive
  • ep: 0x06 bulk
  • ep: 0x07 bulk
FBL
ST Employee

Hi @drmadill 

 

FBL_1-1765466232550.png

Even with packet multiplier 1 each this is not feasible. The minimum TxFIFO size for each IN endpoint is the maximum packet size in words for each EP. This depend on the type of each EP not number of bytes transferred. 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


The numbers I gave you for SetTxFIFO for each endpoint were in words, not bytes. I notice from your spreadsheet that you seem to have interpreted them as bytes. Also, I am currently using a packet multiplier of 1 for each IN endpoint.

Now, you claim that the maximum packet size in words for each endpoint depends on the type of the endpoint rather than the packet size specified in the USB descriptor for that endpoint (which is less than the maximum packet size allowed by a high-speed device in my case). However, what if I only write a packet to the TxFIFO if it is empty? i.e., the previous packet has already been sent (which is what I doing)? In that case, the TxFIFO will never have more than one packet in it. Would this not be handled properly by the USB core?

FBL
ST Employee

In my understanding, Yess @drmadill 

You get my point. Remember, you send ZPL (zero packet length in USB communication standard) when the data length is an exact multiple of the MPS to explicitly signal the end of a USB transfer.
Still waiting for expert confirmation.

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.