Getting my Raspberry Pi set up for high-speed serial UART communication

I bought a Raspberry Pi to work together with my rooms moodlight. The current system uses an FTDI USB to RS485 converter cable with a full-blown linux PC pushing 1Mbps of data over that to drive the animations. I intended to replace that system with a Raspberry, seeing as it already has a UART on-board and would only need a small RS485 chip to drive the bus.
Unfortunately, out of the box the Raspberrys UART can only push 115200baud, and it spits out a shitload of debug data on the serial lines.
Here’s what I did to allow it to use the UART for other things, and to drive the UART at 1Mbps 🙂

The limiting factor on the UART speed is that UART Clock. It only allows baudrates of UART_CLK/16, and the clock is set to 3Mhz by default, limiting it to 187500baud. To drive 1Mbps, we need a UART-clock of at least 16Mhz. To do this we need to:

This should then allow you to set the baudrate higher, to test run ‘sudo stty -F /dev/ttyAMA0 1000000’. If that runs without problems, it’s probably OK. You can test some more with ‘sudo bash’, and then ‘echo  BOO > /dev/ttyAMA0’ and see if an attached FTDI device picks it up at 1Mbps.

Next up is making sure nothing else is using the serial line.

Done! Now all that’s left is writing code to actually push something over that line and wire up a small rs485 chip 🙂

20 thoughts on “Getting my Raspberry Pi set up for high-speed serial UART communication”

  1. For those following… the link above points to the current version of bcm2708.c _NOT_ the version at time of posting. Code matching the post is here: https://github.com/raspberrypi/linux/blob/9efb470560c1507af609524f79b12fdf2b8ba30d/arch/arm/mach-bcm2708/bcm2708.c

    As of _today_ the code in question is now at line 198
    https://github.com/raspberrypi/linux/blob/822123d2cac563ce2f1e27ba7374ea4b43a621da/arch/arm/mach-bcm2708/bcm2708.c

    and is now set to UART0_CLOCK

  2. Have you tried the FTDI USB to RS485 with Raspberry and is it working OK? I need a way to drive RS485 from Raspberry Pi.
    Thanks

    1. I’m not 100% sure, I believe I did at some point test with the USB dongle and I believe it worked, but I do remember that in the end I opted for just a small 485 chip on the normal serial line instead, seeing as it was much(!!) cheaper and smaller 🙂

    2. Follow-up:
      I have been working with my RaspPi again with an FTDI dongle, and I’ve been experiencing some problems.
      In general it works, but one of the three receivers I have malfunction when the “signal” is generated by the RPi over the FTDI dongle. I believe this might be caused by the RPi providing a too low USB voltage and the FTDI in turn not being able to properly sync to the baud-rate.

      Seeing as the RPi features an on-board UART, I highly recommend using that one directly instead. Turning it to RS485 is as simple as putting something like an LTC485 inbetween, where you connect the TX pin to DI, RX to RO, and any other free GPIO pin to DE and RE to switch between sending and receiving (or hard-wire it to ground or 5V if you don’t need to switch).

        1. Yes, *BUT* I’m only using it to send data at this point, which works because 3.3v is higher than the on-threshold for the chip.
          If you want to wire up the receiving end too you should either get a chip that works on 3.3v, or put a voltage divider between the RPi and the 485-transceiver.

  3. FTDI adapter works ok, as long as you have latest kernel and usb set to 1.1 (dwc_otg.speed=1) , dont have my pi here.

  4. Hey!
    do you have an example code of the “code to actually push something over that line” ?

    I have been banging my head on the keyboard after multiple tryouts to handle interrupts from the BCM2835 but I couldn’t get it to work … I could have used ‘echo … > /dev/ttyAMA0′ to send data but then how do you send the DMX break ? (I suppose you were doing DMX)

    I have a FTDI chip over here but I would just really like to make it work any third-party hardware…

    1. The protocol I’m using at this point to drive my LED-strips is one I made up myself, and doesn’t use any break signal.
      However, I do think the normal Linux termios stuff should be able to handle DMX.
      Have a look at this page about termios, specifically the tcsendbreak command.

      Let me know if that helped you 🙂

      EDIT:
      Also this source code might help too. Search for “break_time_us” for the break stuff specifically, or just use that library to handle the DMX protocol for you 🙂

  5. Some UARTS do not support break signals, or only breaks which are too short for DMX specs. If you’re having these troubles (don’t know much about the pi’s uart yet) you can always generate the break using a seperate GPIO pin, OR’d or ANDed with the TX line. Remember that the break will not get queued in the FIFO, so you have to make sure that all the buffered data has been sent out before generating the break. This probably must be observed even for a uart-generated break.

  6. Thanks for this tutorial.

    I have 2 questions :
    – Today, is it still necessary to update start.elf ?
    – Could you provide an 2Gb image with 1Mb serial link “ready to flash” ?

    Thanks a lot.

    1. I found that the rasperian wheezy image that I downloaded did not need a recompiled kernel or a new start.elf. I only needed to modify /boot/config.txt as shown above to run at 230.4 kbaud.

      I downloaded the 2013-05-29-wheezy-armel.img image (it had the 3.6.11 kernel).

  7. I just spent an hour or so configuring my Macbook to compile the kernel and when I went to make the change to the file discovered that the file version was different and did not apply. I then thought: ‘maybe this change has already been rolled into the version of the kernel that I am running?’

    I made the other changes including the start.elf file and now everything works. No need to make a new kernel.

  8. Hello! I tried to do all that is described in this article. But it did not. Could you explain what I go wrong? I am new in Linux.

    When i download kernel source:
    git init
    git clone –depth 1 git://github.com/raspberrypi/linux.git
    I made these points.

    When I tried to checkout:
    git checkout rpi-3.2.27
    I got an “error: pathpec ‘rpi-3.2.27’ did not match any file(s) known to git”

    The next paragraphs i do without errors:
    git init
    git fetch git://github.com/raspberrypi/linux.git rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
    git checkout rpi-3.6.y
    git init
    git fetch git://github.com/raspberrypi/linux.git rpi-3.8.y:refs/remotes/origin/rpi-3.8.y
    git checkout rpi-3.8.y
    KERNEL_SRC=/home/me/linux/
    apt-get update
    apt-get -y dist-upgrade
    apt-get -y install gcc make
    CCPREFIX=/home/me/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-

    Next i try to clean the kernel source from the kernel clone location with “make mrproper” and i get the error:
    CLEAN .config
    rm: cannot remove ‘.config’: Is a directory
    ( I do this command from /home/pi/ directory )

    Where i am mistaken?

    After that i do next paragraph, but i’m not sure what the correct item fulfilled:
    “For those following… the link above points to the current version of bcm2708.c _NOT_ the version at time of posting. Code matching the post is here: https://github.com/raspberrypi/linux/blob/9efb470560c1507af609524f79b12fdf2b8ba30d/arch/arm/mach-bcm2708/bcm2708.c
    I download the bcm2708.c and repalce the file from directory:
    /home/pi/arch/arm/mach-bcm2708/

Leave a Reply

Your email address will not be published. Required fields are marked *