hathach / tinyusb

An open source cross-platform USB stack for embedded system
https://www.tinyusb.org
MIT License
4.9k stars 1.03k forks source link

Don't receive packets immediately when usb packet equals CFG_TUD_ENDPOINT0_SIZE #2456

Open roel0 opened 7 months ago

roel0 commented 7 months ago

Operating System

Linux

Board

STM32U575

Firmware

938cae818

What happened ?

I dont receive USB packets when they are the maximum packet size CFG_TUD_ENDPOINT0_SIZE immediately. I do receive when the host sends more bytes. (The host is a linux PC). So it's seem that the incoming ZLP isn't processed.

If I trigger handle_epout_irq manually, the packet is still not processed. So the packet is for some reason not provided yet by the hardware.

How to reproduce ?

USB device with dualport CDC. Send exactly 64 bytes on FS connection

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

Will add later

Screenshots

No response

I have checked existing issues, dicussion and documentation

HiFiPhile commented 7 months ago

Are you sure a zlp was sent ? Normally it has to be done explicitly.

roel0 commented 7 months ago

Well,

  1. If I use the the official STM32 USB library (yikes), it works fine and I get 3 usb interrupts when receiving a 64 bytes from my linux host
  2. If I use tinyusb I only get one usb interrupt, which handles the 64 bytes packet. But no second interrupt to complete the transfer

-> So it's seems that the the stm32u575 is not correctly initialised by tinyusb? Still need to take a deeper look

roel0 commented 7 months ago

The issue appears when CFG_TUD_CDC_RX_BUFSIZE CFG_TUD_CDC_TX_BUFSIZE and CFG_TUD_CDC_EP_BUFSIZE have a different definition than CFG_TUD_ENDPOINT0_SIZE.

It's still a mystery to me why that is the case

HiFiPhile commented 7 months ago

Please enable debug print which gives you much more information.

HiFiPhile commented 4 months ago

USB 2.0 specification:

 A bulk transfer is complete when the endpoint does one of the following:
• Has transferred exactly the amount of data expected
• Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet
When a bulk transfer is complete, the Host Controller retires the current IRP and advances to the next IRP.
If a data payload is received that is larger than expected, all pending bulk IRPs for that endpoint will be
aborted/retired.

So it's a intended behavior.

If you need to receive packet immediately:

ST's lib works as it queue data length equal to EP size:

/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
#define CDC_DATA_HS_MAX_PACKET_SIZE                 512U  /* Endpoint IN & OUT Packet size */
#define CDC_DATA_FS_MAX_PACKET_SIZE                 64U  /* Endpoint IN & OUT Packet size */
#define CDC_CMD_PACKET_SIZE                         8U  /* Control Endpoint Packet size */

#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

#define CDC_DATA_FS_IN_PACKET_SIZE                  CDC_DATA_FS_MAX_PACKET_SIZE
#define CDC_DATA_FS_OUT_PACKET_SIZE                 CDC_DATA_FS_MAX_PACKET_SIZE