Arduino Serial Vs SerialUSB

[Andrew] wonders why the SerialUSB() function on the Cortex M3-based Arduino Due is so much faster than Serial() on the Uno or Nano, and shares his observations in this short video. He sets up an experiment with a simple sketch on both boards and uses Wireshark to evaluate the results.

Data is sent in the USB packets in groups of four characters on the ATmega-based boards, but the entire string is put in a packet on the Due board. If you look under the hood, the answer is hiding in plain sight. While the Arduino family of boards connect to your computer using a USB virtual serial port, the ATmega ones have an actual serial connection on-board. For instance, on the Nano there is an FT232RL between the USB connector and the microprocessor (on an Arduino Uno board, a small ATMEGA8U2 is used instead of an FTDI chip, but the concept is the same). On the Arduino Due, the USB connects directly to the SAM3X8E processor.

This concept doesn’t apply only to Arduino boards, of course. On any serial connection between two computers, when a virtual USB device is used on both sides of the link (no actual serial signals involved), the serial baud rate is a fictional thing — data transfer speeds depends on USB alone. We are curious why the packets contain four characters in [Andrew]’s ATmega Wireshark captures — why not 1, 2, or 10? Is this something that can be controlled by the programmer, or is it fixed by the protocol and/or the FTDI chip? If you have the answer, let us know in the comments below.

16 thoughts on “Arduino Serial Vs SerialUSB

  1. Latency timer. The driver checks the chip for data periodically, and grabs whatever data’s there. So in that case, the baud rate of the UART leads to 4 chars in it’s check time.

    The latency timer’s usually programmable: at least it is in the D2XX driver.

    1. This. The windows FTDI driver allows you to explicitly set the polling interval, all the way down to 1ms. I’m sure the same setting is available in linux via sysfs somewhere, or an ioctl.

      For typical baudrates it doesn’t matter too much. Most FTDI chips can go up to at least 3Mbps, though. At higher baudrates, you need to poll the device fast enough for its receive buffer to not overrun.

      I occasionally have to work with a piece of equipment with a rabbit microcontroller in it. It’s programmed over serial. The serial protocol was designed before USB serial adapters were commonplace. The programming tool errors out unless I use an FTDI dongle with the poll interval cranked down to 1ms, likely because of some handshaking with very tight timing constraints. Other adapters without configurable poll interval don’t work at all, since they’re likely only polling at 50-100Hz or do.

  2. USB based virtual serial ports allow you to configure the baudrate, but without a real UART anywhere, the data never actually gets clocked out at that rate. Instead, the data moves as fast as it can over USB. That’s going to be either 1Mbps, 10Mbps, or 480Mbps, depending on the microcontroller’s capability.

    Some embedded devices use the baudrate setting as an out-of-band communication channel. For example, setting the baudrate to 1200 might put the microcontroller into a bootloader mode.

    1. Yes, but maybe you need some configuration.

      like define this:
      -D USBCON
      -D USBD_VID=0x1EAF
      -D USBD_PID=0x0004
      -D USB_PRODUCT=\”bluepill\”

  3. ‘While the Arduino family of boards connect to your computer using a USB virtual serial port, the ATmega ones have an actual serial connection on-board. ‘
    Did you mean ‘While the AVR-based family of boards…’?

    1. I see how that was confusing… I meant that ALL of the Arduino boards connect to the computer using a virtual USB serial port. The ATMEGA ones convert it to real TTL logic-level serial signals on the board. Some Arduino boards, like the DUE which use a Cortex M3 with an integrated USB port, skip the “convert to serial” step. On these boards it is pure USB to USB link from your computer to the Arduino MCU.

    1. I’ve always found semihosting to be massive bottleneck. Yes, it’s convenient to use, but this can lead developers to forget they are doing large blocking calls. I’m more prone to use 1Mb UART with short error codes.
      Would love to learn another way for real time systems.

  4. Obviously when you search “due” on an English dictionary, you get the English word as in “your taxes are due”.

    The Italian word “due” means “two” (like “uno” means “one”) and it is not pronounced the same as English – it’s more like “doo-ay”, see this Italian pronunciation dictionary:

  5. The 4-byte packet is due to the internal MCU peripheral buffer.

    Check page 767 of the datasheet

    The UART_THR which is the UART Holding Buffer is 32bits wide, so that is 4 chars.
    You load the 4 chars, it starts transmitting, and when it’s done it fires up a TXEMPTY interrupt to notify the user and let it fill it again.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.