2025-11-24 10:40 AM
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):
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
2025-12-08 7:27 AM
Thank you for your reply. My current FIFO configuration is:
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).
2025-12-10 8:29 AM
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.
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.
2025-12-10 8:57 AM
Here are the IN endpoint types:
Here are the OUT endpoint types:
2025-12-11 9:47 AM
Hi @drmadill
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.
2025-12-13 2:00 AM
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?
2025-12-15 2:30 AM
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.