USB CDC ACM deadlock


I had been some problems developing a simple app for a S7G2-SK board. It has to work as a simple CDC-ACM USB Device and when it is plugged into a PC (Windows 10) it has to send a text periodically.

The scenario is:

a) When de micro is rebooted and it is plugged into a PC, using a simple MINGW64 console to open the comm port (command: cat ttySxx) the app is correctly working. The user can read the text. (I also try with Terminal program)

b) From case a, if the board is plugged out, go back to case a is possible; all works fine.

c) The problem is when, to exit cat command, the user use Ctrl-C or SIGINT (I suppose when. If he decide to open ir again without unplugged it there is no problem.

d) In case of the USB is unplugged, its impossible to plugged it again. Windows recognize the COM port but any application (including cat command) will able to use it without a hard reset.

Deadlock point is at file ux_dcd_synergy_transfer_request.c (line 180):

while (pipectr_reg & UX_SYNERGY_DCD_DCPCTR_INBUFM )
pipectr_reg = ux_dcd_synergy_register_read(dcd_synergy,
UX_SYNERGY_DCD_PIPE1CTR + ((ed -> ux_dcd_synergy_ed_index - 1UL) * 2UL));

UX_SYNERGY_DCD_DCPCTR_INBUFM bit is never cleared.


I read this and this posts because its has a similar scenario but I couldn't find any clue or idea about how to solve it.


To be clear, a simple project is attached.


- USB driver used is the Windows generic.
- e2 Studio 7.6.0 Build Id: R20190919-1708
- SSP version is 1.7.5


¿Have someone any idea how to solve this issue?


Thanks so much.

  • This sounded very familiar to me, so I looked up the two post links. The second "post" link throws some suspicion at the USBx driver. But to rule this in/out our in-house USBx expert that asks this question when the USBx appears to deadlock:

    "When the hang-up occurs, [what is ] the value of _ux_system_slave->ux_system_slave_device.ux_slave_device_state? From this we can see what USBX thinks the device state is. It should be 0 if the device is disconnected."

    Unfortunately nobody came back with an answer and we did not pursue it further.

    This is his rationale (paraphrased slightly):

    "If it’s true that you are able to call _ux_device_class_cdc_acm_write after the device has been disconnected (it’s supposed to return an error since the device is disconnected), then it sounds like the driver isn’t calling _ux_device_stack_disconnect, which disconnects the device at a generic, non-driver level and more importantly changes the device’s state to disconnected. Or maybe the driver is not calling it before you call _ux_device_class_cdc_acm_write, which would be an error."

    If you can provide this information, that is if you have access to debugging source code, we can verify if this is a driver issue or not or at least know better how the logic has failed.

    Janet Christiansen
    Express Logic
  • In reply to JanetC:

    When the USB is disconnected:
    - ux_slave_device_state = 0
    - ux_slave_device_configuration_selected = 0
    - ux_slave_device_first_interface = 0

    When the USB is connected:
    - ux_slave_device_state = 3
    - ux_slave_device_configuration_selected = 1
    - ux_slave_device_first_interface = <dir>

    When the USB is disconnected after a SIGINT (SIGINT doesn't change any value):
    - ux_slave_device_state = 0
    - ux_slave_device_configuration_selected = 0
    - ux_slave_device_first_interface = 0


    * Disconnection is detected after 1-4 seconds when I use the SIGINT, without it, the time to detect it is  ≈ 0 second. Could this be because of the debug mode and the variable value polling?

    * Activation and deactivation functions are called always.

    Trying to write into the bus into the deactivation function after the SIGINT cause the same deadlock. Without the SIGINT the code returned of the write function is 0x26 or 0x04.

    In case of the COM port is never opened, doing this action will cause the same deadlock. In this scenario, USB driver is not recognized.

    (I forgot to upload the example project I am using, here it is)

  • In reply to JanetC:

    Hello JanetC,

    Have you got any other question i could help?

    I'm not finding any solution to this problem. Could you be able to reproduce it?
  • In reply to Ismael:

    This could be caused by the fact the function ux_dcd_synergy_transfer_abort() tries to clear the FIFO buffer memory by using the BLCR bit :-

            /* Clear the FIFO buffer memory. */
            ux_dcd_synergy_register_write(dcd_synergy, UX_SYNERGY_DCD_CFIFOCTR, UX_SYNERGY_DCD_FIFOCTR_BCLR);

    #if !defined(BSP_MCU_GROUP_S124) && !defined(BSP_MCU_GROUP_S128) && !defined(BSP_MCU_GROUP_S1JA)
            ux_dcd_synergy_register_write(dcd_synergy, UX_SYNERGY_DCD_D0FIFOCTR, UX_SYNERGY_DCD_FIFOCTR_BCLR);

    However the BCLR bit only clears the buffer facing the CPU side.

    the INBUFM bit in the PIPEnCTR register indicates there is data in the FIFO.

    To clear all buffers of the FIFO the ACLRM bit in the PIPEnCTR should be used.

    Please try the attached project, it uses the ACLRM bit to clear the FIFO buffers in the ux_dcd_synergy_transfer_abort() function.

    There is a modified version of the function in src\ux_dcd_synergy_transfer_abort.c (the original version in synergy\ssp\src\framework\sf_el_ux\ux_dcd_synergy_transfer_abort.c is excluded from the build).

  • In reply to Jeremy:

    Hello Jeremy,
    Your project version solves the problem I wrote before.

    Will It be available in next SSP release?

    Thanks so much.
  • In reply to Ismael:

    This is a known issue, and should be fixed in a future release of the SSP