Good Evening everybody,
I have been working on an application that gets data from an ADC chip and streams them over USB using bulk transfers. Much of the effort that relates to this work has been described in this post. Key features of that application are:
- Data transfer from the ADC to the MCU over SSI (SPI) is performed using an external interrupt on the MCU; the DOUT line of the ADC goes low when a new result is available and this fires an external interrupt whose ISR gathers the data.
- Data are stored in a multiple buffer in a circular fashion; when that buffer is halfway full, data are sent over USB to the host application of a PC starting from the "top" (the beginning) of the buffer. This has been implemented and tested in another application. USB raw data are observed using a monitoring application.
- One of the ADC channels is connected to a sinusoidal signal that is supplied by a signal generator. If everything worked properly, a plot of the data would be an exact replica of that signal.
- Data from all activated channels of the ADC (3 channels) are stored in the following form: <channel 0 data><channel 1 data><channel 2 data><channel 0 data><channel 1 data><channel 2 data><channel 0 data><channel 1 data><channel 2 data>...
But monitoring the USB raw data reveals that what is stored to the host PC's disk is not of that form but some data are lost.
I checked things thoroughly in the debugger and noticed the following:
Each part of the multiple buffer is 192 bytes long. What I do in the MCU's code is that I send data over USB every 192 bytes. I have set BULK_BUFFER_SIZE to 384 bytes instead of 256 bytes, like in the USB bulk example supplied with TivaWare. However, after the 128th byte - or after the 64th byte - data are lost.
What is more strange is the fact that data loss happens when sending those over USB; the data stored in the MCU memory are intact and are copied byte-to-byte to the USB TX buffer correctly. Please refer to the function that performs that task at the end of this post. Moreover, that function does not return the number of bytes that are written to USB but it adds 128 more bytes.
It seems that I have not understood in depth how data are sent over USB using the buffers in the usb_dev_bulk example.
Any ideas, anyone? This might have a simple solution but I have become blind after exhaustive work on this...
// Modified from function EchoNewDataToHost() in usb_dev_bulk example supplied by TI. static uint32_t SendDataToHost(tUSBDBulkDevice *psDevice, uint8_t *pi8Data, uint_fast32_t ui32NumBytes) { uint_fast32_t ui32Loop, ui32Space, ui32Count; uint_fast32_t ui32WriteIndex; tUSBRingBufObject sTxRing; // 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). USBBufferInfoGet(&g_sTxBuffer, &sTxRing); // How much space is there in the transmit buffer? ui32Space = USBBufferSpaceAvailable(&g_sTxBuffer); // How many characters can we process this time round? //ui32Loop = (ui32Space < ui32NumBytes) ? ui32Space : ui32NumBytes; //ui32Count = ui32Loop; ui32Count = (ui32Space < ui32NumBytes) ? ui32Space : ui32NumBytes; // I changed the above 2 lines to that // Set up to process the characters by directly accessing the USB buffers. ui32WriteIndex = sTxRing.ui32WriteIndex; ui32Loop = 0; while(ui32Loop < ui32NumBytes) { // Write bytes to USB TX buffer g_pui8USBTxBuffer[ui32WriteIndex] = pi8Data[ui32Loop]; // 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; ui32Loop++; } // We've processed the data in place so now send the processed data // back 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); }