USB UART output buffer remains full after serial disconnect

Windows 11, NCS v2.3.0, VSCode

Hi, I am using the uart_poll_out API for communicating via USB serial.

For each character I want to output, I do this:

uint32_t dtr;
uart_line_ctrl_get(DEV_UART_USB, UART_LINE_CTRL_DTR, &dtr);
if (dtr)
{
    uart_poll_out(DEV_UART_USB, c);
}

The other side of the serial connection can disconnect at any time.

I don't want my code to hang trying to write, that's why I checked the DTS beforehand, and basically throw away any data that won't get sent immediately.

The problem I have is:

- I am writing continuously

- The other side disconnects

- I attempt to detect that, and do, eventually, but not before the uart_poll_out puts a few characters into what I assume is an output buffer which fills up a short time later

Then, when the other side re-connects, the bytes that are sitting in the output buffer get sent.  This corrupts the datastream to the receiver as those bytes were for a different connection.

Is there a way to deal with this?

I would basically like to detect that I can't send data, and clear any existing output buffer at that time.

Or any other way to deal with this situation?

I'm not a serial expert and I only had the line_ctrl code because I saw it in an example.  Please let me know.

Thanks.

  • Hello,

    I don't see any better way than to always check the uart_line_ctrl_get(devUART_LINE_CTRL_DTR, &dtr) before trying to send data. 

    I assume you are calling usb_enable() here, can you try to add a callback function such as:

    static void status_cb(enum usb_dc_status_code status, const uint8_t *param)
    {
    	LOG_INF("Status %d", status);
    	// Clear buffers here if status is USB_DC_DISCONNECTED.
    }
    
    ...
    ret = usb_enable(status_cb);
    ...

    I do believe you should be able to clear all buffers on disconnect event.

    The complete list of status codes are:

    /**
     * @brief USB Driver Status Codes
     *
     * Status codes reported by the registered device status callback.
     */
    enum usb_dc_status_code {
    	/** USB error reported by the controller */
    	USB_DC_ERROR,
    	/** USB reset */
    	USB_DC_RESET,
    	/** USB connection established, hardware enumeration is completed */
    	USB_DC_CONNECTED,
    	/** USB configuration done */
    	USB_DC_CONFIGURED,
    	/** USB connection lost */
    	USB_DC_DISCONNECTED,
    	/** USB connection suspended by the HOST */
    	USB_DC_SUSPEND,
    	/** USB connection resumed by the HOST */
    	USB_DC_RESUME,
    	/** USB interface selected */
    	USB_DC_INTERFACE,
    	/** Set Feature ENDPOINT_HALT received */
    	USB_DC_SET_HALT,
    	/** Clear Feature ENDPOINT_HALT received */
    	USB_DC_CLEAR_HALT,
    	/** Start of Frame received */
    	USB_DC_SOF,
    	/** Initial USB connection status */
    	USB_DC_UNKNOWN
    };

    Maybe you can use those to also investigate your other issue you have:
    usb_cdc_acm: cdc_acm_poll_out: Ring buffer full, drain buffer 

    Best regards,
    Kenneth

  • Thank you.

    I assume you are calling usb_enable() here, can you try to add a callback function such as:

    Yes I receive a callback in that way.

    I do believe you should be able to clear all buffers on disconnect event.

    How do I do that?  Is there documentation or an example?  I don't understand how to do this from your reply.

    I don't see any better way than to always check the uart_line_ctrl_get(devUART_LINE_CTRL_DTR, &dtr) before trying to send data. 

    Are you saying there is no way to stop this from happening?

    Is the problem description clear enough?

    I am saying I believe several bytes get loaded into some area in memory before I am notified of disconnect (usb callback) and also during that time I am still getting the dtr (probably because the bytes are in ram to be sent out later but aren't blocking yet.

    Thanks.

    Doug

  • Maybe you can share some soure code I can look at?

    Kenneth

  • Hi, what code do you want to see to help you answer this?

    Let's be specific so we can get to the answer quickly.

  • Ideally I want a project I can run on an nRF52840-DK to recreate this.

    Kenneth

Related