From b9c40767414e0ebb98cc0a8476d14362f76ddf15 Mon Sep 17 00:00:00 2001 From: Ireneusz Gaicki Date: Wed, 17 Jul 2019 12:23:39 +0200 Subject: [PATCH] STM32F7: Do not generate redundant IN tokens When STM32F746-DISCO board was being used in (unsupported) USBHost mode, the communication was unreliable. Our investigation revealed that the problem lied in redundant IN tokens that the host generated even though it shouldn't. This could lead to endless high-frequency NAKs being received from device, which caused watchdog reset as USBHost spent all time in interrupt handlers. In our application the clocks frequencies are: * HCLK = 48 MHz * APB1 = 6 MHz * APB2 = 12 MHz We have captured the raw USB High-Speed traffic using OpenVizsla. Without this change, when USB MSD device connected to the system responded to IN with NAK, there were excessive IN tokens generated about 667 ns after the NAK. With this commit the IN tokens are generated no sooner than 10 us after the NAK. The high frequency of the IN/NAK pairs is not the biggest problem. The biggest problem is that the USB Host did continue to send the IN token after DATA and ACK packets were received from device - *without* any request from upper layer (USB MSD). The USB MSD devices won't have extra data available on Bulk IN endpoint after the expected data was received by Host. In such case IN/NAK cycle time is only houndreds of nanoseconds, the MCU has no time for anything else. The problem manifested not only on Bulk endpoints, but also during Control transfers. Example correct scenario (when this fix is applied): * SETUP stage * SETUP [host -> address 0 endpoint 0] * DATA0 [80 06 00 01 00 00 08 00] [CRC16: EB 94] * ACK * DATA stage * IN * NAK ... the IN/NAK repeated multiple time until device was ready * IN * DATA1 [12 01 10 02 00 00 00 40] [CRC16: 55 41] * ACK * STATUS stage * OUT * DATA1 ZLP * ACK Without this commit, in DATA stage, after the ACK was received, the host did send extra IN to which device responded with STALL. On bus it was: * DATA stage ... * IN * DATA1 [12 01 10 02 00 00 00 40] [CRC16: 55 41] * IN * STALL * IN * STALL * STATUS stage * OUT * DATA1 ZLP * STALL In the fault case the next SETUP was sent only after 510 ms, which indicates timeout in upper layer. With this commit the next SETUP is sent 120 us after the STATUS stage ACK. --- targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_hcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_hcd.c b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_hcd.c index 284257ec11..6a83252cdb 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_hcd.c +++ b/targets/TARGET_STM/TARGET_STM32F7/device/stm32f7xx_hal_hcd.c @@ -969,6 +969,7 @@ static void HCD_HC_IN_IRQHandler (HCD_HandleTypeDef *hhcd, uint8_t chnum) tmpreg &= ~USB_OTG_HCCHAR_CHDIS; tmpreg |= USB_OTG_HCCHAR_CHENA; USBx_HC(chnum)->HCCHAR = tmpreg; + reactivate = 1; } __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); // MBED: changed