AnsweredAssumed Answered

Issue with STM32 USB Transmit Interrupted by Receive

Question asked by J.M.001 on Aug 11, 2015
Latest reply on Mar 15, 2016 by dischinger.michael

The Scenario:
I have a custom board running an STM32F303VCTx connected via USB (Full Speed Device) to a Linux machine as a Custom HID peripheral.  A majority of the time the system works correctly sending data in both directions, but under some circumstances (details to follow), the system gets into a state where Linux’s libusb library begins to report timeouts (error code -7) for every write attempt.  Forcing a re-enumeration via Linux recovers the system.  I have tried this on an embedded Linux machine and a desktop Linux machine which is one of the reasons I suspect the STM32 side.

Source Code:
The STM32 driver libraries being used (including USB stack) are those provided by the STM32CubeMX4.9.0 application using the STM32Cube FW_F3 V1.2.0 firmware package.  All I have done is implement the custom HID callback functions and customise the descriptors.  I have 4 endpoints:

  HAL_PCDEx_PMAConfig(pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);

  HAL_PCDEx_PMAConfig(pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);

  HAL_PCDEx_PMAConfig(pdev->pData , 0x81 , PCD_SNG_BUF, 0x100);

  HAL_PCDEx_PMAConfig(pdev->pData , 0x02 , PCD_SNG_BUF, 0x140);

Further Investigation:
I have been using LED toggling in the code and a scope to investigate where the system is when the issue occurs.  It appears that the scenario is that a call to HAL_PCD_EP_Transmit() (to send some data to the host), is being interrupted by an incoming packet (from the host)  (i.e. PCD_EP_ISR_Handler() enters the “if ((wEPVal & USB_EP_CTR_RX) != 0)” condition).

My Best Guess:
The incoming data is received on endpoint 0x02, and the outgoing data is sent on endpoint 0x81, so I don’t see any reason why the one should impact the other. My best guess is that the incoming frame is corrupting the out-going frame, and so the frame that linux receives, triggers the Linux driver to block the device assuming it has malfunctioned.  A re-enumeration resets the linux driver.  This suggested the USB shared memory functions (PCD_WritePMA() and PCD_ReadPMA()) were trampling each other, but from what I can tell, the offsets and lengths of each are correct so they don’t overlap.  I even tried moving the offsets around and increasing the lengths, but that made no difference.

Can anyone propose a solution and/or further investigations, and/or point me to somewhere that might be able to shed some light on this issue?