10
votes

I am trying to read a register from an RS485 adapter using a UART connection on an ARM board with no success

Machines

Connectors

Slave device connected to ARM board

Energy power meter <--rx/tx cable--> SENA RS485 Adapter <--Serial Male/Male adapter + Serial to mini serial cable --> ARM board mini-serial port

see images of the setup:

Device tree used: am335x-sbc-t335.dts

Device tree resources: http://get-album.com/dts/

Slave device connected to PC

Energy power meter <--2 wire rx/tx--> SENA RS485 Adapter <--> PC

note: The mini serial port on the board is the same port that is used for serial-console communication (on baud 115200) - and this works with no problems

Below is a c code that reads the first register from the connected slave device with the use of libmodbus library

libmodbus_test.c - reading and printing the first reigster from the device:

#include <sys/types.h>
#include <string.h>
#include <modbus.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h> 

#define MODBUS_DEVICE "/dev/ttyS2"
#define MODBUS_STOP_BIT 1
#define MODBUS_DATA_BIT 8
#define MODBUS_START_BIT 1
#define MODBUS_PARITY 'N'

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

    const char *dev_path = MODBUS_DEVICE;
    uint16_t result[2];
    int slave_nr = 31, baud = 9600;
    modbus_t *mb;

    if (argc == 2) {
        dev_path=argv[1];
    } 

    mb = modbus_new_rtu(dev_path, baud, MODBUS_PARITY, MODBUS_DATA_BIT, MODBUS_STOP_BIT);
    if (mb == NULL) {
        printf("error creating libmodbus rtu\n");
        return -1;
    }
    printf("created new rtu...\n");
    modbus_set_debug(mb, 1);
    if (modbus_connect(mb) < 0 ){
        printf("modbus error: %s\n", modbus_strerror(errno));
        modbus_close(mb);
        modbus_free(mb);
        return -1;
    }

    modbus_set_slave(mb, slave_nr);

    printf("ModBus connected !\n");

    if (modbus_read_registers(mb, 0x1, 2, result) < 0) {
        printf("error reading bits: %s\n", modbus_strerror(errno));
        modbus_close(mb);
        modbus_free(mb); 
        return -1;
    }

    printf("successfully red integer: %d:  %X (hex)\n", result[0], result[0]);

    modbus_free(mb);
    return 0;
}

[output from running libmodbus_test on PC]

root@cm-debian:~/new# modbus gcc -I /usr/local/include/modbus libmodbus_test.c -o libmodbus_test -lmodbus
root@cm-debian:~/new# ./libmodbus_test /dev/ttyS2
created new rtu...
Opening /dev/ttyS2 at 9600 bauds (N, 8, 1)
ModBus connected !
[1F][03][00][01][00][02][96][75]
Waiting for a confirmation...
<1F><03><04><00><DD><00><DD><54><51>
successfully red integer: 221:  DD (hex)

[output from running libmodbus_test on the ARM board]

root@cm-debian:~/new# gcc -I /usr/include/modbus/ libmodbus_test.c -o libmodbus_test -lmodbus
root@cm-debian:~/new# ./libmodbus_test /dev/ttyO0
created new rtu...
Opening /dev/ttyO0 at 9600 bauds (N, 8, 1)
ModBus connected !
[1F][03][00][01][00][02][96][75]
Waiting for a confirmation...
ERROR Connection timed out: select

when executing libmodbus_test from the ARM board, select() always returns 0 while running the same program on PC, it works just fine => the slave device returns data.

An attempt using termios also failed with similar results

termios_test.c

#include <sys/select.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <stdint.h>
#include <linux/serial.h>
#include <sys/ioctl.h>

static const uint8_t table_crc_hi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};


/* Table of CRC values for low-order byte */
static const uint8_t table_crc_lo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};


void calc_crc(uint8_t *buffer, ssize_t length, uint8_t *crc_hi_arg, uint8_t *crc_lo_arg) {

    uint8_t crc_hi = 0xff;
    uint8_t crc_lo = 0xff;
    unsigned int i;

    while (length--) {
        i = crc_hi ^ *buffer++;
        crc_hi = crc_lo ^ table_crc_hi[i];
        crc_lo = table_crc_lo[i];
    }

    *crc_hi_arg = crc_hi;
    *crc_lo_arg = crc_lo;

}

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

    char *dev_path = "/dev/ttyS2";
    if (argc == 2) {
        dev_path = argv[1];
    }
    uint8_t write_data[8];
    int fd,write_len,select_ret, bytes_avail, status;
    struct termios config;
    char c;
    uint8_t crc_hi, crc_lo;
    fd_set activefs, tmpfs;;
    struct timeval timeout;

    timeout.tv_sec = 0;
    timeout.tv_usec= 500000;

    fd = open(dev_path, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);

    if (fd == -1){
        perror("open");
        return 1;
    } 

    FD_ZERO(&tmpfs);
    FD_SET(fd, &tmpfs);

    printf("opened device\n");
    if (tcgetattr(fd, &config) < 0) { close(fd); return -1 }

    if (cfsetispeed(&config, B9600) < 0 || cfsetospeed(&config, B9600) < 0) {
        printf("cant setting speed!\n");
        close(fd);
        return 1;
    }


    config.c_cflag |= (CREAD | CLOCAL);
    config.c_cflag &=~ CSIZE;
    config.c_cflag &=~ CSTOPB;
    config.c_cflag &=~ PARENB;
    config.c_cflag |= CS8;

    config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

    config.c_iflag &= ~INPCK;
    config.c_iflag &= ~(IXON | IXOFF| IXANY);

    config.c_oflag &= ~OPOST;


    config.c_cc[VMIN] = 0;
    config.c_cc[VTIME] = 0;

    if (tcsetattr(fd, TCSANOW, &config) < 0) {
        printf("cant apply config!\n");
        close(fd);
        return 1;
    }


    write_data[0] = 0x1f; // slave addr
    write_data[1] = 0x03; // function
    write_data[2] = 0x00; // data address of first coil (8b)
    write_data[3] = 0x01; // data address of first coil (8b)
    write_data[4] = 0x00; // num of coils requested
    write_data[5] = 0x01; // num of coils requested
    calc_crc(write_data, 6, &crc_hi, &crc_lo);
    write_data[6] = crc_hi;
    write_data[7] = crc_lo;

    printf("data: [0x%x][0x%x][0x%x][0x%x][0x%x][0x%x][0x%x][0x%x]", write_data[0], write_data[1], write_data[2], write_data[3], write_data[4], write_data[5], write_data[6], write_data[7]);

    while (1) {

        sleep(1);
        write_len= write(fd, write_data, 8);
        activefs = tmpfs;
        select_ret = select(1, &activefs, NULL, NULL, &timeout);
        if (select_ret < 0) {
            perror("select");
            return 1;
        }

        if (select_ret > 0) {
            printf("select returned %d\n", select_ret);
            if (read(fd, &c, 1) < 0) {
                perror("read");
            } else {
                printf("received: %d\n", c);
            }
        }

    }


}

[output from termios.c on the ARM board]

root@cm-debian:~/new# ./termios /dev/ttyO0
opened device

... select keeps returning 0

[output from termios.c on PC]

$ gcc -o termios_test termios_test.c
$ ./termios_test /dev/ttyS2
opened device
data: [0x1f][0x3][0x0][0x1][0x0][0x1][0xd6][0x74]select returned 1
received: 31
select returned 1

Never mind the values, there IS a data exchange and that's what I want to achieve using the board

I tried passing RS485 attributes via pcntl, but the same results happened termios_rs485_test.c: http://pastebin.com/RWtHtjLF

The connection between the board and the PC is done through the ultra mini serial to DB9 cable and I can successfully read/write data from and to the board. How come reading data from the RS485 adapter never succeeds? where should I be looking in order to get closer a solution?

Here are some info about the board / drivers / etc

root@cm-debian:~/modbus# uname -a
Linux cm-debian 4.4.0-cm-t335-5.1 #98 SMP Thu Sep 1 15:12:31 IDT 2016 armv7l GNU/Linux

root@cm-debian:~/new# dmesg | grep -i --color '\(serial\|tty\|uart\)'
[    0.000000] Kernel command line: console=ttyO0,115200n8 root=ubi0:rootfs rw rootfstype=ubifs ubi.mtd=rootfs
[    0.771007] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.780286] omap_uart 44e09000.serial: no wakeirq for uart0
[    0.780329] of_get_named_gpiod_flags: can't parse 'rts-gpio' property of node '/ocp/serial@44e09000[0]'
[    0.780960] 44e09000.serial: ttyO0 at MMIO 0x44e09000 (irq = 155, base_baud = 3000000) is a OMAP UART0
[    1.543031] console [ttyO0] enabled
[    1.550036] omap_uart 48022000.serial: no wakeirq for uart1
[    1.556099] of_get_named_gpiod_flags: can't parse 'rts-gpio' property of node '/ocp/serial@48022000[0]'
[    1.556764] 48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 156, base_baud = 3000000) is a OMAP UART1
[    2.953486] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    2.973176] usb usb1: SerialNumber: musb-hdrc.0.auto
[    3.572722] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[    6.689030] systemd[1]: Expecting device dev-ttyO0.device...
[    7.210727] systemd[1]: Starting system-getty.slice.
[    7.235407] systemd[1]: Created slice system-getty.slice.
[    7.241302] systemd[1]: Starting system-serial\x2dgetty.slice.
[    7.265277] systemd[1]: Created slice system-serial\x2dgetty.slice.
[    7.925632] systemd[1]: Starting LSB: controls configuration of serial ports...
[    8.485680] systemd[1]: Started LSB: controls configuration of serial ports.
[   14.840532] pinctrl-single 44e10800.pinmux: pin 44e10978.0 already requested by 48022000.serial; cannot claim for 481cc000.can
[   14.895866] pinctrl-single 44e10800.pinmux: pin 44e10980.0 already requested by 48022000.serial; cannot claim for 481d0000.can


root@cm-debian:~/modbus# setserial -a /dev/ttyO0
/dev/ttyO0, Line 0, UART: undefined, Port: 0x0000, IRQ: 155
        Baud_base: 3000000, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal

root@cm-debian:~/new# setserial -a /dev/ttyS2
/dev/ttyS2, Line 2, UART: unknown, Port: 0x0000, IRQ: 0
        Baud_base: 0, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal

root@cm-debian:~/new# setserial -a /dev/ttyS1
/dev/ttyS1, Line 1, UART: unknown, Port: 0x0000, IRQ: 0
        Baud_base: 0, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal

root@cm-debian:~/new# setserial -a /dev/ttyS0
/dev/ttyS0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
        Baud_base: 0, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal


root@cm-debian:~/modbus# lsmod
Module                  Size  Used by
sha256_generic          9731  1
hmac                    2866  1
drbg                   13731  1
ctr                     3673  2
ccm                     7928  2
arc4                    2000  2
wl12xx                 57190  0
wlcore                180594  1 wl12xx
mac80211              605465  2 wl12xx,wlcore
cfg80211              492985  2 mac80211,wlcore
snd_soc_davinci_mcasp    15953  2
snd_soc_tlv320aic23_i2c     2092  1
snd_soc_simple_card     7474  0
snd_soc_tlv320aic23    10191  1 snd_soc_tlv320aic23_i2c
snd_soc_edma            1309  1 snd_soc_davinci_mcasp
snd_soc_core          158330  5 snd_soc_davinci_mcasp,snd_soc_edma,snd_soc_tlv320aic23_i2c,snd_soc_tlv320aic23,snd_soc_simple_card
snd_pcm_dmaengine       5548  1 snd_soc_core
snd_pcm                92743  4 snd_soc_davinci_mcasp,snd_soc_core,snd_soc_tlv320aic23,snd_pcm_dmaengine
c_can_platform          6650  0
c_can                   9638  1 c_can_platform
wlcore_spi              5086  0
can_dev                12315  1 c_can
ti_am335x_adc           5635  0
snd_timer              21413  1 snd_pcm
kfifo_buf               3452  1 ti_am335x_adc
snd                    55936  3 snd_soc_core,snd_timer,snd_pcm
industrialio           40286  2 ti_am335x_adc,kfifo_buf
evdev                  13187  0
omap_wdt                5293  0
soundcore               1339  1 snd


root@cm-debian:~/new# cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 2 (v7l)
BogoMIPS        : 597.60
Features        : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x3
CPU part        : 0xc08
CPU revision    : 2

Hardware        : Generic AM33XX (Flattened Device Tree)
Revision        : 0000
Serial          : 0000000000000000

root@cm-debian:~/new# cat /proc/consoles
ttyO0                -W- (EC p  )  250:0

root@cm-debian:/etc# cat debian_version
8.2

Any help is well appreciated Thanks

UPDATE

While the ultra mini serial to DB9 cable is connected to the board, I ran termios_test.c and while running, I inserted a metal piece in the middle pin of the cable (the TX) and I could see garbage data showing on the screen (sometimes!). I plugged the male-male adapter to the cable and touched the middle pin again, and I could see garbage data again.

Another thing I've done is connecting the slave device to to the SENA RS485 adapter, and use the metal piece on the pins, the middle pin of the adapter, when touching the metal, makes the TX led turn on. no pins would turn on the RX led. When connecting that RS485 adapter to the PC's COM port, sending data to that port would make the RX led flash. I am beginning to suspect that the board is not writing to the RS485 adapter correctly, or that pins are not mapped correctly. Where should I go from here? might this be really a software issue?

1
It sounds like systemd is starting getty on /dev/ttyO0 as well. And there are kernel parameters that uses ttyO0 as the kernel console. Try to get rid of that configurationnos
Removed /dev/ttyO0 from bootargs but this did not work either, same resultsTaher
Can you point to a device tree file in use? It looks like you have 'CAN' running on the ARM board (I guess not on the PC) and these different protocols can be claiming the UART. A basic test is to connect a loopback cable (or direct connect to a PC w. cross over) and run mini-com, etc just to see that you can use this port. Have you done that? This eliminates any issues with your code, voltages with devices, linux/init configuration, etc. Divide and conquer is always good. There are many layers where things can go wrong, so people can only guess.artless noise
Lowercase u in abbreviations is used as an alternative for prefix μ(micro), e. g. uC (microcontroller), um(micrometer) and so on. U in UART just means "universal", so the abbreviation should be spelled all-caps, otherwise it looks confusing.Igor Skochinsky
I see a modbus_test.c in the question and a libmodbus_test.c in the compilation command... Are these the same files?autistic

1 Answers

7
votes

There are two software issues found in the termios_test.c. First issue was related to missed tcgetattr(). Second one is what the first parameter to select() must be 1, not fd+1. Now they fixed and the code still don't work with SENA RS485.

Artless Noise suggested to connect ARM board to PC and check if UART on ARM board is properly configured. Smokie connected ARM to PC using ultra mini serial to DB9 cable and confirmed that termios_test.c can send and receive data to windows PC.

For now, I assumed than the problem is with physical connection of ARM to SENA. Ultra mini serial to DB9 cable used to connect ARM to PC is a crosscable. It connect ARM RX pin to PC TX pin and vice versa. SENA RS485 adapter is intended to be connected to PC directly without any cables. It has direct connetion: PC TX pin connected to SENA TX pin and PC RX pin to SENA RX pin. ARM is connected to SENA using ultra mini serial to DB9 cable and male - male COM adapter. Male - Male COM adapter doesn't change pin order, so TX pin became TX pin. So in the connection ARM TX pin became wrong connected to SENA RX pin.

In order to make schematic work, COM null modem cable must be used instead of Male - Male COM adapter. It basic pinout might be following:

ARM side                              SENA side
TXT pin 3                        <--> RXD pin 2
RXD pin 2                        <--> TXT pin 3
GND                              <--> GND
RTS pin 7 (leave unconnected)     +-> RTS pin 7
                                  |
CTS pin 8 (leave unconnected)     +-> CTS pin 8
                                  |
DTR pin 4 (leave unconnected)     +--> DTR pin 4 (to emulate the same behavior as PC does)
DCD pin 1 (leave unconnected)     (leave unconnected) DCD pin 1
DSR pin 6 (leave unconnected)     (leave unconnected) DSR pin 6

If SENA use hardware flow control, then RTS and DTR inputs must be connected to CTS output. If not, they might left unconnected. I suggest to connect RXD, TXD and GND signals first, and if that won't work, connect RTS, CTS and DTR pins.

It is possible to connect RTS and CTS pins to ARM to implement hardware flow control, but that doesn't make sence. Because SENA RS485 TX/RX speed is the same as UART speed. Anyway, the following changes should be made: install R44 and R45 (which is not installed on ARM board) and modify RTS/CTS pins in the ARM board DTS file (now they used as I2C1 pins) and setup UART in software to use flow control.

In case if someone claim UART on ARM you will see unexpected characters in the the data flow (for example you will see SENA TX pin blinks during ARM boot, if ARM using UART0 as console). Or you will see 'login:' or 'login incorrect' stings in the data flow if getty using UART. Also ARM boot ROM could print some strings to UART and you cannot disable that behaviour. U-boot might use UART as console and output banner strings. Be ready that such data will go into RS485 and somehow affect it's work.