Back to home page

OSCL-LXR

 
 

    


0001 ===========================
0002 RS485 Serial Communications
0003 ===========================
0004 
0005 1. Introduction
0006 ===============
0007 
0008    EIA-485, also known as TIA/EIA-485 or RS-485, is a standard defining the
0009    electrical characteristics of drivers and receivers for use in balanced
0010    digital multipoint systems.
0011    This standard is widely used for communications in industrial automation
0012    because it can be used effectively over long distances and in electrically
0013    noisy environments.
0014 
0015 2. Hardware-related Considerations
0016 ==================================
0017 
0018    Some CPUs/UARTs (e.g., Atmel AT91 or 16C950 UART) contain a built-in
0019    half-duplex mode capable of automatically controlling line direction by
0020    toggling RTS or DTR signals. That can be used to control external
0021    half-duplex hardware like an RS485 transceiver or any RS232-connected
0022    half-duplex devices like some modems.
0023 
0024    For these microcontrollers, the Linux driver should be made capable of
0025    working in both modes, and proper ioctls (see later) should be made
0026    available at user-level to allow switching from one mode to the other, and
0027    vice versa.
0028 
0029 3. Data Structures Already Available in the Kernel
0030 ==================================================
0031 
0032    The Linux kernel provides the serial_rs485 structure (see [1]) to handle
0033    RS485 communications. This data structure is used to set and configure RS485
0034    parameters in the platform data and in ioctls.
0035 
0036    The device tree can also provide RS485 boot time parameters (see [2]
0037    for bindings). The driver is in charge of filling this data structure from
0038    the values given by the device tree.
0039 
0040    Any driver for devices capable of working both as RS232 and RS485 should
0041    implement the rs485_config callback and provide rs485_supported in the
0042    uart_port structure. The serial core calls rs485_config to do the device
0043    specific part in response to TIOCSRS485 ioctl (see below). The rs485_config
0044    callback receives a pointer to a sanitizated serial_rs485 structure. The
0045    serial_rs485 userspace provides is sanitized before calling rs485_config
0046    using rs485_supported that indicates what RS485 features the driver supports
0047    for the uart_port. TIOCGRS485 ioctl can be used to read back the
0048    serial_rs485 structure matching to the current configuration.
0049 
0050 4. Usage from user-level
0051 ========================
0052 
0053    From user-level, RS485 configuration can be get/set using the previous
0054    ioctls. For instance, to set RS485 you can use the following code::
0055 
0056         #include <linux/serial.h>
0057 
0058         /* Include definition for RS485 ioctls: TIOCGRS485 and TIOCSRS485 */
0059         #include <sys/ioctl.h>
0060 
0061         /* Open your specific device (e.g., /dev/mydevice): */
0062         int fd = open ("/dev/mydevice", O_RDWR);
0063         if (fd < 0) {
0064                 /* Error handling. See errno. */
0065         }
0066 
0067         struct serial_rs485 rs485conf;
0068 
0069         /* Enable RS485 mode: */
0070         rs485conf.flags |= SER_RS485_ENABLED;
0071 
0072         /* Set logical level for RTS pin equal to 1 when sending: */
0073         rs485conf.flags |= SER_RS485_RTS_ON_SEND;
0074         /* or, set logical level for RTS pin equal to 0 when sending: */
0075         rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
0076 
0077         /* Set logical level for RTS pin equal to 1 after sending: */
0078         rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
0079         /* or, set logical level for RTS pin equal to 0 after sending: */
0080         rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
0081 
0082         /* Set rts delay before send, if needed: */
0083         rs485conf.delay_rts_before_send = ...;
0084 
0085         /* Set rts delay after send, if needed: */
0086         rs485conf.delay_rts_after_send = ...;
0087 
0088         /* Set this flag if you want to receive data even while sending data */
0089         rs485conf.flags |= SER_RS485_RX_DURING_TX;
0090 
0091         if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
0092                 /* Error handling. See errno. */
0093         }
0094 
0095         /* Use read() and write() syscalls here... */
0096 
0097         /* Close the device when finished: */
0098         if (close (fd) < 0) {
0099                 /* Error handling. See errno. */
0100         }
0101 
0102 5. Multipoint Addressing
0103 ========================
0104 
0105    The Linux kernel provides addressing mode for multipoint RS-485 serial
0106    communications line. The addressing mode is enabled with SER_RS485_ADDRB
0107    flag in serial_rs485. Struct serial_rs485 has two additional flags and
0108    fields for enabling receive and destination addresses.
0109 
0110    Address mode flags:
0111         - SER_RS485_ADDRB: Enabled addressing mode (sets also ADDRB in termios).
0112         - SER_RS485_ADDR_RECV: Receive (filter) address enabled.
0113         - SER_RS485_ADDR_DEST: Set destination address.
0114 
0115    Address fields (enabled with corresponding SER_RS485_ADDR_* flag):
0116         - addr_recv: Receive address.
0117         - addr_dest: Destination address.
0118 
0119    Once a receive address is set, the communication can occur only with the
0120    particular device and other peers are filtered out. It is left up to the
0121    receiver side to enforce the filtering. Receive address will be cleared
0122    if SER_RS485_ADDR_RECV is not set.
0123 
0124    Note: not all devices supporting RS485 support multipoint addressing.
0125 
0126 6. References
0127 =============
0128 
0129  [1]    include/uapi/linux/serial.h
0130 
0131  [2]    Documentation/devicetree/bindings/serial/rs485.txt