I am using the USB component in Processor Expert with MQX Lite on the K20, and I seeing what looks like missing transactions, or transacations that have been overwritten. I am setting up the BDT entry with a buffer and a callback routine. The callback routine simply sets a semaphore to wake up a task that reads the contents of the buffer, and initializes the next reception. I thought the next reception would be held off until the next BDT entry was set up, but it looks like it's overwriting the previous buffer before the data is transferred. Am I using this API correctly?
/************************************************************************************************************
* this routine is called by the application task to transfer the buffer data to the parsing buffer
*************************************************************************************************************/
void ReadInputDataSetup(unsigned char *bufin, int *size)
{
int tdata;
int x;
tdata = DataTD.TransmittedDataSize;
if (tdata)
{
memcpy(&bufin[*size], Buffer, tdata);
*size += tdata;
DataTD.Head.EpNum = 0; /* Initialize receive request for EP0(Out), when data is received,
call ReadInputDataTask routine */
DataTD.Head.BufferPtr = (uint8_t *)Buffer; /* Input buffer pointer */
DataTD.Head.BufferSize = (uint16_t)32; /* Size of input buffer */
DataTD.Head.Flags = LDD_USB_DEVICE_TRANSFER_FLAG_EXT_PARAM; /* TD contains extension parameter. Callback doesn't occur without this */
DataTD.CallbackFnPtr = &ReadInputDataTask; /* Set pointer to the ReadInputDataTask function */
(void)USB1_DeviceRecvData(SavedMyUsbPtr->UsbPtr,(LDD_USB_Device_TTD *)&DataTD);
}
}
/*******************************************************
** Method : ReadInputDataTask (User method)
**
** Description :
** Set the semaphore to cause the reading of the buffer,
** and set up for the next receive.
* */
void ReadInputDataTask(LDD_TDeviceData *USBDevDataPtr, LDD_USB_Device_TTD* pTD)
{
SavedMyUsbPtr = (MY_USB *)USBDevDataPtr;
if (pTD->TransferState == LDD_USB_TRANSFER_DONE)
PostUSBSem();
}
...
// application task loop pulls in 32 byte at a time until there is not enough room for another 32, then parses.
for(;;)
{
WaitUSBSem();
ReadInputDataSetup(flash_buf, &x);
if (((sizeof(flash_buf) - x) < 32)|| (dfu_state == DFU_MANIFEST_SYNC_STATE))
{
result = FlashArrayS19(flash_buf, x, line);
x = 0; //reset buffer pointer
switch(result)
{
case Flash_OK:
break;
case Flash_FACCERR:
dfu_status.state = DFU_ERRERASE_STATUS;
break;
case Flash_FPVIOL:
dfu_status.state = DFU_ERRWRITE_STATUS;
break;
case Flash_MGSTAT0:
dfu_status.state = DFU_ERRUNKNOWN_STATUS;
break;
case Flash_RDCOLERR:
dfu_status.state = DFU_ERRWRITE_STATUS;
break;
case Flash_NOT_ERASED:
dfu_status.state = DFU_ERRPROG_STATUS;
break;
case Flash_CONTENTERR:
dfu_status.state = DFU_ERRADDRESS_STATUS;
break;
}
}
block_status = BLOCK_DONE;
}
=======================================================================
After a little further study, I found out the DMAERR bit in the USB0_ERRSTAT register is set when the problem occurs. This causes an interrupt without data, but the offending
packet is already "eaten". Possible timing problem?
"This bit is set if the USB Module has requested a DMA access to read a new BDT but has not been given
the bus before it needs to receive or transmit data. If processing a TX transfer this would cause a transmit
data underflow condition. [not doing a TX]
If processing a RX transfer this would cause a receive data overflow condition.
This interrupt is useful when developing device arbitration hardware for the microprocessor and the USB
module to minimize bus request and bus grant latency. This bit is also set if a data packet to or from the
host is larger than the buffer size allocated in the BDT. In this case the data packet is truncated as it is put
in buffer memory."
I'm using a USB sniffer, and the packet doesn't look too big. Hmmm.
DMAERR bit appears to be a red herring. It's set all the time regardless of failure. It also is not OR'd into the
ISTAT ERROR bit BTW
found the problem. Programmer error (whew). I was making a call to (void)USB1_DeviceRecvData(SavedMyUsbPtr->UsbPtr,(LDD_USB_Device_TTD *)&DataTD); when I didn't have to. I had already made the call when the USB command was issued.