cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7RSxx OTG strange behavior with bulk transfer

simo zz
Senior

Hi,

I am testing the USB HS Device CDC implemented from the CDC example (so using ST middlewares) and I notice a strange behavior while reading transfers of 512B.

Internally, the function CDC_Receive_HS  file Appli/Src/usb_cdc_if.c has been adapted for a simple loopback as follows:

 

static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 11 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceHS);
  SCB_CleanDCache_by_Addr((uint32_t *)Buf, *Len);
  CDC_Transmit_HS(Buf, *Len);
  return (USBD_OK);
  /* USER CODE END 11 */
}

 

So basically, my testing program, based on libusb v1.0.27.11936, consists of consecutive bulk transfers to EP  #0x01 (bulk writing to STM32  CDC device) and from EP #0x81 (bulk reading from STM32 CDC device) during a time interval of 1 second.

It works fine except for bulk transfers of 512B: in this case, the test results in approx. 50% of zero length bulk reads (0 B of data) so resulting in 75% of the achievable throughput (a maximum of 12 MB/s for 511B transfers with this tests), since for any bulk transfer of size < 512B, there are no zero length reads: data written to STM32 CDC is correctly read back from it, both in therms of equal data transferred size (both W/R) and data matching.

I checked the MPSIZ and XFERSIZ fields values. The RM doesn't specify anything special regarding the programming value. I could check during debugging that 512 is being written into these fields.

So what could be the problem with exactly 512 B?

Sounds like a possible off-by-one error.

Thanks,

S.

1 ACCEPTED SOLUTION

Accepted Solutions

Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h

change:

 

#define CDC_DATA_HS_IN_PACKET_SIZE                  CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_HS_OUT_PACKET_SIZE                 CDC_DATA_HS_MAX_PACKET_SIZE

 

to 

 

#define CDC_DATA_HS_IN_PACKET_SIZE                  2*CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_HS_OUT_PACKET_SIZE                 2*CDC_DATA_HS_MAX_PACKET_SIZE

 

it seems that the relevant size is CDC_DATA_HS_IN_PACKET_SIZE.

Actually after various test, this is not failing with 512B.

View solution in original post

3 REPLIES 3
FBL
ST Employee

Hi @simo zz 

You need to consider overhead and propagation time for control transfers in high-speed operations? Bulk transfers have no reserved bandwidth and are scheduled after periodic and control transfers. In my understanding, 

  1. For a 512-byte payload consumes 8% of the micro frame bandwidth per transfer. Maximum of 13 transfers per micro frame. Theoretical maximum useful bandwidth is 53.2 MBps. So, ensure periodic transfers should not exceed 80% of the bus bandwidth.
  2. Total overhead for bulk transfer: 55 bytes

Modify the CDC_Receive_HS function to ensure that a ZLP is sent when the transfer size is exactly 512 bytes.

static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 11 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceHS);
  SCB_CleanDCache_by_Addr((uint32_t *)Buf, *Len);
  
  if (*Len == 512) {
    // Transmit 512 bytes
    CDC_Transmit_HS(Buf, *Len);
    // Send a zero-length packet to indicate the end of the transfer
    CDC_Transmit_HS(NULL, 0);
  } else {
    CDC_Transmit_HS(Buf, *Len);
  }
  return (USBD_OK);
  /* USER CODE END 11 */
}

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.


Hello @FBL,

Thank you for your interest.


@FBL wrote:

You need to consider overhead and propagation time for control transfers in high-speed operations? 


Not at the moment, the test is just for loopback, bandwidth, correctness of the functionality.

I tested sending a ZLP as you propose but it does not solve the issue. Also, why should I do it in case of exactly 512B? With, for example, 511B and 513B, this problem does not happen, so for every bulk transfer size different than 512B.

s.

Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h

change:

 

#define CDC_DATA_HS_IN_PACKET_SIZE                  CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_HS_OUT_PACKET_SIZE                 CDC_DATA_HS_MAX_PACKET_SIZE

 

to 

 

#define CDC_DATA_HS_IN_PACKET_SIZE                  2*CDC_DATA_HS_MAX_PACKET_SIZE
#define CDC_DATA_HS_OUT_PACKET_SIZE                 2*CDC_DATA_HS_MAX_PACKET_SIZE

 

it seems that the relevant size is CDC_DATA_HS_IN_PACKET_SIZE.

Actually after various test, this is not failing with 512B.