USB Freezes / kStatus_USB_Busy

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB Freezes / kStatus_USB_Busy

2,431 Views
variable_andrew
Senior Contributor I

I'm trying to debug why after some random large amount of data / time - I start to see USB freezing, using code based on the evkbimxrt1050_dev_cdc_vcom_freertos demo in MCUXpresso. 

My problem seems MAYBE similar to what caused other's to start threads: USB isochronous EP stuck 

and https://community.nxp.com/thread/498477 

and K22 USB device CDC and HID problem 

But I don't see a clear workaround for the RT1052's USB stack.

In that the USB is getting stuck in a busy state in USB_DeviceCdcAcmSend() 

If I follow this, I THINK that isBusy is set in usb_device_dci.c in 

static usb_status_t USB_DeviceTransfer(usb_device_handle handle,
                                       uint8_t endpointAddress,
                                       uint8_t *buffer,
                                       uint32_t length)
{
    usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle;
    usb_status_t error                = kStatus_USB_Error;
    uint8_t endpoint                  = endpointAddress & USB_ENDPOINT_NUMBER_MASK;
    uint8_t direction                 = (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
                        USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT;
    OSA_SR_ALLOC();

    if (NULL == deviceHandle)
    {
        return kStatus_USB_InvalidHandle;
    }

    if (NULL != deviceHandle->controllerInterface)
    {
        if (deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy)
        {
            return kStatus_USB_Busy;
        }
        OSA_ENTER_CRITICAL();
        deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 1U;
        OSA_EXIT_CRITICAL();
        if (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)
        {
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
            if (length)
            {
                DCACHE_CleanByRange((uint32_t)buffer, length);
            }
#endif
            /* Call the controller send interface, the callbackFn is initialized in
            USB_DeviceGetControllerInterface */
            error = deviceHandle->controllerInterface->deviceSend(deviceHandle->controllerHandle, endpointAddress,
                                                                  buffer, length);
        }
        else
        {
#if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U))
            if (length)
            {
                DCACHE_CleanInvalidateByRange((uint32_t)buffer, length);
            }
#endif
            /* Call the controller receive interface, the callbackFn is initialized in
            USB_DeviceGetControllerInterface */
            error = deviceHandle->controllerInterface->deviceRecv(deviceHandle->controllerHandle, endpointAddress,
                                                                  buffer, length);
        }
        if (kStatus_USB_Success != error)
        {
            OSA_ENTER_CRITICAL();
            deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U;
            OSA_EXIT_CRITICAL();
        }
    }
    else
    {
        error = kStatus_USB_ControllerNotFound;
    }
    return error;
}

How could it be that isBusy is not getting reset back to 0 in rare cases?

Is it the timing issues mentioned in the threads I linked to above? or are there a set of common cases that cause USB's interface to get stuck on isBusy == 1?

When looking on the USB packet analyzer, all traffic appears to be fine, just when I'm sending many packets from the RT1052's USB, as noted above, occasionally (like after a few thousand packets) the RT1052 just stops sending data and is stuck in the isBusy state. 

Labels (1)
Tags (3)
4 Replies

1,880 Views
niepiekm
Contributor I

I found the same problem, also with CDC class. And in my case, I can observe the problem when I have a sending task enabled, (`USB_DEVICE_CONFIG_USE_TASK = 1U` in `usb_device_config.h`). When I had this task disabled, the problem does not occur. 

0 Kudos
Reply

2,252 Views
variable_andrew
Senior Contributor I

Just to show where I am in code: 

Screen Shot 2020-02-28 at 10.47.54 AM.png

and if i force isBusy to 0 (as noted using the debug view):

Screen Shot 2020-02-28 at 10.56.39 AM.png

isBusy is still set elsewhere... 

The USB stack is pretty complex - so if I could get some pointers on where isBusy should be cleared when I'm only sending data over the bulk endpoint from the RT1052 to a computer (not receiving anything when this state is hit),  and what would cause this to not be cleared... maybe that would help me debug. 

0 Kudos
Reply

2,252 Views
danielchen
NXP TechSupport
NXP TechSupport

Hi Andrew:

I noticed one thread about the possible race condition on usb_device_dci.c. Please refer to below link

Posible race condition on usb_device_dci.c 

Did you try the solution by janbertran?

USB_OSA_ENTER_CRITICAL();
if (deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy)
{
    USB_OSA_EXIT_CRITICAL();
    return kStatus_USB_Busy;
}

Regards

Daniel

2,252 Views
variable_andrew
Senior Contributor I

Hi danielchen@fsl‌,

Thanks for the feedback -

What I ended up doing to get this to work for me was: create a separate FreeRTOS task for sending, and then send via FreeRTOS queues - which seems to avoid race conditions for me