Table of contents
Currently, the linux kernel already supports the implementation of 485, but due to the support of the underlying driver, we need to modify the underlying driver when using different chips to meet the various callback interfaces of the kernel 485, and then realize 485 functions.
The 485 mainly lies in the time of switching between sending and receiving control. This article takes 8250 as an example to describe the process of 485 configuration and switching.
Serial port driver hierarchy
Do not discuss tty, tty is divided into three layers
1) Serial common layer
2) 8250 general purpose layer
3) Specific 8250 chip driver layer
8250_dw is the specific chip layer. When it is parsed that there is a corresponding configuration in the dts, the probe interface to this is called. If there are three serial ports in the dts, call the probe interface three times . Then call the interface of the upper layer in turn to report the serial port information.
485 configuration process
dts related
When the 8250_dw registers the serial port with the 8250, the 8250 layer calls back the general 485 dts analysis function uart_get_rs485_mode to obtain the support of the serial port to 485. The code of this function is as follows. Through this code, we can see several dts parameters whose functions are:
dts | Function |
rs485-rts-delay | Delay after 485 transceiver switching, unit ms |
rs485-term | Switch GPIO pin definition |
linux,rs485-enabled-at-boot-time | Whether to enable 485 by default, it can also be modified through ioctl later |
/**
* uart_get_rs485_mode() - retrieve rs485 properties for given uart
* @port: uart device's target port
*
* This function implements the device tree binding described in
* Documentation/devicetree/bindings/serial/rs485.txt.
*/
int uart_get_rs485_mode(struct uart_port *port)
{
struct serial_rs485 *rs485conf = &port->rs485;
struct device *dev = port->dev;
u32 rs485_delay[2];
int ret;
ret = device_property_read_u32_array(dev, "rs485-rts-delay",
rs485_delay, 2);
if (!ret) {
rs485conf->delay_rts_before_send = rs485_delay[0];
rs485conf->delay_rts_after_send = rs485_delay[1];
} else {
rs485conf->delay_rts_before_send = 0;
rs485conf->delay_rts_after_send = 0;
}
/*
* Clear full-duplex and enabled flags, set RTS polarity to active high
* to get to a defined state with the following properties:
*/
rs485conf->flags &= ~(SER_RS485_RX_DURING_TX | SER_RS485_ENABLED |
SER_RS485_TERMINATE_BUS |
SER_RS485_RTS_AFTER_SEND);
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
if (device_property_read_bool(dev, "rs485-rx-during-tx"))
rs485conf->flags |= SER_RS485_RX_DURING_TX;
if (device_property_read_bool(dev, "linux,rs485-enabled-at-boot-time"))
rs485conf->flags |= SER_RS485_ENABLED;
if (device_property_read_bool(dev, "rs485-rts-active-low")) {
rs485conf->flags &= ~SER_RS485_RTS_ON_SEND;
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
}
/*
* Disabling termination by default is the safe choice: Else if many
* bus participants enable it, no communication is possible at all.
* Works fine for short cables and users may enable for longer cables.
*/
port->rs485_term_gpio = devm_gpiod_get_optional(dev, "rs485-term",
GPIOD_OUT_LOW);
if (IS_ERR(port->rs485_term_gpio)) {
ret = PTR_ERR(port->rs485_term_gpio);
port->rs485_term_gpio = NULL;
return dev_err_probe(dev, ret, "Cannot get rs485-term-gpios\n");
}
return 0;
}
configuration registration
The lowest chip driver needs to be registered:
1) The callback interface of the serial layer :
int (*rs485_config)(struct uart_port *, struct serial_rs485 *rs485);
Complete 485 related initialization
2) The callback interface of the 8250 layer:
void (*rs485_start_tx)(struct uart_8250_port *);
void (*rs485_stop_tx)(struct uart_8250_port *);
Used to control the transceiver switch of 485
initialization
uart_set_rs485_config--"driver rs485_config callback
serial8250_em485_config-, in addition to the initialization of basic structure members, there are two processing functions of high-precision timers, which are used to handle switching after delay.
static int serial8250_em485_init(struct uart_8250_port *p)
{
if (p->em485)
return 0;
p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC);
if (!p->em485)
return -ENOMEM;
hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
p->em485->stop_tx_timer.function = &serial8250_em485_handle_stop_tx;
p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;
p->em485->port = p;
p->em485->active_timer = NULL;
p->em485->tx_stopped = true;
p->rs485_stop_tx(p);
return 0;
}
485 transceiver switching
It is relatively easy to receive by default and switch to send through the interface start_tx_rs485.
When switching back to receiving, due to the existence of sending FIFO, it needs to be processed. Judgment processing is added to the kernel code. The code is as follows:
static inline void __stop_tx(struct uart_8250_port *p)
{
struct uart_8250_em485 *em485 = p->em485;
if (em485) {
unsigned char lsr = serial_in(p, UART_LSR);
/*
* To provide required timeing and allow FIFO transfer,
* __stop_tx_rs485() must be called only when both FIFO and
* shift register are empty. It is for device driver to enable
* interrupt on TEMT.
*/
if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
return;
__stop_tx_rs485(p);
}
__do_stop_tx(p);
}
The LSR register is mainly judged here. If the lsr register is not implemented, the switching of 485 will never be carried outThe author encountered this unsupported situation.
delay_after_send
Since there is no support of lsr, it is necessary to rely on delay to handle when to switch. The kernel code already supports, that is delay_after_send, the unit is ms.
For example, send 640 bytes and send fifo size is 64, then we can set this delay as
10bit*1000ms*len/baud
=10*1000*64/115200= 5.56~~6ms
Actual test: trigger when the sending FIFO is configured to be empty, and send 64 pieces each time, then configure a delay of 7ms
If 650 bytes are sent, 10 bytes are sent for the last time,
10*1000*10/115200=0~1ms, then the delay configuration is 2ms
__stop_tx is called by the user after the user buffer data has been sent .
It can be seen that the delay is strongly related to the FIFO size and trigger threshold of the chip.