2020-02-11 01:38 PM
I am trying to implement some very basic USB communication functionalities between my STM32F7 and another device. The device can usually be configured by ASCII messages through serial, and so I am trying to achieve that same functionality but through USB. As a starter I am trying to send a single command, and that is where my trouble starts.
I am using the STMCube USB Host libraries (v1.15.0 found at https://github.com/STMicroelectronics/STM32CubeF7/tree/master/Middlewares/ST/STM32_USB_Host_Library/Class/CDC). I am able to connect and enumerate successfully with the device, so basic levels of back-and-forth communication are there. The issue comes when I try to transmit my ASCII message to the device.
When I call the USBH_CDC_Transmit(found in usbh_cdc.c) function, the STM32F7 gets flooded with interrupts, specifically the NAK and channel-disabled interrupts in HCD_HC_OUT_IRQHandler(found in stm32f7xx_hal_hcd.c). This causes the CDC data transfer state machine to get stuck in a loop. The NAK causes the state machine to try resending the message, the message gets NAK'd immediately, and the process continues. This is all happening so quickly and so often that the performance of the system lags considerably with a USB interrupt triggering every 10 microseconds.
I have looked and have found similar cases to mine:
https://community.st.com/s/question/0D50X00009Xked0SAB/stm32cube-usb-host-driver-interrupt-flood
These other cases have offered insight, but the major difference being that they were dealing with an excess of interrupts during IN data transactions where I am just trying to get OUT data transactions to work.
Does anyone have any insight into this? I can definitely provide more information if needed.
Thank you in advance
2020-02-11 03:02 PM
NAK in Bulk transactions is a mechanism through which device indicates to host that it is temporarily not ready to receive or transmit data, see USB 2.0 8.5.2 Bulk Transactions. In other words, it does not matter whether it was an In or Out transaction, NAK for host means that device is not ready, retry later.
It's upon the Host to schedule a retransmission. The Synopsys OTG IP used in STM32 provides no support for scheduling/timing, so this has to be done in software.
The Cube libraries don't appear to provide scheduling either. The simplest thing to do is defer the next attempt for this transaction to the next frame, i.e. after SOF. I believe some of the fixes out there do exactly this. This of course impact latencies, but that's upon you to judge and implement a different mechanism, if this is not suitable.
JW