As the title, I noticed that sometimes the output buffer will be splited into two bulk packages.
e.g. if I send [1, 2, 3, 4, 5, 6, 7] by using SerialUSB.write(), sometimes the output package will be [1, 2, 3, 4] and [5, 6, 7], not [1, 2, 3, 4, 5, 6, 7].
Then I found that, in cdc_queue.c, we are using TransmitQueue to handle the output buffer, maybe for avoiding overflow? Not sure about this.
And for TransmitQueue, actually, it is a ring buffer. So when write pointer < read pointer, which means something like this:
[x4 x5 x6 x7 0 0 ...... 0 0 x0 x1 x2 x3]
x(n) means the output buffer we provided, 0 means no-related bytes.
Then the current approach will run USBD_LL_Transmit twice to send the whole output buffer.
first time, we send [x0 x1 x2 x3]
then, we send [x4 x5 x6 x7]
(it seems that each of them are called block in the code, I will call them block bellow)
Function call:
USBSerial::write
|-> CDC_TransmitQueue_Enqueue
|-> CDC_continue_transmit
|-> |-> CDC_TransmitQueue_ReadBlock
|-> |-> USBD_CDC_SetTxBuffer
|-> |-> USBD_CDC_TransmitPacket
|-> |-> |-> USBD_LL_Transmit
Before we send the data, as the comment in L980, the following code will set the total length of the packet.
|
/* Update the packet total length */ |
|
pdev->ep_in[CDCInEpAdd & 0xFU].total_length = hcdc->TxLength; |
But it seems that the total length is incorrect. It is same to the length of the block.
So two packets will be sent instead of one as expected.
For the solusion, I'm using USBD_LL_Transmit directly, instead of using the ring buffer TransmitQueue.
And it works as expected now, so I think there's a bug in the output buffer handling approach.
Desktop (please complete the following information):
- OS: Windows
- Arduino Cli: 0.34.2
- STM32 core version: 2.7.1
Board (please complete the following information):
As the title, I noticed that sometimes the output buffer will be splited into two bulk packages.
e.g. if I send [1, 2, 3, 4, 5, 6, 7] by using
SerialUSB.write(), sometimes the output package will be [1, 2, 3, 4] and [5, 6, 7], not [1, 2, 3, 4, 5, 6, 7].Then I found that, in
cdc_queue.c, we are usingTransmitQueueto handle the output buffer, maybe for avoiding overflow? Not sure about this.And for
TransmitQueue, actually, it is a ring buffer. So whenwrite pointer < read pointer, which means something like this:[x4 x5 x6 x7 0 0 ...... 0 0 x0 x1 x2 x3]
x(n) means the output buffer we provided, 0 means no-related bytes.
Then the current approach will run
USBD_LL_Transmittwice to send the whole output buffer.first time, we send [x0 x1 x2 x3]
then, we send [x4 x5 x6 x7]
(it seems that each of them are called
blockin the code, I will call them block bellow)Function call:
USBSerial::write
|-> CDC_TransmitQueue_Enqueue
|-> CDC_continue_transmit
|-> |-> CDC_TransmitQueue_ReadBlock
|-> |-> USBD_CDC_SetTxBuffer
|-> |-> USBD_CDC_TransmitPacket
|-> |-> |-> USBD_LL_Transmit
Before we send the data, as the comment in L980, the following code will set the total length of the packet.
Arduino_Core_STM32/cores/arduino/stm32/usb/cdc/usbd_cdc.c
Lines 980 to 981 in f31d070
But it seems that the
total lengthis incorrect. It is same to the length of the block.So two packets will be sent instead of one as expected.
For the solusion, I'm using
USBD_LL_Transmitdirectly, instead of using the ring bufferTransmitQueue.And it works as expected now, so I think there's a bug in the output buffer handling approach.
Desktop (please complete the following information):
Board (please complete the following information):