chore(usb): cdc_queue now use uint32_t length#2550
Conversation
…E_BUFFER_PACKET_NUMBER>512 or CDC_RECEIVE_QUEUE_BUFFER_PACKET_NUMBER>512.
which allows CDC_TRANSMIT_QUEUE_BUFFER_PACKET_NUMBER>512 or CDC_RECEIVE_QUEUE_BUFFER_PACKET_NUMBER>512. Signed-off-by: warmonkey <luoshumymail@gmail.com>
|
Hi @warmonkey So I will not merge this PR, sorry. |
On STM32F4 USB_WritePMA will not be called. The actual function to send data over USB is USBD_LL_Transmit() -> ... -> USB_EPStartXfer() There two paths can trigger the USBD_LL_Transmit(): USBSerial::write() -> CDC_continue_transmit(), USBD_CDC_TransmitCplt() -> CDC_continue_transmit() -> USBD_CDC_TransmitPacket() -> USBD_LL_Transmit() -> HAL_PCD_EP_Transmit() -> USB_EPStartXfer() In CDC_continue_transmit() file: usbd_cdc_if.c line 345, it's calling as stated in stm32f4xx_ll_usb.c function USB_EPStartXfer line 782: from the code above we know that the size to send from CDC_TransmitQueue_ReadBlock() previously, is assigned to ep->xfer_len (at stm32f4xx_hal_pcd.c line 1940 for stm32f4), then write into OTG_FS_DIEPTSIZx or OTG_HS_DIEPTSIZx register as: from RM0008 RM0090 RM0432 we know the PKTCNT has 10bits, max value 0x3ff (1023), XFRSIZ has 19bits, max value 0x7ffff (524287). 1023 * 512 = 523776 < 524287 but, it's not easy to know the USB is running in HS or FS mode. In conclusion, we should limit the maximum size returned by CDC_TransmitQueue_ReadBlock() to OTG_MAX_PKTCNTUSB_FS_MAX_PACKET_SIZE which is 102364 (for now). I will read The CDC queue is a software buffer, it's not relevant to the PMA area. The PMA is located in Before I submit this PR I checked multiple times, compiled and deployed on actual products. I ran the test for at least 24hrs. |
|
Im working on an improvement. Will use |
|
@fpistm I think we should merge to make the feature available first. taking MAX_PACKET_SIZE = 64 is a conservative number so its correct but not optimal. iit will be slower on HS. |
There was a problem hiding this comment.
Pull request overview
This PR updates the USB CDC queue and related call sites to remove the previous ~32KB limitation caused by uint16_t length/index variables, enabling larger CDC transmit/receive queues when packet counts exceed 512.
Changes:
- Widened CDC queue indices/lengths from 16-bit to 32-bit and adjusted queue read/write logic accordingly.
- Updated
USBSerialread helpers to work with the widened receive-queue APIs. - Introduced a helper to compute the maximum TX transfer size and attempted to clamp TX chunking accordingly.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| libraries/USBDevice/src/USBSerial.cpp | Updates read helper locals to match widened receive-queue API types. |
| libraries/USBDevice/src/cdc/usbd_cdc.c | Adds USBD_CDC_GetTxMaxSize() helper to compute max TX transfer size. |
| libraries/USBDevice/src/cdc/usbd_cdc_if.c | Uses the new max TX size when selecting a transmit block. |
| libraries/USBDevice/src/cdc/cdc_queue.c | Widens queue counters and adds transmit block clamping logic. |
| libraries/USBDevice/inc/usbd_cdc.h | Declares the new USBD_CDC_GetTxMaxSize() API. |
| libraries/USBDevice/inc/cdc_queue.h | Widens queue struct fields and updates function signatures/macros. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #ifdef USE_USBD_COMPOSITE | ||
| uint8_t USBD_CDC_GetTxMaxSize(USBD_HandleTypeDef *pdev, uint8_t ClassId) | ||
| { | ||
| /* Get the Endpoints addresses allocated for this class instance */ | ||
| CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, ClassId); | ||
| #else | ||
| uint8_t USBD_CDC_GetTxMaxSize(USBD_HandleTypeDef *pdev) | ||
| { | ||
| #endif /* USE_USBD_COMPOSITE */ | ||
|
|
||
| return pdev->ep_in[CDCInEpAdd & 0xFU].maxpacket * USB_MAX_PKTCNT; | ||
| } |
| #define CDC_TRANSMIT_MAX_BUFFER_SIZE 65472 //STM32 USB OTG DIEPTSIZ PKTCNT maximum 0x3ff | ||
| #define CDC_RECEIVE_MAX_BUFFER_SIZE CDC_QUEUE_MAX_PACKET_SIZE |
| int CDC_TransmitQueue_ReadSize(CDC_TransmitQueue_TypeDef *queue); | ||
| void CDC_TransmitQueue_Enqueue(CDC_TransmitQueue_TypeDef *queue, const uint8_t *buffer, uint32_t size); | ||
| uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, uint16_t *size); | ||
| uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, uint32_t *size); |
| // Read flat block from queue biggest as possible, but max QUEUE_MAX_PACKET_SIZE | ||
| uint8_t *CDC_TransmitQueue_ReadBlock(CDC_TransmitQueue_TypeDef *queue, | ||
| uint16_t *size) | ||
| uint32_t *size) | ||
| { | ||
| if (queue->write >= queue->read) { |
raise cdc buffer size 32KB limit due to uint16_t length variables.
This PR fixes bug: cdc queue limited
Now CDC_TRANSMIT_QUEUE_BUFFER_PACKET_NUMBER and/or CDC_RECEIVE_QUEUE_BUFFER_PACKET_NUMBER both can be greater than 512. which every buffer size is 64B, 64*512=32768