[BBB][Angstrom Distribution] [RS485] Applying a custom Patch

Hi all,

Yes I did it ^^, I successfully made my BBB ( Kernel 3.8.x ) work with the RS485 CAP ( I was able to talk with my PC with a USB<>RS485 adaptater )

To do it, I modified the Kernel (omap serial driver) and I tested it on a Ubuntu Distribution ( Why ? Because I don’t know how to modify the source code of the kernel with an angstrom distribution. And Robert Nelson explain very well how to do it with a Ubuntu distribution).

It’s true, that the eMMC use the GPIO1_0 & GPIO1_4 of the BBB and the RS485 cap need them, but it’s also easy to disable the virtual cap eMMC! Just a simple echo -4 > $SLOTS do the trick.
And I also had to create my own rs485 virtual cap to enable the GPIO1_0 & GPIO1_4 & UART1_TX & UART1_RX

But now, for my project I need to cross compile, and it looks like that there is no toolchain on the ubuntu distribution (working with the Robert Nelson Ubuntu distribution).

So I’m going back to the Angstrom distribution, but my problem is that I don’t know where to put my patch ? Will it work ? I don’t know how to create a patch, I just did this command : " sudo git diff > …/rs485.patch" ( Robert Nelson => on your KERNEL folder )

I read here => http://downloads.angstrom-distribution.org/demo/beaglebone/

That i can create my own image, with this :

git clone git://[github.com/Angstrom-distribution/setup-scripts.git](http://github.com/Angstrom-distribution/setup-scripts.git)
cd setup-scripts
./oebb.sh config beaglebone
MACHINE=beaglebone ./oebb.sh bitbake systemd-image

My question is where I can put my patch ? Or where I can modify the Kernel ?

Thx you every one, It’s because of your help, That I was able to make this Work !

I will soon explain my work on this project in my blog.

Michael Musset,

rs485 (1).patch (8.41 KB)

Nice! Good job!

You can also disable eMMc on boot if you put ‘capemgr.disable_partno=BB-BONE-EMMC-2G’ in the uEnv.txt file.


Is it possible that the next Angstrom release will include this patch ? :stuck_out_tongue:

I’m also interested in using the RTS pins to control the RS485 Transmit Enable. I have tried it directly
in my application over GPIO. But still not working smoothly.

It is possible to rebuild the kernel with the script rebuild.sh in the folder tools from GIT(RobertCNelson)

I’m also using the Kernel from RobertCNelson.
How can i execute the patch?

I could succesfully compile the kernel with your patch, but when I run my application I get the following error:

omap_uart 481a8000.serial: Could not request GPIO -1224967096 : -22

I use GPIO2_6 (32*2+6) = 70

Is it right to use
#define TIOCSRS485 0x5463

instead of
#define TIOCGRS485 0x542F

Did u compile the kernel with angstrom or for ubuntu? ( if it is for angstrom I’m interested since nobody answer me

Well first, u have to create a virtual cap to activate uart X. And check on your dmesg that u can see it.

Look at the video from dereck Molloy. On YouTube. And expl in very well how to do so, and explain everything about the device tree…

Hi Micka, thank you for the quick response.
Im using Debian with the latest kernel (3.8.13-bone22) and your patch.
I got all my uarts working. I can even send some data over RS485 when I set the gpio manually high (https://developer.ridgerun.com/wiki/index.php/Gpio-int-test.c).
But this should happen automatically when I send some data over the uarts with rs485 config.

Why I get error for -1224967096 : -22 (the number changes everytime)

Hey, sounds interesting, could you explain me how did you apply this path on the debian image :slight_smile:

I suggest, that om you modify the patch and put some printk( same as printf but it is for the kernel). You will be able to see the results in the dmesg.

I will soon explain every step in my blog.

This might be an old response, but I was able to get the patch working with Angstrom.

I am considering looking into using the RTS line for the DE toggle as it seems like it might be configurable from Devicetree settings if it is done this way. At the moment, you have to call ioctl commands (per the sample given) to configure it to run.

Please pardon my rough notes, I have not yet had a chance to type it up in a better way, but I thought someone might benefit from this anyway.

Steps to getting RS485 working:

  1. Download the RS485 Patch


  1. Download kernel tree for the patch
  • I used the following directions

*** Better yet, just read the README.md file after checking out the kernel from git ***

Prerequisites### ARM Cross Compiler

To compile the linux kernel for the BeagleBone Black, you must first have an ARM cross compiler installed. I use gcc-4.7-arm-linux-gnueabi-base that comes with Ubuntu 13.04. It is assumed the cross compiler has been added to your path.

uBoot mkimage

The bootloader used on the BeagleBone black is u-boot. u-boot has a special image format called uImage. It includes parameters such as descriptions, the machine/architecture type, compression type, load address, checksums etc. To make these images, you need to have a mkimage tool that comes part of the u-Boot distribution. Download u-boot, make and install the u-boot tools:

wget ftp://ftp.denx.de/pub/u-boot/u-boot-latest.tar.bz2
tar -xjf u-boot-latest.tar.bz2
cd into u-boot directory
make tools
sudo install tools/mkimage /usr/local/bin

Compiling the BeagleBone Black Kernel

git clone git://github.com/beagleboard/kernel.git
cd kernel
git checkout 3.8

Now run the RS485 patch

cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig
wget http://arago-project.org/git/projects/?p=am33x-cm3.git\;a=blob_plain\;f=bin/am335x-pm-firmware.bin\;hb=HEAD -O kernel/firmware/am335x-pm-firmware.bin
cd kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- beaglebone_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage dtbs

~~make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage-dtb.am335x-boneblack~~   <- Leave this out, makes the system refuse to boot                                            

// Might not need these? needs further testing
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=/home/cpeacock/export/rootfs modules_install

  1. Backup uImage-3.8.13 to uImage-3.8.13.old
  2. Copy the resulting uImage file into /boot/uImage-3.8.13


Had to modify:
/usr/include/linux/serial.h to match the newly compiled kernel (in particular the struct serial_rs485)

Hi all,

Interesting Work! What is the max baud rate you can get from this rs485 cape on BBB?



Well, I’m working with the BaudRate 38400 and I don’t have any problem. I didn’t try further.


Hi Mika,

I need to go two orders of magnitude higher (3.8 Meg, for a short distance of six feet, half duplex). Is there a chance with BBB?


The best way to know is to try … buy the beaglebone black, the rs485 cap and test it !

I am using a custom built cape for my application, so I have not tested it. Though according to the schematics it looks like the chip does not support those rates.

According to the schematic at:

It looks like the RS485 cape uses a TI transceiver part no: SN75HVD12Dhttp://www.ti.com/lit/ds/symlink/sn75hvd12.pdf

Should be able to go up to 1Mbps, but not much higher.

Checking the ARM Datasheet (AM335x ARM Cortex -A8 MPU Technical Reference Manual):

19.1.1 UART Mode Features
The general features of the UART/IrDA module when operating in UART mode are:

  • 16C750 compatibility

  • Baud rate from 300 bps up to 3.6864 Mbps

  • Auto-baud between 1200 bps and 115.2 Kbps

Since on the ARM side, you have slightly higher max data rates, so if you had a faster chip you could approach the rate you need given the right design. If you need faster than what is natively on the ARM, you could look into a custom solution with the PRU, but I don’t have any experience with that.



That is great info!

Thanks a bunch,


Hi All,

I have a interesting issue:

What I have did is:

  • Downloaded Angstrom linux
  • Applied RS485 patch
  • Compiled kernel image and push it to BBB.
    Now I have developed two applications:
  1. send.c : This application periodically sends the data on UART
  2. recv.c: This application waits to read the data from UART.
    Both above application works pretty well without any issue. Even I do not have to manually drive the GPIO. (Driver patch handles GPIO value perfectly.).


Now, I have developed an application which is combination of both send and recv. I mean , after sending one byte on UART from BBB to other host machine, I just wait for input bytes to receive(added receive timepout at 10 sec). Now in this cae, even if I do not send any character from host machine, BBB detects one/two arbitary bytes. This seems that driver changes GPIO position (from send mode to recv mode) before transmitte buffer gets empty.

Did any one has face this problem? Can you guys please share your thoughts on this?


What is the baudRate ? Can you spy the communication with an other device ? ( serial adapter rs485/rs232 )

In my case, baudrate 38400 work pretty well, without noise.

and please don’t UNDERLINE !


Hello Micka,

Thanks for your prompt response. I was using 115200. Now I have tried with 38400 and 9600 as well but still the problem persists.

Can you do me a favor? Can you please send the termios structure configurations with which query-response type application works at your end? Here is the configurations I am using:

struct termios my_termios, new_termios;
int fd0 = open("/dev/ttyO4", O_RDWR | O_NDELAY | O_NOCTTY);

tcgetattr(fd0, &my_termios);
my_termios.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
my_termios.c_oflag &= ~(OCRNL | ONLCR | ONLRET | ONOCR | OFILL | OLCUC | OPOST);
my_termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG | ECHOK | ECHOCTL | ECHOPRT);
my_termios.c_cflag &= ~(CSIZE | PARENB);
my_termios.c_cflag &= ~CRTSCTS;
my_termios.c_cflag |= CS8 | CLOCAL | CREAD;
my_termios.c_cflag &= ~CBAUD;
my_termios.c_cflag |= B9600;
my_termios.c_cc[VMIN] = 0;
my_termios.c_cc[VTIME] = 5;

rv = tcsetattr(fd0, TCSANOW, &my_termios);
tcgetattr(fd0, &new_termios);


Enjoy :

// 8N1 :
mode . c_cflag &= ( ~ CSIZE ) ; mode . c_cflag |= CS8 ;
mode . c_cflag &= ( ~ PARENB ) ;
mode . c_cflag &= ( ~ CRTSCTS ) ;

raw same as -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -opost -isig -icanon -xcase min 1 $
mode . c_iflag |= IGNBRK ;
mode . c_iflag |= IGNPAR ;
mode . c_iflag &= ( ~ INLCR ) ;
mode . c_iflag &= ( ~ ICRNL ) ;
mode . c_iflag &= ( ~ IXON ) ;
mode . c_iflag &= ( ~ IXOFF ) ;
mode . c_oflag &= ( ~ ONLCR ) ;
mode . c_oflag &= ( ~ OCRNL ) ;
mode . c_lflag &= ( ~ ISIG ) ;
mode . c_lflag &= ( ~ ICANON ) ;
mode . c_lflag &= ( ~ ECHO ) ;
rv=tcsetattr ( pContext->iHandlerConnection , 0 /
no special action */ , & mode );

Now, I have developed an application which is combination of both send and recv. I mean , after sending one byte on UART from BBB to other host machine, I just wait for input bytes to receive(added receive timepout at 10 sec). Now in this cae, even if I do not send any character from host machine, BBB detects one/two arbitary bytes.

Could you clarify what you mean by this? I am assuming you are essentially using one host as a master and one as the slave. Do you mean when neither end is transmitting, you are seeing arbitrary bytes, or that when the master sends a request out, you that same master sees bytes even if nothing is transmitted by either host?

If the random bytes are all 0’s or all 1’s (0x00, 0xFF) that might indicate some problems in what the non-driven state of the line voltage is.

If the bytes seem similar to what was being transmitted, you might be getting reflections if the line is not terminated properly.

This seems that driver changes GPIO position (from send mode to recv mode) before transmitte buffer gets empty.

Is this a guess from the behavior, or did you watch the signal lines, or use printk statements in the patch?

Did any one has face this problem? Can you guys please share your thoughts on this?

I have not seen this issue and have been using the patch at 38400 baud with an ADM2582 chip for a number of months now.