Go Down

Topic: Is there a known speed limitation on the Uno USB UART? (Read 1 time) previous topic - next topic


I'm running a Uno R1 with a Linux host. I'm getting all kinds of corrupted data in the Uno -> Host direction.

I'm running at 115200 bps speed, which I believe means that the 8u2 that's on the board will run 115200 to the Atmega, but I believe the 8u2 always runs the USB bus at its native 12 Mbps (so, about 100x faster than the serial speed.)
It seems that the USB bus should keep up just fine.
I imagine that the Linux ACM USB drivers are pretty well worked out -- I'm on kernel 3.2, and people all over the world are running internets over cell phones over this kind of driver.

I've looked at the serial signal sent from the Atmega using a logic analyzer, and it's doing fine.

Are there any known bugs with data transfers to the master for older Uno boards?
Is there a firmware update I should apply to the 8u2?

Nick Gammon

I've looked at the serial signal sent from the Atmega using a logic analyzer, and it's doing fine.

My guess is the receiving program on the host cannot process data that fast.


i succesfully used a baudrate of 921600 on linux. what program and with wich configuration are you reading/writing the serial?
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie


I use 115200 with Linux just redirecting the serial device to a file with BASH. It works fine on Uno or Duemilanove allowing for the different device name.


but with this batch are you setting the right values? if no, try do do it.
maybe there is a different initialization by udev for USBx and ACMx devicies
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie


The atmega328p on the UNO running at 16MHz has a theoretical limit of (I can't decide which off hand) either 1Mbps or 2Mbps (depending on if you can set the baud rate generator to 0 and have it still work - something I'm not sure of).
Get 10% off all 4D Systems TFT screens this month: use discount code MAJENKO10


The BASH code I use

Code: [Select]

arduinoport=`cat /root/arduinoport` # sets arduinoport to suit UNO or Duemilanove which is stored in /root/arduinoport

stty -F $arduinoport cs8 115200 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts -clocal

cat $arduinoport|head -n 6|tail -n 4 > /root/arduino2

other than setting the device name  (/dev/ttyUSB0 for the Duemilanove) in /root/arduinoport that is the only change between the Uno and the Duemilanove. It has worked 100% once a minute over several years. Although I do use the Duemilanove most of the time. 


I have used two different programs:

1) A C++ program that configures the port with tcsetattr(), and then runs a recv() loop in a thread. I have tried with both O_NONBLOCK, and MIN=1/TIME=1 tty settings.
2) Simply "dd if=/dev/ttyACM2 of=foo bs=X" on the command line, with values of X of 1 and 16 and 64.

Note that latency is important -- data sent from the board is packetized in chunks of 7 - 18 bytes, and as soon as there is data, I want to be able to poll it.
The actual data rate is only about 2 kB/second, so at packet size 64, that's 32 calls to read() per second.

How big is the receive/USB buffer in the 8u2 on the Uno? Is it double-buffered? Maybe the firmware is available somewhere so I can look at it to answer this question myself?
I would expect that there would be sufficient buffering in the Linux ttyACM driver so that it could keep up with this simple data rate, but somehow, it's not yet working right.


After seeing this thread and posting in it, I thought I'd hook up my Uno in place of the Duemilanove in my long running home monitoring sketch. All appeared well so I left it to it, came back to it several hours later to find numerous holes in my graphs and log files. Not many, but not the 100% perfect record the Duemilanove has been turning in.  I've put the Duemilanove back in place.  I've had numerous doubts about the Uno since I bought one, this hasn't exactly inspired my confidence..............


It is an early Uno BTW - A genuine Italian one.

The Duemilanove I took out and put back is a Chinese knock off I bought on Ebay.


Yes, my Uno is early, too -- it's a R1, and it has the 8u2, not the 16u2 for serial conversion.
Maybe I should try the R3 and see if it's any better...


I tried with an R3, and it has the same problem.

I also tried with two stop bits (to give it a bit more breathing room) and with 38400 bps instead of 115200 bps, with about the same result.

Additionally, after a few hundred bytes, the receiving just stops, even though I can verify on the logic analyzer that the data is still being sent out the TX of the 328p. This happens no matter whether I use "cat," "dd," or my own program.

I'm going to have to try this on Windows now, to see if it really can be a Linux driver problem.


I took a look at the firmware for the 8u2 in the arduino-1.0.1 distribution.

I'm re-building the arduino-usbserial using the latest version of LUFA. Some changes were needed, because some symbols had changed names, but that worked out alright.

Now, I'm trying to program the 8u2 chip directly. After flashing the chip, the Linux USB stack sees it as ttyACM2, but any attempt to read from or write to it just hangs. This is most likely because of the update to a newer LUFA, as I didn't spend a ton of time on that. Does anyone else have experience with this? Or is the fact that I didn't combine with the DFU firmware the problem? If so, how do I do that combinification step?

Flashing back to the UNO-dfu_and_usbserial_combined.hex firmware goes back to the old broken behavior.

Nick Gammon

I'm getting all kinds of corrupted data in the Uno -> Host direction.

Can you give more detail? I had a sketch sending MIDI data in quite large volumes at 115200 baud to the serial monitor on a Mac. It didn't "seem" to lose any, although it might be hard to tell for sure. What I can say though is that the data lined up.  See here for example:


If bytes were being dropped, the text wouldn't line up the way it did.

How big is the receive/USB buffer in the 8u2 on the Uno? Is it double-buffered?

According to the datasheet:

Programmable maximum packet size from 8 to 64 bytes Programmable single or double buffer


I read through the code in the usbserial firmware, and it uses a 128 byte ring buffer going each direction, with a "high water mark" at 96 bytes.
At 10 bytes per millisecond, that's only 3 ms to drain a packet worst case, which may be hard to get with a 1 ms USB bus frame length. There may be other things on the USB bus, or the host may be temporarily busy or something...

Also, the ring buffer uses two pointers and one byte for count, when all it really needs is two bytes; one each for head and tail counter. Such waste ;-)

Right now, I'd like for my updated re-build of the firmware to actually work. I believe the problem is that the fuses are set to use the bootloader, which I have not programmed into the chip, and thus it hangs when I start it. But, that could be wrong, because the bus will at least see it ("lsusb" shows the Arduino device, etc.) If I can make this firmware work, then I can experiment enough to figure out where the loss is -- on the Linux side or the 8u2 side.
(I do not need or use the DFU functionality.)

Another option is perhaps to look at the VirtualSerial project from the LUFA distribution, and see if that will work any better...

Go Up