Skip to main content
robin23
Associate
January 14, 2009
Question

USB Bulk IN pipe data errors?

  • January 14, 2009
  • 2 replies
  • 881 views
Posted on January 14, 2009 at 08:07

USB Bulk IN pipe data errors?

    This topic has been closed for replies.

    2 replies

    eng22
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 12:57

    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.

    robin23
    robin23Author
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 12:57

    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;

    }

    }

    }