AnsweredAssumed Answered

USB Freezes / kStatus_USB_Busy

Question asked by variable_andrew on Feb 28, 2020
Latest reply on Feb 28, 2020 by variable_andrew

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 Posible race condition on usb_device_dci.c 

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. 

Outcomes