Skip to main content
shippo
Associate II
June 14, 2014
Question

USB transfer multiple of packet size

  • June 14, 2014
  • 17 replies
  • 5447 views
Posted on June 14, 2014 at 15:30

I don't know whether this is related to the STM32CubeF4 package or the STM32F407 so I'll post here.

I'm using the STM32F4 discovery board and the onboard USB FS port.

I wrote a VCP interface that lets me send a buffer of any length (basically just expanded the CDC example), but when I try to send a buffer with a length which is a multiple of the FS max packet size (64 bytes) the data is not transferred immediately but only on the next call to USBD_LL_Transmit (which in turn calls HAL_PCD_EP_Transmit).

I tested this with 64 and 128 byte buffers.

Am I doing something wrong here, is this a known bug or a new bug?

And is it more likely related to the STM32CubeF4 or the chip itself?

What I already did is look through the HAL firmware code but as far as I can see there's no rounding errors or similar that would cause such an issue...
    This topic has been closed for replies.

    17 replies

    jeanmark
    Visitor II
    June 18, 2014
    Posted on June 18, 2014 at 10:09

    Hi,

    Change ''if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize))'' by ''if(((CDC_Handle->RxDataLength - length) >= 0) && (length >= CDC_Handle->DataItf.InEpSize))''

    shippo
    shippoAuthor
    Associate II
    June 18, 2014
    Posted on June 18, 2014 at 10:37

    Hi, I don't think that's anywhere in my code...

    I did grep for

    RxDataLength

     

    but didn't find anything.

    shippo
    shippoAuthor
    Associate II
    July 11, 2014
    Posted on July 11, 2014 at 17:19

    Bump, I still have this problem with the new 1.3.0 HAL version.

    I scanned the source code quite thoroughly but didn't find anything obvious (to me) that could cause this.

    Any ideas?
    klaus
    Associate
    July 11, 2014
    Posted on July 11, 2014 at 22:26

    I'm struggling with the same problem. The solution is to send an additional 

     ZLP (zero length packet) but I don't figured it out at the moment how to manage this.

    Btw.: how did you realize your VCP receive function ?

    shippo
    shippoAuthor
    Associate II
    July 11, 2014
    Posted on July 12, 2014 at 01:29

    ZLP, that's the info I needed.

    I got it working now by sending a ZLP in the

    DataIn

    callback of the VCP (former CDC, I renamed everything) class if the transfer size is a multiple of the packet size. Like so:

    PCD_HandleTypeDef *hpcd = pdev->pData;
    PCD_EPTypeDef *ep = &hpcd->IN_ep[epnum]; 
    // For transfers exactly a multiple of the packet size, we need to send a zero length packet to complete
    if
    (ep->xfer_len && (ep->xfer_len / ep->maxpacket) * ep->maxpacket == ep->xfer_len)
    {
    ep->xfer_len = 0;
    USB_EPStartXfer(hpcd->Instance, ep, 0);
    }

    The proper place to do this would probably be

    HAL_PCD_IRQHandler

    , but that calls the

    DataIn

    callback anyway. Regarding the receive function, I don't really know what you mean. I just use the Receive function from the template and piece together a command line from received characters. Or do you mean the transmit function?
    klaus
    Associate
    July 14, 2014
    Posted on July 14, 2014 at 11:18

    Hello Peter,

    where can I find the DataIn function you mentioned ?

    Could you explain why my approach doesn't work:

    uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)

    {

      uint8_t result = USBD_OK;

      /* USER CODE BEGIN 8 */

      USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);

      result = USBD_CDC_TransmitPacket(hUsbDevice_0);

      if ((Len%64==0) && (result==USBD_OK))

      {

        USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, 0);

        result = USBD_CDC_TransmitPacket(hUsbDevice_0);

      }

      /* USER CODE END 8 */

      return result;

    }

    Which library version do you use ?

    shippo
    shippoAuthor
    Associate II
    July 14, 2014
    Posted on July 14, 2014 at 12:36

    It's actually called 

    USBD_CDC_DataIn

    in the CDC class file

    usbd_cdc.c

    It's the function that is called when an IN transfer is complete.

    I guess the transfer isn't finished when you call 

    USBD_CDC_TransmitPacket

    the second time, do you get

    USBD_OK

    or

    USBD_BUSY

    returned?

    I use 1.3.0

    klaus
    Associate
    July 14, 2014
    Posted on July 14, 2014 at 13:00

    I get ''USBD_OK''

    shippo
    shippoAuthor
    Associate II
    July 14, 2014
    Posted on July 14, 2014 at 13:25

    Try to send more data than the TX FIFO holds, maybe you get

    USBD_BUSY

    then.

    Other than that, I have no idea. Just use the callback like I do, seems more logical to do it this way and it works.

    lfrodrigues
    Associate
    July 28, 2014
    Posted on July 28, 2014 at 20:31

    Hi Peter,

    I've also been struggling trying to make the vcp work. Would you be able to share your code?

    Best,

    Luis