In developing a USB Mass Storage Device Host, we uncovered what we believe is a bug in the Tivaware USB library. Inside the USBHCDPipeRead function (usbhostenum.c), there are two while loops (see attached). The exterior while loop is waiting for ui32RemainingBytes to be zero and the interior while loop is a while(1) that can be broken out of by various conditions. The problem is presented when a USB device is disconnected while the code within the while loops are being executed. Because of the disconnection, the USB interrupt is triggered and the interrupt handler sets the DISCONNECT bit of g_sUSBHCD.ui32IntEvents. This bit is checked inside of the interior while loop and, since it is set, the Pipe State is set to ePipeError and the interior while loop is broken out of. However, ui32RemainingBytes is still non-zero, so the outer while loop continues executing. The next time through the interior while loop, the DISCONNECT bit is still set and the Pipe State is again set to ePipeError and the interior loop is again broken out of. This becomes an infinite loop. One way to fix the issue would be to clear the DISCONNECT bit which would allow the ePipeError status of the Pipe State to clear ui32RemainingBytes before breaking out of the interior while loop. Another way would be to set ui32RemainingBytes to zero directly.
A condensed version of the code is below.
I have also attached usbhostenum.c to show the entire block..
while(ui32RemainingBytes != 0)
{
//
// Wait for a status change.
//
while(1)
{
//
// If any error event occurs then exit out of the loop.
//
if(g_sUSBHCD.ui32IntEvents & (INT_EVENT_DISCONNECT |
INT_EVENT_VBUS_ERR |
INT_EVENT_POWER_FAULT))
{
//
// Set the pipe state to error.
//
g_sUSBHCD.psUSBINPipes[ui32PipeIdx].iState = ePipeError;
break;
}
//
// If data is ready then return it.
//
if(g_sUSBHCD.psUSBINPipes[ui32PipeIdx].iState == ePipeDataReady)
{
break;
}
else if(g_sUSBHCD.psUSBINPipes[ui32PipeIdx].iState == ePipeError)
{
//
// An error occurred so stop this transaction and set the
// number of bytes to zero.
//
ui32Size = 0;
ui32RemainingBytes = 0;
break;
}
}
}
Thank you.
Sincerely,
Jim Manz