2009-01-13 11:07 PM
USB Bulk IN pipe data errors?
2011-05-17 03:57 AM
As part of our design we are trying to implement a double buffered IN endpoint. All of the examples found for the STM32 are for OUT endpoints. We seem to have achieved double buffering as we are filling 16 out of the 19 available slots per frame. Occasionally the first few bytes of the block (64) sent from the endpoint ISR is corrupted but not every time. The suspicion is that we are testing the wrong flags in the ISR and may be modifying the data as it is sent? Below is the USB code snippets
The endpoint is setup in the usb_prop file in the standard device reset routine:Code:
void Device_Reset() { // Set device as not configured state pInformation->Current_Configuration = 0; // Current Feature initialization pInformation->Current_Feature = Device_ConfigDescriptor[7]; SetBTABLE(BTABLE_ADDRESS); // Initialize Endpoint 0 SetEPType(ENDP0, EP_CONTROL); SetEPTxStatus(ENDP0, EP_TX_NAK); SetEPRxAddr(ENDP0, ENDP0_RXADDR); SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); SetEPTxAddr(ENDP0, ENDP0_TXADDR); Clear_Status_Out(ENDP0); SetEPRxValid(ENDP0); // Initialize Endpoint 1 SetEPType(ENDP1, EP_BULK); SetEP_KIND(ENDP1); SetEPDblBuffAddr(ENDP1, ENDP1_BUF0Addr, ENDP1_BUF1Addr); SetEPDblBuffCount(ENDP1, EP_DBUF_IN, 0x40); ClearDTOG_RX(ENDP1); ClearDTOG_TX(ENDP1); SetEPRxStatus(ENDP1, EP_RX_DIS); SetEPTxStatus(ENDP1, EP_TX_NAK); // we'll NAK until frame data available SetEPRxValid(ENDP0); // Set this device to response on default address SetDeviceAddress(0); bDeviceState = ATTACHED; } When we want to commence the transfer we fill the buffers with data then signal the data available. Once the first buffer is emptied the EP1 in callback fires to fill the emptied buffer with the next 64 bytes of data?Code:
void BeginUpload() { u8 i; u8 blockBuffer[64]; // block buffer size uploadAddress = EXT_SRAM_START; // reset USB read upload address frameMode = FRAME_MODE_UPLOAD_PENDING; // start upload // add an additional 2 blocks to the data size as padding (this may be removed later) for (i = 0; i < 128; i++) *((u8 *)(dmaAddress++)) = 0x5A; // fill the info frame with, image size, frame id and ''out of image'' marker (0xFFFF) *((u32 *)&blockBuffer[56]) = dmaAddress & (EXT_SRAM_SIZE-1); // size of image (4 bytes, LSB first) *((u16 *)&blockBuffer[60]) = frameId.w; // frame count (2 bytes, LSB first) blockBuffer[62] = 0xFF; // illegal within JPEG image ... blockBuffer[63] = 0xFF; // ... therefore must be out of frame for (i = 0; i < 56/*sizeof(blockBuffer)*/; i++) blockBuffer[i] = 0x0A; // first block to send test UserToPMABufferCopy(blockBuffer, ENDP1_BUF0Addr, sizeof(blockBuffer)); for (i = 0; i < 56/*sizeof(blockBuffer)*/; i++) blockBuffer[i] = 0x0B; // first block to send test UserToPMABufferCopy(blockBuffer, ENDP1_BUF1Addr, sizeof(blockBuffer)); ClearDTOG_RX(ENDP1); ClearDTOG_TX(ENDP1); ToggleDTOG_RX(ENDP1); ToggleDTOG_RX(ENDP1); // added now both A and B are sent SetEPTxStatus(ENDP1, EP_TX_VALID); // now we have data to send } In the interrupt routine 64 byte chunks are copied from the buffer until it is exhasted. On the last interrupt the alternate buffer still has 64 bytes to send from the previous ISR so the flag is just toggled. After that the end point reverts to NAKing the host until the routine is initiated again from the routine above.Code:
/******************************************************************************* * Function Name : EP1_IN_Callback * Description : Endpoint 1 in callback routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void EP1_IN_Callback(void) { if ((uploadAddress >= EXT_SRAM_START) & (uploadAddress < EXT_SRAM_LIMIT)) { // in upload mode if (uploadAddress < dmaAddress) { _ToggleDTOG_RX(ENDP1); //signal to the USB engine that there is data to transmit // refill the buffer that has just been emptied // determine which buffer to copy into if ((GetENDPOINT(ENDP1) & EP_DTOG_RX)) { Debug1On(); // write to ENDP1_BUF0Addr buffer UserToPMABufferCopy((u8 *)uploadAddress, ENDP1_BUF0Addr, EP1_BUFFER_SIZE); Debug1Off(); } else { Debug2On(); // write to ENDP1_BUF1Addr buffer UserToPMABufferCopy((u8 *)uploadAddress, ENDP1_BUF1Addr, EP1_BUFFER_SIZE); Debug2Off(); } uploadAddress += EP1_BUFFER_SIZE; } else if (uploadAddress > 0) { // should be one more block to transmit _ToggleDTOG_RX(ENDP1); //signal to the USB engine that there is data to transmit // finished uploading // reset upload address to signal upload complete uploadAddress = 0; } } }2011-05-17 03:57 AM
Hey robin.stone, could you figure out what was happening?
Kind of having similar doubts here. Exact the same trouble with the lack of examples. Thanks.