Enabling RS485 mode on Viola carrier board

Hi, I am trying to enable RS485 serial communication on the UART_B using the viola carrier board v1.1A and the colibri imx6. I’m following the code example described here:

http://git.toradex.com/cgit/linux-toradex.git/tree/Documentation/serial/serial-rs485.txt?h=toradex_vf_4.1

The problem is the execution of the ioctl with request TIOCGRS485 or TIOCSRS485 that returns error number 25 “Inappropriate ioctl for device”. Are these requests supported in the device driver? Can the UART_B work with RS485 support?

Thank you for your time.

Daniele

Currently only the 3.10.17 Kernel provides RS485 support:
http://git.toradex.com/cgit/linux-toradex.git/commit/drivers/tty/serial/imx.c?h=toradex_imx_3.10.17_1.0.0_ga&id=82cf64948ddab0360fab876ee321b6191ed7258a

You might be able to forward port the patch… What Version are you using?

Hi @stefan.agner I am a Daniele’s colleague. We are using the 3.14.28 kernel as provided in your bsp. Are you planning to port that patch in the 3.14.28?

Thanks for the answer.
The ioctl works using Linux kernel 3.10.17; however, even with rs485 mode enabled, i couldn’t manage to receive/transmit anything as the RTS signal isn’t set correctly by the driver. The only way I managed to make rs485 work was by disabling completely flow control and manually set the RTS signal before and after every transmission.

Here is the simple code I used to test rs485 mode:

int main(int argc, char *argv[])
{
    int fd;
    int rts_delay;
    char port_name[255]="";
    char transmit_data[255]="", receive_data[255]="";
    int transmit_number, receive_number;

    if(argc < 2){
        fprintf(stderr, "Usage:\t%s { port } { data } [ delay ]\n"
            "\tport         : port address\n"
            "\tdata         : data to be send\n"
            "\tdelay        : RTS delay time after send\n\n",
            argv[0]);
        return -1;
    }
    strcpy(port_name, argv[1]);
    strcpy(transmit_data, argv[2]);
    if(argc > 3){
        sscanf(argv[3], "%d", &rts_delay);
    }
    else{
        rts_delay = 20;
    }

    /* Open serial port */
    fd = open(port_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if(fd < 0){
        fprintf(stderr, "Error! can not open serial port: %d %s\n", errno, strerror(errno));
        return -1;
    }
    else{
        fprintf(stderr, "Port name = %s; fd is %d\n", port_name, fd);
    }

    /* Set serial port */
    struct termios my_termios;
    tcgetattr(fd, &my_termios);

    my_termios.c_cflag |=  CS8 | CREAD | CLOCAL;

    tcsetattr(fd, TCSANOW, &my_termios);

    /* Set RS485 mode */
    struct serial_rs485 rs485conf;
    rs485conf.flags |= SER_RS485_ENABLED;
    rs485conf.flags |= SER_RS485_RTS_ON_SEND;
    rs485conf.flags &= ~SER_RS485_RTS_AFTER_SEND;
    rs485conf.delay_rts_before_send = rts_delay;
    rs485conf.delay_rts_after_send = rts_delay;
    if(ioctl(fd, TIOCSRS485, &rs485conf) < 0){
        fprintf(stderr, "Error! set rs485 ioctl: %d %s\n", errno, strerror(errno));
        close(fd);
        return -1;
    }
    sleep(4);
    /* Transmit data */
    sprintf(transmit_data, "%s\n", argv[2]);
    transmit_number = write(fd, transmit_data, strlen(transmit_data));
    if(transmit_number < 0){
        fprintf(stderr, "Error! write data: %d %s\n", errno, strerror(errno));
        close(fd);
        return -1;
    }
    else{
        fprintf(stderr, "Complete! write %d chars: %s\n", transmit_number, transmit_data);
    }
    sleep(4);

    /* Receive data */
    while(1){
        fprintf(stderr, "Receive while\n");
        sleep(2);
        receive_number = read(fd, receive_data, 254);
        if(receive_number > 0){
            if(receive_data[0] == '\n'){
                continue;
            }
            receive_data[receive_number] = 0;
            fprintf(stderr, "Fantastic! read %d chars: %s\n", receive_number, receive_data);
         break;
        }
    }
    sleep(2);

    /* Close serial port*/
    if(close(fd) < 0){
        /* Error handling, See errno. */
    }
    return 0;
}

Am I missing something?