cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with sending more than 16Kbytes of data with CDC_Transmit_FS.

pass3master
Senior

We are trying to send serial data from an ST microcontroller to a PC using CDC_Transmit_FS.
We can send data less than 16Kbyte (4096 * 4byte) without any problem, but when we try to send larger size, sometimes we get USBD_STATUS_CANCELED (confirmed by Wireshark + USBpcap).
Could you please tell us why the above behavior occurs?

10 REPLIES 10
FBL
ST Employee

Hi @pass3master 

For bulk transfer in full speed, max packet size is 64. It is preferable to share your trace to understand better the error. Instead of sending a large chunk of data at once, split it into smaller chunks that fit within the endpoint buffer size (64bytes in FS mode).

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.


I'm out of offce with limited access to my emails.
Happy New Year!

Thank you for your response. I see.
So, if I want to transfer 40Kbytes of data, I need to call CDC_Transmit_FS 625 times (40000 ÷ 64)?

Hi @pass3master 

As explained in this article How to select suitable endpoints for your STM32 US... - STMicroelectronics Community, you can implement double buffering if available, to improve data throughput. Also, FIFO sizes can be adjusted to optimize performance and reduce CPU overhead. For example, to handle more data and reduce the frequency of FIFO overflows, bulk endpoints require large FIFOs to handle large data transfers efficiently. Otherwise, you can implement a timer to manage the transmission of large data chunks by generating periodic interrupts. Using this timer, you allow your STM32 perform other tasks in between transmission and reduce the risk of overwhelming the USB stack.

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.


I'm out of offce with limited access to my emails.
Happy New Year!

@pass3master wrote:

Thank you for your response. I see.
So, if I want to transfer 40Kbytes of data, I need to call CDC_Transmit_FS 625 times (40000 ÷ 64)?


Actually 626 times, to send the ZLP after the last 64-byte packet. Hint: use TransmitComplete callback to send the next portion. Also, check if the USB stack you use appends ZLPs automatically. If so, don't use 64-byte portions as they will be transmitted as 2 packets.

Also, do NOT call Transmit from the main loop - it should be called from and ISR of the same priority as USB interrupt. That in fact may be the source of your original problem.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Why should I not call CDC_Transmit_FS from the main loop?
Is it because other interrupts may occur during transmission?

It was explained in few threads on USB. The HAL routines are not designed to be reentrant. If a USB interrupt is triggered during the execution of Transmit, there is a chance to store an incorrect value in one of USB peripheral register. This may easily lead to USB hangups or incorrect operation. So, either use software-generated interrupt to call Transmit (the priority must be the same as USB hw interrupt) or call transmit with interrupts disabled.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Thank you for your answer. I see. I understand.
I have one more question. Is it possible to disable only the USB interrupt? Also, how should I write this in the program?

gbm
Lead III

Right, it's enough to disable USB int. Use NVIC_DisableIRQ() and NVIC_EnableIRQ().

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Pavel A.
Evangelist III

Except of one small thing: chance of priority inversion. If you raise the interrupt priority to the level of USB, all interrupts of lower priority will be blocked. If you just disable the USB interrupt, you remain at background/thread priority and can be preempted by interrupts of lower priority than the USB.