You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
STM32U5 (dwc2) – FS USB – 1 CDC class – minimal implementation, unmodified from examples/device/cdc_dual_ports besides buffer sizes (and using only one CDC class).
If the OUT endpoint buffer size is less than twice the USB packet size and less than the amount of bytes sent by the host, the OUT endpoint buffer and subsequently the RX FIFO will miss bytes (for example: buffer size 70, transmitted bytes 80 -> 10 bytes lost). Even worse, those lost bytes get still written to memory beyond the linear buffer (memory overflow corruption).
Solution:
Either the buffer overflow bug detailed below must be solved, or atleast the examples/documentation should be modified:
CFG_TUD_CDC_RX_BUFSIZE has to be >= CFG_TUD_CDC_EP_BUFSIZE.
CFG_TUD_CDC_EP_BUFSIZE has to be >= 128 for FS resp. >= 1024 for HS.
Transmit more than 70 bytes (e. g. 80) from host to device.
Debug Log:
Defintion of OUT endpoint buffer (CFG_TUD_CDC_EP_BUFSIZE=70) in cdc_device.c:
As the RX FIFO (CFG_TUD_CDC_RX_BUFSIZE=1024) has plenty of space available, the OUT endpoint is prepared for xfer in _prep_out_transaction():
The call is forwarded by usbd_edpt_xfer() in usbd.c to dcd_edpt_xfer() in dcd_dwc2.c, still with the correct length (total_bytes = CFG_TUD_CDC_EP_BUFSIZE):
If the host transmits for example 80 bytes (b'0123456789012345678901234567890123456789012345678901234567890123456789ABCDEFGHIJ' in this case), those get split into two USB FS packages (64 bytes + 16 bytes). handle_rxflvl_irq() is called twice without return in between by
with bcnt=(64, 16), both times directly writing into the linear buffer:
No length check against xfer->total_len happens here, the bytes are directly written to memory (each 4 bytes as double words first, the remaining 1-3 bytes following):
Memory of xfer->buffer after the first copy (bcnt=64):
Memory of xfer->buffer after the second copy (bcnt=16), the 70 bytes long OUT endpoint buffer is overflown by 10 bytes (b'ABCDEFGHIJ' in this case):
We can potentially overflow to up to two FS packages (128 bytes) until the xfer->buffer pointer is reset – tested by transmitting 1kB of b'X':
The same should happen with HS USB, the overflow should increase to up to 1024 bytes.
The text was updated successfully, but these errors were encountered:
CFG_TUD_CDC_RX_BUFSIZE >= CFG_TUD_CDC_EP_BUFSIZE should be added as an assert.
CFG_TUD_CDC_EP_BUFSIZE has to be multiple of endpoint size (64,128, etc. for FS) otherwise DCD may not working correctly, in case of DWC2 it's mentioned in IP's programming guide but not in STM32's reference manual.
Board
STM32U5 custom
Firmware
STM32U5 (dwc2) – FS USB – 1 CDC class – minimal implementation, unmodified from examples/device/cdc_dual_ports besides buffer sizes (and using only one CDC class).
Two bugs occur:
tud_cdc_rx_cb
RX callback happens and the stack stalls (see CDC epout_buf and epin_buf sizes should be different #1924 (comment) for the same bug).Solution:
Either the buffer overflow bug detailed below must be solved, or atleast the examples/documentation should be modified:
CFG_TUD_CDC_RX_BUFSIZE
has to be >=CFG_TUD_CDC_EP_BUFSIZE
.CFG_TUD_CDC_EP_BUFSIZE
has to be >= 128 for FS resp. >= 1024 for HS.How to reproduce:
Debug Log:
Defintion of OUT endpoint buffer (
CFG_TUD_CDC_EP_BUFSIZE=70
) incdc_device.c
:As the RX FIFO (
CFG_TUD_CDC_RX_BUFSIZE=1024
) has plenty of space available, the OUT endpoint is prepared for xfer in_prep_out_transaction()
:The call is forwarded by
usbd_edpt_xfer()
inusbd.c
todcd_edpt_xfer()
indcd_dwc2.c
, still with the correct length (total_bytes = CFG_TUD_CDC_EP_BUFSIZE
):If the host transmits for example 80 bytes (
b'0123456789012345678901234567890123456789012345678901234567890123456789ABCDEFGHIJ'
in this case), those get split into two USB FS packages (64 bytes + 16 bytes).handle_rxflvl_irq()
is called twice without return in between bywith
bcnt=(64, 16)
, both times directly writing into the linear buffer:No length check against
xfer->total_len
happens here, the bytes are directly written to memory (each 4 bytes as double words first, the remaining 1-3 bytes following):Memory of
xfer->buffer
after the first copy (bcnt=64
):Memory of
xfer->buffer
after the second copy (bcnt=16
), the 70 bytes long OUT endpoint buffer is overflown by 10 bytes (b'ABCDEFGHIJ'
in this case):We can potentially overflow to up to two FS packages (128 bytes) until the
xfer->buffer
pointer is reset – tested by transmitting 1kB ofb'X'
:The same should happen with HS USB, the overflow should increase to up to 1024 bytes.
The text was updated successfully, but these errors were encountered: