Linux RS485 support


EIA-485, also known as TIA/EIA-485 or RS-485, is a standard defining the electrical characteristics of drivers and receivers for use in balanced digital multipoint systems.

This standard is widely used for communications in industrial automation because it can be used effectively over long distances and in electrically noisy environments. See here for more information.

Some CPUs (e.g., Atmel AT91) contain a built-in half-duplex mode capable of automatically controlling line direction by toggling RTS. That can used to control external half-duplex hardware like an RS485 transceiver or any RS232-connected half-duplex device like some modems.

The Linux kernel has a huge amount of drivers. Probably more than any other (even commercial) OS. Incredibly, however, it doesn't have many drivers for RS485 serial communications. This may mean that Linux is not much used in this sector, yet.

History of RS485 support in the Linux kernel

The Linux kernel provides the serial_rs485 structure (see the include/linux/serial.h file) to handle RS485 communications. This data structure is used to set and configure RS485 parameters in the platform data and in ioctls.

The first driver having RS485 support was the serial driver for the Cris platform. Some time ago, I modified the driver to use kernel's rs485 data structure instead of a private one. In practice, I kept the old ioctl (adding a "deprecated" message) and I added a new ioctl to handle the new kind of communication. In the next months, I improved the RS485 interface of the driver.

I also worked on the Atmel serial driver, by adding RS485 support. As far as I know, this driver is used on several production systems, including the ThinLinx Hot-e systems.

Finally, I completed and fixed the Linux RS485 interface.

This is a partial list of commits (reverse chronological order) related to the RS485 support in Linux:
Currently, only the following Linux drivers support RS485 mode:
  • /drivers/serial/crisv10.c: serial driver used on the Cris ETRAX platform
  • /drivers/serial/atmel_serial.c: serial driver used on Atmel platforms (AVR32 and AT91 included)

Usage from user-level and support for additional drivers

The documentation about how to use RS485 from user space, as well as how to add RS485 support to an existing driver can be found in the Documentation/serial/serial-rs485.txt file in the Linux kernel sources. The most updated version of this file can be found here.

IMPORTANT: An inconsistency has been recently found in the usage of the fields of the serial_rs485 structure.
The crisv10.c and the atmel_serial.c serial drivers, in fact, interpreted the fields of the serial_rs485 structure in a different way.
In particular, crisv10.c used SER_RS485_RTS_AFTER_SEND and SER_RS485_RTS_ON_SEND for the logical level of the RTS pin; atmel_serial.c, instead, used these values to know if a delay had to be set before and after sending.
A patch to make the usage of these variables consistent across all drivers has been already merged mainline. The patch fixed the Documentation as well.

From now on, SER_RS485_RTS_AFTER_SEND and SER_RS485_RTS_ON_SEND will be used to set the logical level of the RTS pin (as in the crisv10.c driver); the delay will be understood by looking only at the value of delay_rts_before_send and delay_rts_after_send.

The SER_RS485_RTS_BEFORE_SEND flag has been removed. This flag had been added by mistake around 3 months ago, when the meaning of the flags seemed to be the enable of a delay instead of the logical value of the RTS pin, and this flag seemed to be missing.
Now that the meaning of the flags has been cleared, this flag has been removed.

If you want to use RS485 communications on Linux, please use a kernel release equal or greater than v3.2-rc3.

Last updated November 22nd, 2011