Unable to use RS-485 with Raspberry Pi CM3+ /dev/ttyAMA0

Hello everyone.

As the thread topic suggests, it appears to be almost “impossible” to implement Half duplex RS-485 on the Raspberry Pi Ubuntu Core 16 image. Have anyone of you implemented a fix or hack to enable this?

Here is my setup:
MAX3485 RX, TX <–> TX, RX pins of (ttyAMA0)
MAX3485 RE/DE <–> GPIO 17 (ALT3 mode, RTS0)

The MAX3485 is connected to a simple cheap RS485 USB converter, and when opening the /dev/ttyAMA0 port (cat /dev/ttyAMA0) I can receive data, so which means the RS-485 setup is working as it should. I can also manually toggle the GPIO17 HIGH to write, and that works.

I enabled RTS/CTS using the code from: https://github.com/mholling/rpirtscts
Now the kicker is just getting it to work on the kernel side (using ioctl to configure).
But my sample app kicks me out saying error 25: ‘Inappropriate ioctl for device’ when I want the kernel serial driver to handle the RTS toggling when receiving/transmitting.

Any advice?

My C app:
#include <linux/serial.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <string.h>
int main(void)
{
int fd; /File Descriptor/
int retStatus;
fd = open("/dev/ttyAMA0",O_RDWR); //Opening the serial port
if (fd < 0){
printf(“Unable to open /dev/ttyAMA0\n”);
printf("%s", strerror(errno));
close(fd);
return 1;
}

    struct serial_rs485 rs485conf;
    /* Enable RS485 mode: */
    rs485conf.flags |= SER_RS485_ENABLED;

    /* Set logical level for RTS pin equal to 1 when sending: */
    rs485conf.flags |= SER_RS485_RTS_ON_SEND;

    /* Set logical level for RTS pin equal to 0 after sending: */
    rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);

    /*Set the stuffs*/
    retStatus = ioctl(fd, TIOCSRS485, &rs485conf); /*Set the RS-485 mode*/
    if (retStatus < 0){
            printf("ioctl failed and returned errno %d \n",errno);
            printf("%s", strerror(errno));
            getchar(); 
    }
    else{
            printf("\nRS-485 Enabled.\n");
            getchar(); //To view the pins change before closing the port
    }
    close(fd);
 }

Are you running this application from inside a snap on Ubuntu Core 16?

I am running my sample app in the commandline, with sudo. (Compiled with gcc in Ubuntu Classic, executing outside of Classic)
Unless I have to create a simple snap app and connect it to the gadgetsnap?

are you running the app as root/with sudo ? Ubuntu Core does not add the system user to all the grups you are used to from an ubuntu desktop install so group rw permissions for device nodes do often not apply …

1 Like

Yes, I run the app with root permissions, (sudo/root)
It is also appearing to return the same error for ttyUSB0 as well.
Unless my code is not up to snuff?

I tested a simple C app as well with manually toggling the RTS pin to high, and it appears to be executing, so maybe it all comes down to the kernel not supporting the RS-485 (“SER_RS485_ENABLED”) stuff?

I have found that the serial driver ‘amba-pl011’ does not have the RS-485 support that I need, but I found this pull request not approved yet:

I’ve already compiled this changes on the “normal” Raspberry pi kernel, rather old (4.19), and it seemed to work when I run my app.
Will try to build it for Ubuntu Core, with the latest kernel version, with the changes/patch(es) included.

you should perhaps also file a bug so our kernel team is aware: