This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
we have a serious communication problem using the usb_bulk_driver library: Receiving information from the host works very well but the transmit function ceases to work from time to time. This may happen after a system uptime of five minutes, three hours or even 40 hours.
Our firmware is based on the bulk device demo software package with a little modification. Our transmit function is called "static uint32_t SendStringToHost(uint8_t *pui8Info, uint_fast32_t ui32NumBytes)". This function starts a new transmission only if the old transmission is completely finished. For this purpose, we set a global flag "USB_TXR" in the TX interrupt function "uint32_t TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData)". Even a 50 µs delay inside the TxHandler does not solve the problem.
NB: "g_ui32USBTXTimer" is being incremented every 1 ms inside the SysTick procedure.
Please find the source code below:
//*****************************************************************************
//
// Handles bulk driver notifications related to the transmit channel (data to
// the USB host).
//
// \param pvCBData is the client-supplied callback pointer for this channel.
// \param ulEvent identifies the event we are being notified about.
// \param ulMsgValue is an event-specific value.
// \param pvMsgData is an event-specific pointer.
//
// This function is called by the bulk driver to notify us of any events
// related to operation of the transmit data channel (the IN channel carrying
// data to the USB host).
//
// \return The return value is event-specific.
//
//*****************************************************************************
uint32_t
TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,
void *pvMsgData)
{
//
// We are not required to do anything in response to any transmit event.
// All we do is update our transmit counter.
//
if (ui32Event == USB_EVENT_TX_COMPLETE)
{
g_ui32TxCount += ui32MsgValue;
/*
//
// wait a little bit...
// NB: character time is about 8 µs
// ... does not solve the problem
//
delay_us(50);
*/
//
// set USB TX ready flag
//
USB_TXR = true;
}
return(0);
}
static uint32_t
SendStringToHost(uint8_t *pui8Info, uint_fast32_t ui32NumBytes)
{
uint_fast32_t ui32Loop, ui32Count;
uint_fast32_t ui32ReadIndex;
uint_fast32_t ui32WriteIndex;
tUSBRingBufObject sTxRing;
bool bWriteTimeout, bUSBRingBufEmpty;
//
// initialize TX timeout counter
//
g_ui32USBTXTimer = 0;
//
// ui32NumBytes characters to process;
// wait until transmit buffer is completely empty
//
do
{
//
// Get the current buffer information to allow us to write directly to
// the transmit buffer (we already have enough information from the
// parameters to access the receive buffer directly).
//
// Copy the current ring buffer settings to the clients storage.
//
/*
USBBufferInfoGet(&g_sTxBuffer, &sTxRing);
bUSBRingBufEmpty = USBRingBufEmpty(&sTxRing);
*/
//
// replacement for "USBBufferInfoGet(&g_sTxBuffer, &sTxRing)" without any function calls
//
(&sTxRing)->pui8Buf = (&g_sTxBuffer)->sPrivateData.sRingBuf.pui8Buf;
(&sTxRing)->ui32ReadIndex = (&g_sTxBuffer)->sPrivateData.sRingBuf.ui32ReadIndex;
(&sTxRing)->ui32Size = (&g_sTxBuffer)->sPrivateData.sRingBuf.ui32ReadIndex;
(&sTxRing)->ui32WriteIndex = (&g_sTxBuffer)->sPrivateData.sRingBuf.ui32WriteIndex;
//
// replacement for "USBRingBufEmpty(&sTxRing)" without any function calls
//
ui32WriteIndex = (&sTxRing)->ui32WriteIndex;
ui32ReadIndex = (&sTxRing)->ui32ReadIndex;
bUSBRingBufEmpty = (ui32WriteIndex == ui32ReadIndex) ? true : false;
//
// calculate timeout condition
//
bWriteTimeout = (g_ui32USBTXTimer > 20);
} while (!(bUSBRingBufEmpty && USB_TXR) && !bWriteTimeout);
//
// check for USB TX timeout
//
if (bWriteTimeout)
{
//
// flush TX buffer and discard input string because transmission is not possible at the moment
//
USBBufferInfoGet(&g_sTxBuffer, &sTxRing);
USBRingBufFlush(&sTxRing);
USB_TXR = true;
ui32Count = 0;
}
else
{
//
// prepare transmission: clear USB TX ready flag
//
USB_TXR = false;
//
// How many characters can we process this time round?
// Calculation is no more necessary because we write when buffer is free.
//
//ui32Loop = (ui32Space < ui32NumBytes) ? ui32Space : ui32NumBytes;
//ui32Count = ui32Loop;
ui32Count = ui32Loop = ui32NumBytes;
//
// Set up to process the characters by directly accessing the USB buffers.
//
ui32ReadIndex = 0;
ui32WriteIndex = sTxRing.ui32WriteIndex;
while (ui32Loop)
{
//
// copy string to the transmit buffer
//
g_pui8USBTxBuffer[ui32WriteIndex] = pui8Info[ui32ReadIndex];
//
// Move to the next character taking care to adjust the pointer for
// the buffer wrap if necessary.
//
ui32WriteIndex++;
ui32WriteIndex = (ui32WriteIndex == BULK_BUFFER_SIZE) ? 0 : ui32WriteIndex;
ui32ReadIndex++;
ui32ReadIndex = ((ui32ReadIndex == BULK_BUFFER_SIZE) ? 0 : ui32ReadIndex);
ui32Loop--;
}
//
// We've processed the data in place so now send the processed data
// to the host.
//
USBBufferDataWritten(&g_sTxBuffer, ui32Count);
}
//
// We processed as much data as we can directly from the receive buffer so
// we need to return the number of bytes to allow the lower layer to
// update its read pointer appropriately.
//
return (ui32Count);
}
Thanks,
Juergen
Hi Mr. Wang,
we did not try out the example CCS project for such a long system uptime. We even do not work on the LaunchPad but have our own PCB instead, meanwhile.
Our application is sending a quite huge amount of data to the host. The data are collected inside the 1 ms SysTick routine (ADC readouts) which requires an execution time of about 250 µs. Except for the SysTick (and USB I/O, but that is not in our hands), the whole application is simply running in the main loop. We did not do any modifications except for the new "SendStringToHost()" routine which comes very close to the output routine of the example project you mentioned.
When the TX thread is "gone" and blocking, the rest of the application is still operating. The USB device is still present and USB RX works without any trouble. So our command interpreter does as well.
If you recommend us to test the example project, we would have to write an additional Windows test software, running on the host.
Regards,
Juergen
Hi Mr. Wang,
using the launchpad hardware and the original usb_dev_bulk software, we have the same problem.
But we are no more sure that it is a firmware / USB bulk driver problem but a hardware problem.
The probability for a failure depends on the Windows PC used and whether a USB hub is present
in the system or not. Even the length of the USB cable has an influence. The USB system gives
the impression to work quite undependable.
For example, when connecting the launchpad (with usb_dev_bulk firmware installed) via the target
USB (U7) and an 1.8 m cable to an USB hub, the USB device is enumerated but communication is
not possible (!). Using an 1.0 m cable, the communication works for a few minutes.
Regards,
JL