BeagleBone Black & RS485 CAP : almost done !

Hi,

I’m really sorry to contact you, but I’ve tried everything, I’ve done a lot of research. BUT but, there is just one thing missing and I can’t tell what is it …

First, I don’t understand why the beaglebone rs485 cap has connected the RE & DE to the pin :

  • GPIO1_4
  • GPIO1_0

If there was a way to connect the DE to the RTS pin of the uart, it would have been much more easy to control it. Maybe I’m missing something …

But, I’m not lucky, the signal DE is not connected to the pin RTS of the selected UART. So, I had to find a way to control it. Then luckily, I found a patch :

http://support.criticallink.com/redmine/projects/armc8-platforms/wiki/Driving_RS-485_transceivers

I know, it’s not the same kernel as the one that we have in the BeagleBoneBlack. But it’s almost the same driver omap.

So I looked at the file http://support.criticallink.com/gitweb/?p=linux-mityarm-335x.git;a=blobdiff;f=drivers/tty/serial/omap-serial.c;h=60f18a75928bce9c055af43ef93b91b8e3204fdb;hp=5e713d3ef1f47c49eaa93f8d4ced09ce87b89c1e;hb=3e1a3878bbe545b7d4a2ab65023a9938b0d5984e;hpb=4e9949242364492c8ffea0a738f1ab4e5a30752c

And I reported the modification to this file : RobertCNelson/linux-dev/KERNEL/drivers/tty/serial/omap-serial.c

I also changed the header include/uapi/linux/serial.h :

struct serial_rs485 {

__u32 flags; /* RS485 feature flags */

#define SER_RS485_ENABLED (1 << 0)

#define SER_RS485_RTS_ON_SEND (1 << 1)

#define SER_RS485_RTS_AFTER_SEND (1 << 2)

#define SER_RS485_RTS_BEFORE_SEND (1 << 3)

#define SER_RS485_USE_GPIO (1 << 5)

__u32 delay_rts_before_send; /* Milliseconds */

__u32 delay_rts_after_send; /* Milliseconds */

__u32 gpio_pin; /* GPIO Pin Index */

__u32 padding[4]; /* Memory is cheap */

};

I looked carefully at the README on how I can “hack” the actual driver :


Development/Hacking:



first run (to setup baseline tree): ./build_kernel.sh


then modify files under KERNEL directory 


then run (to rebuild with your changes): ./tools/rebuild.sh

The kernel successfully compiled. And the Beagleboneblack is booting ! yeah :

Linux beaglebone 3.8.13-bone18 #1 SMP Mon May 20 22:22:10 CEST 2013 armv7l GNU/Linux

I was very excited, I thought that it was done !

So I configured the serial port 4 by following this tutorial :

http://hipstercircuits.com/enable-serialuarttty-on-beaglebone-black/

And I tried a little piece of code :

#include <linux/serial.h>

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <termios.h>

#include <unistd.h>

#include <string.h>

#include <sys/ioctl.h>

/* Driver-specific ioctls: */

#define TIOCSRS485 0x5463

//#define TIOCSRS485 0x542F

/* new defines in linux/serial.h of CL provided kernel */

#ifndef SER_RS485_USE_GPIO

#define SER_RS485_USE_GPIO (1<<5)

#endif

#define GPIO1_0 (32*1+0)

#define USE2

/*

  • Test program for 485 control

*/

int main(int argc, char* argv[]){

struct serial_rs485 rs485conf;

char buffer2[21];

int i, rv, opt;

struct termios my_termios, new_termios, stdio;

printf(“test\n”);

int fd2 = open("/dev/ttyO4", O_RDWR | O_NOCTTY | O_NDELAY);

rs485conf.flags = (1<<0); //SER_RS485_ENABLED;

rs485conf.flags |= SER_RS485_USE_GPIO;

rs485conf.delay_rts_before_send = 0;

rs485conf.gpio_pin = GPIO2_20;

rv = ioctl (fd2, TIOCSRS485, &rs485conf);

if (rv) {

perror(“unable to set IOCTL:”);

}

tcgetattr(fd2, &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 | ECHOE | ECHOKE | 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 |= B115200; // B19200; //

my_termios.c_cc[VMIN] = 1;

my_termios.c_cc[VTIME] = 5;

rv = tcsetattr(fd2, TCSANOW, &my_termios);

tcgetattr(fd2, &new_termios);

fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);

printf(“Reading (hit q, return to quit)…\n”);

while(1){

if(read(fd2, buffer2, 1) > 0) write(STDOUT_FILENO, buffer2, 1);

if(read(STDIN_FILENO, buffer2, 1) > 0) {

if (buffer2[0]=‘q’) {

break;

}

}

}

close(fd2);

}

But after compiling and executing the code, I got : unable to set IOCTL:: Inappropriate ioctl for device

What ? Why ?

I’m sur that I modified the structure atmel_pops :


static struct uart_ops atmel_pops = {

		/* ... */
		**.ioctl          = serial_omap_ioctl,**

	};

I’m sure, that I’m also using the OMAP serial driver :

dmesg | grep tty

[41854.526040] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61) is a OMAP UART4

The only thing that I’m not sure, is how the ioctl function works ! What this error means exactly ? => unable to set IOCTL:: Inappropriate ioctl for device
I also discovered an error in the dmesg log when I enabled the uart4 with this tutorial : http://hipstercircuits.com/enable-serialuarttty-on-beaglebone-black/

the error message :

[41854.512676] bone-capemgr bone_capemgr.8: part_number ‘enable-uart5’, version ‘N/A’
[41854.512844] bone-capemgr bone_capemgr.8: slot #6: generic override
[41854.512893] bone-capemgr bone_capemgr.8: bone: Using override eeprom data at slot 6
[41854.512944] bone-capemgr bone_capemgr.8: slot #6: ‘Override Board Name,00A0,Override Manuf,enable-uart5’
[41854.513244] bone-capemgr bone_capemgr.8: slot #6: Requesting part number/version based 'enable-uart5-00A0.dtbo
[41854.513297] bone-capemgr bone_capemgr.8: slot #6: Requesting firmware ‘enable-uart5-00A0.dtbo’ for board-name ‘Override Board Name’, version ‘00A0’
[41854.518086] bone-capemgr bone_capemgr.8: slot #6: dtbo ‘enable-uart5-00A0.dtbo’ loaded; converting to live tree
[41854.518545] bone-capemgr bone_capemgr.8: slot #6: #3 overlays
[41854.522759] omap_uart 481a8000.serial: did not get pins for uart4 error: -19
[41854.526040] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61) is a OMAP UART4
[41854.531592] bone-capemgr bone_capemgr.8: slot #6: Applied #3 overlays.

I really don’t know where to look at now … totally lost, why I got this error: Inappropriate ioctl for device ?
Is it also the right approach ? Do you have some better Idea ?

the source file of my omap-serial.c file : http://pastebin.com/ddakpHX8

Thx you very much for your help,

Micka,

OK. So. These boards are not made or supported by BeagleBoard.org.

They are sold under the beagleboardtoys.com name and designed and supported by the same company that makes the BeagleBoard.

You need to contact them at support@beagleboardtoys.com

The cape is not currently supported on BeagleBone Black because the SW is still be rewritten for the 3.8 Kernel. A topic you will find all over the forum if you do a quick search.

If you go here, http://circuitco.com/support/index.php?title=BeagleBone_Black_Accessories#Compatible_Capes you will see that this cape is not listed as compatible at this time.

Gerald

Hi Micka,

I’ve also got an RS485 cape but have not played with it yet. I’ve just today got the RS232 cape working though.
I’m not sure if any of my findings could be helpful to you but in case you want to have a look, they are here and summarised here.

I’m surprised you’ve had to resort to compiling from source - having a look at the signals on P8 connector, it seems like the same could be achieved just using the device tree overlays approach.

Well, I would love that it work so easily … When I started my research, I didn’t heard about the new Kernel. But I’m glad that recently people understand how the new kernel works.

In my case, I don’t understand exactly how you would like me to use the device tree overlays. What I understand is that you are able to define in a file the MODE of the pins. But I don’t think that you are able to connect the UARTX_RTS to the GPIO1_0 ( DE signal of the RS485 cap ).

Yes, my problems is about the GPIO1_0 and GPIO1_4 . They are not connected to any UART ( no ? ). So how can I control them? (with the uart, automatically) Is there any existing driver that can control those pins ? The wrong way would be to control them in my C++ code. But It’s not clean, and I would lose performance with high baud rate.

Micka,

Micka,

i’ve already responded to this guy a number of times, but we can tell him again.

not all of the UARTs on the AM335x support full flow control, also the fact is that most of the flow control signals are not brought out to the expansion header.

the original RS-485 cape was designed for use with a non-linux OS, therefor no linux kernel support was ever added.

due to the fact that we do not provide official software support for the RS-485 cape, we can not provide any additional resources for enablement under linux.

Dave

Thx you for your answer,

I know that this cap is not supported, I just want to know if my approach is the correct one? I think that it could work.

Also if possible, can you you tell me, which OS support this RS485?

Thx you very much,

Micka,

Thx you for your answer,

I know that this cap is not supported, I just want to know if my approach
is the correct one? I think that it could work.

sorry i don't have first hand knowledge of the requirements for RS-485 support
in linux

Also if possible, can you you tell me, which OS support this RS485?

it was not linux based...

Dave

Hi Micka,

What is your current status? Did you managed to make the RS485 working on your BeagleBone?