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.
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,