Fastest serial communication between CPU and MCU

I’m wondering the fastest method people have found to send data from the Atheros CPU to the MCU on the Yun? I have an app where I would like to render UI for an LCD on the Linux side, and pipe it over to the MCU when it changes.

I have this working from my PC to the MCU over USB at at least 300kB/s using a super trimmed down Serial.read implementation, but running over Serial1 from the Linux results in much much slower speeds. Has anyone found a good way to do this over the serial connection?

If not, is it possible to connect the USB host into the micro USB on the Arduino to communicate from the Linux to the Arduino side that way?

In case someone is interested, this is the sketch code I am using for fast PC to MCU communication over USB. It is significantly faster than the default Serial implementation.

int FastSerialReadBytes(uint8_t* pBuffer, int len, unsigned long timeout = 1000)
{
    int bytesTotalRead = 0;
    unsigned long _startMillis = millis();
    do
    {
        bytesTotalRead += USB_Recv(CDC_RX, &pBuffer[bytesTotalRead], len - bytesTotalRead);
    }
    while(bytesTotalRead < len && millis() - _startMillis < timeout);
    return bytesTotalRead;
}

stonelance: (1) I'm wondering the fastest method people have found to send data from the Atheros CPU to the MCU on the Yun? I have an app ::::SNIP:::: (2) Has anyone found a good way to do this over the serial connection?

(3) If not, is it possible to connect the USB host into the micro USB on the Arduino to communicate from the Linux to the Arduino side that way?

::::SNIP::::

Hey stonelance,

I'm a bit dubious as to the amount of effort that is required for the final outcome, but only you can judge your situation.

1) In theory, there is a faster way to send data between the two chips. 2) There is a way to do this over the serial connection, but I have not tried it. 3) In theory, yes - the two external serial ports can be connected together, but it may not be worth the effort.

Here are a few things to know.

There is a serial connect between the CPU (SOC) and MCU. The recommend way to use the serial port is via the Bridge Library On the Arduino side (the MCU/ATmega32u4) it is Serial1 On the Linux side (the CPU/SOC) it is /dev/ttyATH0 (To verify this login via ssh, $ dmesg | grep tty)

IF YOU WANT TO OPTIMIZE THE SPEED, you'll need to adjust on driver on the Yun side, and then tweek the kernel/driver interface on the Linux side.

On your laptop/desktop, the source for the bridge library is in

${IDE_HOME_DIRECTORY}libraries/Bridge/src/

On the Linux side (the CPU/Atheros AR9331), the serial port is connected to the Bridge library - which is a python script. You'll need to disable the python script and take over the serial port. hotplug2 (I believe) traps the serial port and calls the python script (I have few details because I have not dived into it.) For reference, you can find the python script on the Linux side in /usr/lib/python2.7/bridge/ (There is also useful code in /usr/lib/python2.7/

Here is a decent tutorial on Serial Ports/TTY - The TTY demystified

To change the speed on the Linux serial port, OpenWRT has a write up.

Lastly, if you do not know, the Linux side runs on a kernel developed by OpenWRT

That's it.

Jesse

So I tried your suggestions: - Disabled bridge script - Checked the Linux serial port speed and it seemed reasonable (~230000) - Wrote my own python code to write directly to the /dev/ttyATH0 port - Arduino side uses Serial1

The resulting speeds were still extremely disappointing. I was hitting a maximum speed of around 34kB/s. Unless I am misunderstanding the baud speed, I should be able to get 6 times that.

Any other ideas? I saw in an older thread (http://forum.arduino.cc/index.php?topic=191820.0) some suggestions that the default Serial1 interrupt handlers were extremely slow and limiting the speed, so my next bet is to try to write my own optimized version of Serial1, but I would like to avoid it if there is a better way.

stonelance: ::::SNIP::::

Any other ideas? I saw in an older thread (http://forum.arduino.cc/index.php?topic=191820.0) some suggestions that the default Serial1 interrupt handlers were extremely slow and limiting the speed, so my next bet is to try to write my own optimized version of Serial1, but I would like to avoid it if there is a better way.

Yes, one thing I did not consider is re-writing the serial port on the Atmel (ATmega32U4) side. Before that, you might be able change baud rate on that side. However, a quick look at the data sheet tells me it could be a USART with hardware control or the SPI. My bet would the USART. The schematics say as much, even says it is using a MAX3375E

Both the data sheet and schematics are on this page. http://arduino.cc/en/Main/ArduinoBoardYun

Jesse

stonelance: - Checked the Linux serial port speed and it seemed reasonable (~230000)

230000 bits per second. Each byte takes 8 bits, plus a start bit and stop bit - a total of 10 bits to send a byte. So at 230,000 bits per second, the theoretical maximum rate is 23,000 bytes per second, or 22.46k bytes per second. The hardware simply can't send data faster than that.

I believe the default baud rate is actually 250000 bits per second. That would give a theoretical max throughput of 24.4 kB/s.

The resulting speeds were still extremely disappointing. I was hitting a maximum speed of around 34kB/s.

Disappointing? Sounds like you're getting about 140% of the theoretical maximum! I think your measurement technique is suspect, as I don't see how you can be getting that much bandwidth.

Unless I am misunderstanding the baud speed, I should be able to get 6 times that.

Unless I made an egregious error in my calculations, I would say you are misunderstanding something.

Go ahead and rewrite the drivers if you want, but I think that's a bit premature since you haven't proven a problem with software overhead yet.

stonelance: ::::SNIP::::

Any other ideas? I saw in an older thread (http://forum.arduino.cc/index.php?topic=191820.0) some suggestions that the default Serial1 interrupt handlers were extremely slow and limiting the speed, so my next bet is to try to write my own optimized version of Serial1, but I would like to avoid it if there is a better way.

stonelance, someone just asked on something I was completely unaware of. Namely, there is a GPIO line on the AR9331 that is connected directly to the ATMega32u4. It uses SPI and there is a library for it. I DON'T if this is related to the Bridge Library.

The question: AR9331 gpio to ATMEGA32u4

The person references: http://arduino.cc/en/Main/ArduinoBoardYun

Look for: SPI: on the ICSP header

Jesse

Thanks ShapeShifter. I realized after my post that the baud rate translates to bits. All documentation I read mentioned symbol rate and it wasn't clear if the symbol was the whole byte, or just each bit, but I eventually realized it was referring to a bit. I suspect my higher than theoretical rate was probably due to some buffering on the Linux side.

I did do some rewriting of the Serial1 code, but didn't get any significant improvements (at least not enough for my needs), and the potential for overflow really hampers my use-case. My next plan is to try to connect the two processors via the USB and see if it works.

stonelance: Thanks ShapeShifter. I realized after my post that the baud rate translates to bits. All documentation I read mentioned symbol rate and it wasn't clear if the symbol was the whole byte, or just each bit, but I eventually realized it was referring to a bit.

Yes, there is a subtle difference between baud rate and bits per second. Baud is symbols per second, but in the case of a simple serial port that uses binary signaling, a symbol is a bit.

But there are more complex encoding methods where a symbol can be several bits. Consider a modem that uses a fixed carrier frequency, and it can shift the phase of the signal: the symbol is the phase shift. If the modem can generate and detect two phase shifts (0 and 180 degrees) it can send one bit per symbol time (phase shift.) if it can handle 90 degree phase shifts (0, 90, 180, 270) then it can send two bits per symbol, and the bits per second is twice the baud rate. 45 degree phase shifts let it send three bits per symbol, so the bits per second is four time the baud rate. There are some encoding methods where the bits per second rate can be 64 times the baud rate.

But for straight serial, a symbol is a bit, and baud rate is synonymous with bits per second.