AnsweredAssumed Answered

USB HS Failure to ACK Bulk OUT packet

Question asked by Nicklesworth on Mar 9, 2016
Latest reply on Mar 9, 2016 by Nicklesworth
Hi All,

I'm working on a STM32F429-based USB HighSpeed peripheral which exchanges MIDI data with a host computer. If you're not familiar with MIDI, don't worry about it - just know that in the land of USB it's represented as 2 x bulk endpoints.

In a nutshell - the problem I'm seeing is that sometimes the STM32 fails to provide a handshake packet (NAK, ACK, or otherwise) in response to a OUT packet to the incoming bulk endpoint of the device.

I'm reaching out to see if anyone has experienced a similar issue, hopefully with a workaround/solution.

My configuration is as follows:
  • Hardware: STM32F4x9I-EVAL board (Rev B)
  • Libraries: STM32 USB OTG Library v2.20 (includes SPL v1.6.0)
  • USB Config: Using the USB-HS core with the on-board ULPI PHY enabled
  • Host: Win7-64 PC
I'm looking at the trace from a USB protocol analyzer and can see the following series of events:
  1. I send a 'large' packet of data to the device. I have the bulk endpoint defined as 512 bytes, so the result is the host starts sending many back-to-back 512byte OUT packets.
  3. Several transfers are successfully accepted by the device, where success is defined as: A) OUT, DATAx, ACK ... or B) OUT, DATAx, NAK, PING, ACK, OUT, DATAx, ACK. In both these cases the STM32 has accepted the data transfer.
  5. At some point (~50 transfers later), the host sends a OUT, DATAx...but the STM32 never responds with a handshake byte (ACK, NAK, NYET, STALL)
  7. The host recognizes it never receives a handshake and as a result sends a PING to check the endpoint status. The STM32 responds in kind with an ACK, meaning the endpoint is ready.
  9. The host thinking the endpoint is now ready, attempts the OUT, DATAx again...but handshake packet back from the STM32.
  11. Steps 3-5 occur for many transactions (100K+)...and then for some reason the STM32 finally decides to ACK an OUT transaction. It transfers some more data, but then falls back into the bad behavior of steps 3-5.
It's worth noting that this problem does not occur if I use either the USB-FS core of the USB-HS core with on-chip FS PHY. But this is at a significantly data rate.

The only other ISR running in the system is SysTick, and it's as low as a priority as it can get. 

I'm not currently do anything with the incoming data. I'm merely trying to test the raw transfer speed. My "_DataOut" handler within the USB ISR is very simplistic. The MIDI data handler within is simply a stub at this point.

uint8_t usbd_MIDI_DataOut(void *pdev, uint8_t epnum)
    // ------------------------------------------------------------------------
    // Determine how many bytes have been received and handle them
    // Note: USB should NAK until endpoint is re-prepared for new reception
    // ------------------------------------------------------------------------
    uint32_t rx_count = ((USB_OTG_CORE_HANDLE *)pdev)->dev.out_ep[epnum].xfer_count;
    usbd_MIDI_RX(rx_buffer, rx_count);
    // ------------------------------------------------------------------------
    // Re-Prepare the OUT endpoint to receive the next packet from the host
    // uint32_t DCD_EP_PrepareRx(USB_OTG_CORE_HANDLE *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t buf_len)
    // ------------------------------------------------------------------------
    DCD_EP_PrepareRx(pdev, midi_driver_config.base_ep_out, rx_buffer, MIDI_EP_SIZE);
    return USBD_OK;

void usbd_MIDI_RX(uint8_t* buffer, uint32_t len)
    // ReadUsbRcvdData(buffer, len);

The USB trace is seen below.