Back at the previous post I discovered some pretty nasty latency issues with USB Serial ports, where the default settings would make byte level responses unfeasible. For this reason I decided to test the delay times of different serial ports I have laying around my PC, with some unexpected results and oddities.

Measuring latency

For this purpose I wrote a small C++ program that opens a given serial port, configures all the commonly used baud rates, and measures the time it takes to send a single byte and read it back (provided the RX/TX lines are tied together) and test it against the expected minimum time it would take to read back a byte. In essence, the time it takes to transmit it, start and stop bits included.

Windows binaries may be downloaded here and source code is available on the source code repository

The output of the application looks as follows:

COM6 (USB Serial Port)
Vendor: FTDI
Times measured in us
  Speed       Ideal    Minimum    Average    Maximum      Delta
    110:      90909        430       1006       1808     -89902
    300:      33333      39028      40058      43010       6724
    600:      16666      19972      21211      22139       4544
   1200:       8333      10038      11010      12013       2677
   2400:       4166       4997       5896       6564       1730
   4800:       2083       2830       3285       4040       1202
   9600:       1041       1419       2004       2880        962
  14400:        694        995       1226       2057        532
  19200:        520        988       1250       2068        729
  38400:        260        857       1011       1976        751
  56000:        178        420       1006       1989        827
  57600:        173        853       1007       2039        834
 115200:         86        578       1009       2005        922
 128000:         78        578       1007       1990        929
 256000:         39        418       1003       1991        964

Pretty straightforward. The first column has the baud rate, the “Minimum” and “Maximum” columns have the minimum and maximum delay measured during the test, and the “Average” column has the average delay measured across the 256 bytes written / read to the serial port.

Special mention to the “Ideal” column that shows the ideal delay that would be expected if the byte is ready and read just as soon as it has been transmitted over the wire. Also the “Delta” column is the result of subtracting the “Ideal” value to the “Average” value. A delta of 0 would mean no delay at all, a positive delta means the byte is received some time after the stop bit was transmitted and a negative delta means the byte was received before the stop bit was expected to be transmitted. That first row will make sense later.

Now on to the test cases.

FTDI FT232RL (default settings)

Running the test with the configuration windows assigns it out of the box we get some depressing results (all times in μs)

Speed Ideal Avg. Δ
110 90909 15906 -75002
300 33333 47862 14528
600 16666 31883 15216
1200 8333 15952 7619
2400 4166 15900 11733
4800 2083 15900 13817
9600 1041 15898 14857
14400 694 15943 15249
19200 520 15894 15373
38400 260 15902 15641
56000 178 15902 15723
57600 173 15900 15726
115200 86 15898 15811
128000 78 15898 15820
256000 39 15892 15853

First the bad news, delta times (Δ) are simply awful. Almost none of them manages to fall below 10000 μs with most of them nearing 16000 μs.

Second, the first row, the one at 110 baud, has learned how to time travel with a negative delta so big it would mean we got back the entire byte even before the first bit has been transmitted, and without read errors! So this requires breaking out the logic analyzer.

This ain't 110 baud...

After finding the magical U character (Hex: 0x55) we discover that this FTDI chip when asked to run at 110 bps it will silently configure itself to run at 115200 bps instead.

Now, measuring any other actually working transmission we confirm that indeed the delay between bytes is close to what the application has measured. In this example we measure the delay between 0x55 and 0x56 at 9600 bps.

15 freaking ms!

Around 15 ms of delay between bytes. Unacceptable.

FTDI FT232RL (low latency settings)

Next due to the unacceptable delay of the previous test, the FTDI chip is configured to have the lowest delay allowed, 1 ms, instead of the default 16 ms that the previous test has clearly shown it were being hindering the performance.

The new results are more acceptable, hovering around 1 ms on most cases.

Speed Ideal Avg. Δ
110 90909 1006 -89902
300 33333 40058 6724
600 16666 21211 4544
1200 8333 11010 2677
2400 4166 5896 1730
4800 2083 3285 1202
9600 1041 2004 962
14400 694 1226 532
19200 520 1250 729
38400 260 1011 751
56000 178 1006 827
57600 173 1007 834
115200 86 1009 922
128000 78 1007 929
256000 39 1003 964

The 110 baud bug is still there but we already know what it is, so no big deal.

SiLABS CP210x

Another USB to Serial chip, this time from Silicon Labs. The results are just like the default configuration FTDI, disappointing.

Speed Ideal Avg. Δ
110 90909 38176 -52732
300 33333 38185 4852
600 16666 22166 5499
1200 8333 14790 6457
2400 4166 9930 5763
4800 2083 8702 6619
9600 1041 8029 6987
14400 694 8137 7442
19200 520 8120 7599
38400 260 8235 7974
56000 178 8264 8085
57600 173 8204 8030
115200 86 8301 8214
128000 78 8250 8172
256000 39 8169 8129

Again the 110 baud configuration fails silently and uses the next thing, in this case the 300 baud config, and all the deltas hoover around the 8 ms mark.

Sadly, trying to disable the read buffer or reducing the latency, does nothing to improve the latency, making the CP210x series unusable for some purposes.

Motherboard COM port

Last, the COM port that my motherboard comes equipped with showed the strangest results so far

Speed Ideal Avg. Δ
110 90909 T! T!
300 33333 T! T!
600 16666 85191 68525
1200 8333 42968 34635
2400 4166 21644 17477
4800 2083 11081 8998
9600 1041 5749 4707
14400 694 3885 3190
19200 520 3092 2571
38400 260 1413 1153
56000 178 961 782
57600 173 972 799
115200 86 495 409
128000 78 E! E!
256000 39 E! E!

First off, 110 and 300 baud are apparently supported (driver allows me to open the port with that configuration) but no data is ever received (Timeout) so yet another serial port oddity to add to the mix.

Then it seems that the fastest the baud rate, the lower the latency, making this port the absolute fastest of the ones tested… at 115200 bps.

And last, the non-standard 128000 and 256000 baud rates are not supported, but this time the driver is kind enough to let me know about it.

Like the CP210x disabling the RX / TX buffers does nothing to improve the latency but in this case, some baud rates are actually usable.

Conclusion

Serial ports on PC kinda suck if you are trying to minimize latency with very small payloads, getting into absurd territory if payloads are 1 or 2 bytes long.

Also, 110 bps is a cursed configuration. All the devices reported accepting that configuration when in reality all of them managed to screw it up in one way or another.