cancel
Showing results for 
Search instead for 
Did you mean: 

USB transfer multiple of packet size

shippo
Associate II
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...
17 REPLIES 17
jeanmark
Associate II
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
Associate II
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
Associate II
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 II
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
Associate II
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 II
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
Associate II
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 II
Posted on July 14, 2014 at 13:00

I get ''USBD_OK''

shippo
Associate II
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.