BBB UART4 RTS for RS-485

2,741 views
Skip to first unread message

lucaso...@gmail.com

unread,
Sep 3, 2014, 11:57:53 AM9/3/14
to beagl...@googlegroups.com
Hello,
I'm writing an app for BeagleBoneBlack running debian (3.8.13-bone50). I would like to use UART4 to communicate with RS485 transmitter over P9.24(UART4 Tx), P9.26(UART4 Rx) and P8.33 (UART4 RTS).
I've disabled HDMI and enabled overlays BB-UART4 and BB-UART4-RTSCTS

cat /sys/devices/bone_capemgr.9/slots
 
0: 54:PF---
 
1: 55:PF---
 
2: 56:PF---
 
3: 57:PF---
 
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
 
5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
 
6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN
 
7: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-UART4
10: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-UART4-RTSCTS

cat
/proc/tty/driver/OMAP-SERIAL
serinfo
:1.0 driver revision:
0: uart:OMAP UART0 mmio:0x44E09000 irq:72 tx:345 rx:0 RTS|CTS|DTR|DSR
4: uart:OMAP UART4 mmio:0x481A8000 irq:45 tx:61355 rx:1 brk:1 RTS|DTR|DSR


RS485 transmitter is connected through RS485-USB converter to PC. When I run screen /dev/ttyO4 9600 +crtscts and periodicaly write some data to it, PC receives it properly, but RTS line stays constantly low (I'm using scope on Tx and RTS lines).
I've also tried to write simple C program, using struct serial_rs485. When I write some data over this program, I got response: Resource temporarily unavailable and dmesg says omap_uart 481a8000.serial: Must use GPIO for RS485 Support.
When I tried to use:
struct serial_rs485 rs485conf;
rs485conf
.flags |= SER_RS485_USE_GPIO;
rs485conf
.gpio_pin = GPIO0_9;

I got error from gcc that it does not know those macros:
SER_RS485_USE_GPIO was not declared in this scope
 rs485conf
.flags |= SER_RS485_USE_GPIO;
struct serial_rs485 has no member named gpio_pin
  rs485conf
.gpio_pin = GPIO0_9;
GPIO0_9 was not declared in this scope
  rs485conf
.gpio_pin = GPIO0_9;

Could somebody help me? I have no more ideas.





Jerônimo Lopes

unread,
Sep 3, 2014, 12:33:55 PM9/3/14
to beagl...@googlegroups.com
Hi,

BB-UART4-RTSCTS-00A0.dts uses set those pins to UART RTS and CTS (mode 6). 

But to use with "struct serial_rs485 rs485conf" you don't need to set the pin as RTS, you just need to set the pin to GPIO (mode 7, at the .dts file).

I don't know if I was clear, but I used RS485 and RTS as a GPIO, works nice.


--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alexander Hiam

unread,
Sep 3, 2014, 1:07:26 PM9/3/14
to beagl...@googlegroups.com, lucaso...@gmail.com
I actually just put up a tutorial for doing this in Python: http://inspire.logicsupply.com/2014/09/beaglebone-rs-485-communication.html 
It uses GPIO1_16, but of course you can use any GPIO pin, including the one that's shared with UART4 RTS.

 
When I tried to use:
struct serial_rs485 rs485conf;
rs485conf
.flags |= SER_RS485_USE_GPIO;
rs485conf
.gpio_pin = GPIO0_9;

I got error from gcc that it does not know those macros:
SER_RS485_USE_GPIO was not declared in this scope
 rs485conf
.flags |= SER_RS485_USE_GPIO;
struct serial_rs485 has no member named gpio_pin
  rs485conf
.gpio_pin = GPIO0_9;
GPIO0_9 was not declared in this scope
  rs485conf
.gpio_pin = GPIO0_9;

 
That's because you're compiling with the standard libc headers, which don't include the modified serial_rs485 struct that uses the GPIO pin. The tutorial I linked above uses Python and just defines the same values locally, which you could do in C as well. You could also grab the Kernel source and include 'include/uapi/linux/serial.h', which has the patched serial_rs485 struct (https://github.com/RobertCNelson/bb-kernel/blob/am33x-v3.8/patches/fixes/0007-omap-RS485-support-by-Michael-Musset.patch#L201). 

lucaso...@gmail.com

unread,
Sep 4, 2014, 8:40:29 AM9/4/14
to beagl...@googlegroups.com
Thank you for your answers. The python code is working perfectly.
I need to use it in greater C project though. So I am compiling new kernel including RS485 patch. I have tried /opt/scripts/tools/update_kernel.sh hoping that it includes the RS485 patch ...unsuccessfully.
I am now following steps from http://jkridner.wordpress.com/2014/06/04/yet-another-set-of-notes-on-building-beaglebone-kernel/

Dne středa, 3. září 2014 17:57:53 UTC+2 lucaso...@gmail.com napsal(a):

Micka

unread,
Sep 4, 2014, 3:51:58 PM9/4/14
to beagl...@googlegroups.com

In the Debian image from Robert C Nelson, the patch rs485 is already included.

lucaso...@gmail.com

unread,
Sep 8, 2014, 7:03:20 AM9/8/14
to beagl...@googlegroups.com
I've downloaded Robert C Nelson's code and run build_kernel.sh and install_kernel.sh. I've controlled that sources are patched by rs485 patch.
BBB booted up normally and uname -r says that I am running new kernel. But I don't have patched kernel headers. I have created serial.h header as following:
 1 #include <linux/types.h>
 
2
 
3
 
4 struct serial_rs485 {
 
5         __u32   flags;                  /* RS485 feature flags */
 
6 #define SER_RS485_ENABLED               (1 << 0)        /* If enabled */
 
7 #define SER_RS485_RTS_ON_SEND           (1 << 1)        /* Logical level for
  8                                                            RTS pin when    
  9                                                            sending */

 
10 #define SER_RS485_RTS_AFTER_SEND        (1 << 2)        /* Logical level for
 11                                                            RTS pin after sent*/

 
12 #define SER_RS485_RTS_BEFORE_SEND (1 << 3)
 
13 #define SER_RS485_USE_GPIO (1 << 5)
 
14 //#define SER_RS485_RX_DURING_TX          (1 << 4)
 
15         __u32   delay_rts_before_send;  /* Delay before send (milliseconds) */
 
16         __u32   delay_rts_after_send;   /* Delay after send (milliseconds) */
 
17 //       __u32   padding[5];             /* Memory is cheap, new structs
 
18                 __u32 gpio_pin; /* GPIO Pin Index */
 
19                 __u32 padding[4]; /* Memory is cheap, new structs
 20                         are a royal PITA .. */

 
21 };


and used it in small example program:
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include "serial.h"
//#include <include/uapi/linux/serial.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
   
int fd = open("/dev/ttyO4", O_RDWR | O_NOCTTY | O_NDELAY);
   
if (fd < 0)
   
{
        perror
("Error opening tty!");
       
return 1;
   
}

   
struct serial_rs485 rs485conf;

    rs485conf
.flags |= SER_RS485_ENABLED;

    rs485conf
.flags |= SER_RS485_USE_GPIO;
    rs485conf
.gpio_pin = 9;
    rs485conf
.flags |= SER_RS485_RTS_ON_SEND;
    rs485conf
.flags &= ~(SER_RS485_RTS_AFTER_SEND);
    rs485conf
.delay_rts_before_send = 0;
    rs485conf
.delay_rts_after_send = 0;

   
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0)
   
{
            perror
("Bad ioctl");
   
}
   
   
struct termios ttyc;
    tcgetattr
(fd, &ttyc);
   
    cfsetospeed
(&ttyc, B9600);          
    cfsetispeed
(&ttyc, B9600);
    ttyc
.c_cflag &= ~CRTSCTS;
    ttyc
.c_cflag |= CS8 | CLOCAL | CREAD;
    ttyc
.c_cflag |= CRTSCTS;
    ttyc
.c_cc[VMIN] = 1;
    ttyc
.c_cc[VTIME] = 5;
    tcsetattr
(fd, TCSANOW, &ttyc);
   
   
char data = 0xAA;

   
int i = 0;
   
while(i < 10000)
   
{
       
if(write(fd, &data, 1) < 1)
       
{
            perror
("Error sending char");
           
break;
       
}
           
        i
++;
   
}
       
   
if (close (fd) < 0)
   
{
        perror
("Error closing tty!");
       
return 1;
   
}


   
return 0;
}
but RTS pin stays still LOW.


Dne čtvrtek, 4. září 2014 21:51:58 UTC+2 Mickae1 napsal(a):

Micka

unread,
Sep 8, 2014, 1:09:41 PM9/8/14
to beagl...@googlegroups.com

Normally If you look at the log (dmsg)  you should see a line rs485 something. It's a printk that I show when the ioctl work.

And of course you have to configure the pin correctly = pin mode for TX, rx,  gpio.

Alexander Hiam

unread,
Sep 8, 2014, 1:12:55 PM9/8/14
to beagl...@googlegroups.com


Normally If you look at the log (dmsg)  you should see a line rs485 something. It's a printk that I show when the ioctl work.

Right, it's 'rs485 v1.1'. If you see that in dmesg then the ioctl worked and it's almost certainly a pinmux issue.
 

lucaso...@gmail.com

unread,
Sep 9, 2014, 8:09:32 AM9/9/14
to beagl...@googlegroups.com
Yes, I can see 'rs485 v1.1'. The python code still works fine out of the box. C code Rx and Tx lines work OK but RTS still does nothing.
When I exported the GPIO9 by hand, dmesg got:
[  222.055685] gpio_request: gpio-9 (RS485 TXE) status -16
[  222.055730] omap_uart 481a8000.serial: Could not request GPIO 9 : -16

That means that 485 kernel support works. Without manually exporting it says just "[  537.089146] rs485 v1.1" and does nothing.

BUT now I've discovered something strange with logical level flags in struct serial_rs485, maybe I'm using different header or maybe I don't understand it correctly.
When I changed the SER_RS485_RTS_AFTER_SEND to 0 and SER_RS485_RTS_ON_SEND to 0, it started working fine.
That means, when sending data, RTS goes HIGH, after sending, it goes immediately LOW , that means,
I expected setting ON_SEND to 1 and AFTER_SEND to 0, but with this setting it just changed from LOW to LOW.

Thank you both again for Your valuable help.
I'm satisfied now :-)


Dne pondělí, 8. září 2014 19:12:55 UTC+2 Alexander Hiam napsal(a):

Alexander Hiam

unread,
Sep 9, 2014, 12:26:56 PM9/9/14
to beagl...@googlegroups.com, lucaso...@gmail.com


On Tuesday, September 9, 2014 8:09:32 AM UTC-4, lucaso...@gmail.com wrote:
Yes, I can see 'rs485 v1.1'. The python code still works fine out of the box. C code Rx and Tx lines work OK but RTS still does nothing.
When I exported the GPIO9 by hand, dmesg got:
[  222.055685] gpio_request: gpio-9 (RS485 TXE) status -16
[  222.055730] omap_uart 481a8000.serial: Could not request GPIO 9 : -16

That means that 485 kernel support works. Without manually exporting it says just "[  537.089146] rs485 v1.1" and does nothing.

BUT now I've discovered something strange with logical level flags in struct serial_rs485, maybe I'm using different header or maybe I don't understand it correctly.
When I changed the SER_RS485_RTS_AFTER_SEND to 0 and SER_RS485_RTS_ON_SEND to 0, it started working fine.
That means, when sending data, RTS goes HIGH, after sending, it goes immediately LOW , that means,
I expected setting ON_SEND to 1 and AFTER_SEND to 0, but with this setting it just changed from LOW to LOW.

Oh yeah, forgot about that. There's a couple ternary operators in the driver that I think might be backwards, which makes it the logic levels a bit counter intuitive. It's:
  SER_RS485_ENABLED | SER_RS485_USE_GPIO
for an active high RE/DE signal and:
  SER_RS485_ENABLED | SER_RS485_USE_GPIO | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND
for an inverted, active low RE/DE signal.
...

Micka

unread,
Sep 12, 2014, 5:02:31 AM9/12/14
to beagl...@googlegroups.com
my problem was two program working on the same uart ...^^

On Fri, Sep 12, 2014 at 10:39 AM, Micka <micka...@gmail.com> wrote:
Hello, everyone, I just notify something with the RS485 : 


I've made a test programm, and in this programm, I'm sending all the time one byte. 

With the oscilloscope, I can see that there is a delay between each frame : 100ms . 


Do you have the same thing ?


Micka,





Micka

unread,
Sep 12, 2014, 4:39:42 AM9/12/14
to beagl...@googlegroups.com, lucaso...@gmail.com
Hello, everyone, I just notify something with the RS485 : 


I've made a test programm, and in this programm, I'm sending all the time one byte. 

With the oscilloscope, I can see that there is a delay between each frame : 100ms . 


Do you have the same thing ?


Micka,





On Tue, Sep 9, 2014 at 6:26 PM, Alexander Hiam <hiamal...@gmail.com> wrote:

bmel...@gmail.com

unread,
Mar 23, 2017, 3:13:23 PM3/23/17
to BeagleBoard, lucaso...@gmail.com
Hi Alexander,

The link you provided does not work:


Do you mind sending me the tutorial? I am currently designing my own cape which will support two RS485 half duplex channels and your tutorial would be very helpful to get me started. My questions are:

1) Am I limited to UART4 or can I use any of the available UARTs on the Beaglebone Black?

2) Just to be 100% sure, I can use any of the GPIO pins for controlling DE & /RE pins on the RS485 transceiver (I'm using TI's ISO15MDW)?

Thank you,

Bolek

rnd...@gmail.com

unread,
Mar 24, 2017, 7:24:41 AM3/24/17
to BeagleBoard, lucaso...@gmail.com, bmel...@gmail.com
Hi,

We are having allot of problems getting RS485 with RTS working on Debian: Linux 4.4
CAn someone help?

Micka

unread,
Mar 24, 2017, 7:11:11 PM3/24/17
to BeagleBoard, bmel...@gmail.com, lucaso...@gmail.com
There is no problem with the kernel 4.4 and rs485. Just use the omap driver and not the 8250 driver. It works well for me since 4 years. 

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages