0
\$\begingroup\$

What is expected error rate and drop rate on ST-Link VCP USART?

On the Nucleo STM32F446RE, my code reads the USART VCP (of ST-Link) and echoes it back. It uses DMA, FreeRTOS, and FreeRTOS queues (enqueing each byte individually). It ISRs the DMA Transfer Complete, but also ISRs the USART IDLE, so that it echoes byte by byte.

When testing it manually, it seems to work perfectly.

I wanted to benchmark it, and found a linux-serial-test tool, which gives poor results:

$ linux-serial-test -p /dev/ttyACM0  -s  -n -f -Z -o 5 -i 7
    Linux serial test app
    Flush RX buffer.
    Stopped transmitting.
    /dev/ttyACM0: count for this session: rx=24764, tx=49152, rx err=12
    Stopped receiving.
    /dev/ttyACM0: count for this session: rx=27121, tx=49152, rx err=12

Nearly half the bytes dropped! And a non-trivial amount of errors. (Note that errors were much higher until I tweaked the DMA buffer size. And if I use the -w option, they go up also.)

Are these drops and errors hardware limits of the ST-Link (esp. since no flow control)? Are they potential issues in my code? Or perhaps the linux-serial-tester itself isn't testing correctly?

What performance of the VCP should I expect, and how should I test it?


Adding a delay in transmission (-a 1000) improves results:

$ linux-serial-test -p /dev/ttyACM0  -s  -n -f -Z -o 15 -i 25 -a 1000
Linux serial test app
Flush RX buffer.
/dev/ttyACM0: count for this session: rx=17977, tx=20480, rx err=0
/dev/ttyACM0: count for this session: rx=44060, tx=45056, rx err=0
Stopped transmitting.
/dev/ttyACM0: No data received for 2.0s. Exiting due to timeout.

and turning on compiler optimizations (either -Os or -O3) improves the rx rate while slightly increasing errors:

$ linux-serial-test -p /dev/ttyACM0  -s  -n -f -Z -o 5 -i 10
Linux serial test app
Flush RX buffer.
Stopped transmitting.
/dev/ttyACM0: count for this session: rx=36874, tx=53248, rx err=85
/dev/ttyACM0: No data received for 2.0s. Exiting due to timeout.

(the exact results vary, but that seems to be the pattern).

\$\endgroup\$
6
  • \$\begingroup\$ I have never had or heard anyone has issues with it. But I cannot answer that question what is the error and drop rate - it may have problems when benchmarked like that. Given that and and other questions you have, it is more likely the problem is in your F4 end. However, you can verify that by removing F4 out of the equation, simply use a wire to loop back the VCP TX to VCP RX directly. \$\endgroup\$
    – Justme
    Commented Sep 29, 2023 at 4:22
  • \$\begingroup\$ One thing I can imagine is that your controller is to slow to catch every interrupt. If you are sending 8bit at e.g. 115200bit/s, and you get an interrupt each 8bit, that gives you roughly 1us between two transmissions.. Is your system fast enough to process this? If you are using HAL functions and HAL ISR callbacks, the answer is no. \$\endgroup\$
    – Mau5
    Commented Sep 29, 2023 at 4:45
  • \$\begingroup\$ I do have to ask; do you use a genuine ST-Link, or a clone? Most people here just say they have an ST-Link but in reality they just have something with a same name for $5 on some shady online store. \$\endgroup\$
    – Justme
    Commented Sep 29, 2023 at 4:46
  • \$\begingroup\$ @Mau5 Your calculations are way off. Having an interrupt every 1us would mean bit rate of 10 Mbps. 115200 bps means interrupt every 86 us. \$\endgroup\$
    – Justme
    Commented Sep 29, 2023 at 4:48
  • \$\begingroup\$ @justme You are right. Sorry for that. \$\endgroup\$
    – Mau5
    Commented Sep 29, 2023 at 5:15

1 Answer 1

1
\$\begingroup\$

So I did a test.

Using your first command line, I tested three different serial ports.

  1. Some FTDI 232R USB cable, shorted TX to RX, no problems, 55296/55296, err=0

  2. Laptop built-in RS232 port with TX shorted to RX, no problems, 54031/54031, err=0

  3. Nucleo H7 with onboard ST-Link FW V2J38M27 or V2J39M27, TX shorted to RX, problems, always first test shows less received than sent, e.g 65012/65536, err=0

  4. Same Nucleo H7 with updated firmware to V2J42M27, even worse numbers and always first test fails, 61709/65536, err=0

But, this may mean nothing.

It may be the Nucleo FW is bad but we don't know. Linux ACM drivers may work poorly with STLink ACM. Test program may be arbitrary and may not be designed to take into account the specifics of some ports, like how USB fits into this, or ACM over USB, etc.

For example, it might just be that the ST-Link firmware has so small buffers that it can't receive all the data in the time required and send them to PC.

For example the FTDI 232R has 128 byte buffer on USB to UART transmit side, and 256 byte UART receive buffer to USB. So it can receive more than transmit in a single USB packet, but still it will lose data when receiving at 3Mbps, because 256 bytes handled as often as PC can poll the USB interface is less than continuous data stream at 3 Mbps.

So without flow control, there can anyway be missed bytes, depending on USB poll rate, USB packet size, and receive packet FIFO size in the USB UART chip implementation.

Since you noticed the issue, you could ask on ST forums if this is normal, what are the actual specs it can handle, and will there be ever be a fix or improvement, either on the firmware, specs, or documentation what the USB ACM VCP is capable of.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks! I replicated tests #1 and #3/4 (with my existing firmware) and got similar results. The jumper between SB13 and SB14 was physically held, not soldered, so I thought that explained the errors - but I assumed you soldered it. One other valuable test is to use the UART pins directly on the MCU to an FTDI cable, without ST-Link at all. However, either way, even the worst numbers on these tests are substantially better than my results in the OP, so clearly either the F4 MCU or my code on it is a substantial bottleneck. Next step: Rewrite my code for better performance. \$\endgroup\$ Commented Sep 29, 2023 at 14:08
  • \$\begingroup\$ @SRobertJames It might be that your F4 code performs too well why ST-Link VCP drops bytes. I assume you use DMA, and for that, you receive N bytes at slow throughput of ST-Link. When you have received one full buffer of N, you transmit out N bytes, using DMA, back-to-back with no gaps, and the ST-Link can't handle that burst rate. \$\endgroup\$
    – Justme
    Commented Sep 29, 2023 at 14:58
  • \$\begingroup\$ Actually, I had transmitted one byte at a time, in a loop. Tightening that loop so that its much faster improves results dramatically. \$\endgroup\$ Commented Sep 29, 2023 at 15:09
  • \$\begingroup\$ @SRobertJames Any question that involves code must post the code. \$\endgroup\$
    – Justme
    Commented Sep 29, 2023 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.