Poor documentation of SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

I have some trouble finding out the meaning of SER_RS485_RTS_ON_SEND and
SER_RS485_RTS_AFTER_SEND. The documentation says:

linux/serial.h
==============
* * %SER_RS485_RTS_ON_SEND	- Logical level for RTS pin when sending.
* * %SER_RS485_RTS_AFTER_SEND	- Logical level for RTS pin after sent.

Practically all UART chips have a -RTS, /RTS pin or RTSn pin and no RTS pin. And what is the meaning of "Logical level" here? Is it the same as Logic Level?

Should I conclude that setting the SER_RS485_RTS_ON_SEND flag should result in
the logic level on the /RTS pin being high (> 0V) during transmission?
And similarly that setting the SER_RS485_RTS_AFTER_SEND flag should result in
the logic level on the /RTS pin being high after transmission?

rs485.yaml
==========
  rs485-rts-active-high:
    description: drive RTS high when sending (this is the default).
    $ref: /schemas/types.yaml#/definitions/flag

  rs485-rts-active-low:
    description: drive RTS low when sending (default is high).
    $ref: /schemas/types.yaml#/definitions/flag

Can I assume that RTS usually means the /RTS pin on the UART chip here.

Looking at the implemented drivers does not make things better.

Some drivers think that when the SER_RS485_RTS_ON_SEND flag is set they should set the RTS bit in E.g. the MCR register when starting a transmission, which
results in the /RTS pin going low on E.g. a genuine 8250.

8250_port.c
===========
/**
 * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback
 * @up: uart 8250 port
 *
* Generic callback usable by 8250 uart drivers to start rs485 transmission. * Assumes that setting the RTS bit in the MCR register means RTS is high.

Wow, that's an odd assumption for a generic 8250/16x50 driver!

 * (Some chips use inverse semantics.)  [...]
 */
void serial8250_em485_start_tx(struct uart_8250_port *up)
{
	unsigned char mcr = serial8250_in_MCR(up);

	if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
		serial8250_stop_rx(&up->port);

	if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
		mcr |= UART_MCR_RTS;
	else
		mcr &= ~UART_MCR_RTS;
	serial8250_out_MCR(up, mcr);
}

The next one behaves the same, but makes a different assumption:

8250_omap.c
===========
static int omap8250_rs485_config(struct uart_port *port,
				 struct ktermios *termios,
				 struct serial_rs485 *rs485)
{
	[...]
	/*
	 * Retain same polarity semantics as RS485 software emulation,
	 * i.e. SER_RS485_RTS_ON_SEND means driving RTS low on send.

Shouldn't SER_RS485_RTS_ON_SEND mean driving RTS high on send?

	 */
	if (rs485->flags & SER_RS485_RTS_ON_SEND)
		priv->mdr3 &= ~UART_OMAP_MDR3_DIR_POL;
	else
		priv->mdr3 |= UART_OMAP_MDR3_DIR_POL;

	serial_out(up, UART_OMAP_MDR3, priv->mdr3);

Others believe that they should clear the RTS bit in MCR for
SER_RS485_RTS_ON_SEND when starting a transmission, resulting in the /RTS
pin going high.

8250_bcm2835aux.c
=================
static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up)
{
	[...]
	/*
	 * On the bcm2835aux, the MCR register contains no other
	 * flags besides RTS.  So no need for a read-modify-write.
	 */
	if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND)
		serial8250_out_MCR(up, 0);
	else
		serial8250_out_MCR(up, UART_MCR_RTS);
}

Same here:

8250_pci.c
==========
static int pci_fintek_rs485_config(struct uart_port *port, struct ktermios *termios,
			       struct serial_rs485 *rs485)
{
		[...]
		if (rs485->flags & SER_RS485_RTS_ON_SEND) {
			/* RTS driving high on TX */
			setting &= ~FINTEK_RTS_INVERT;
		} else {
			/* RTS driving low on TX */
			setting |= FINTEK_RTS_INVERT;
		}

Can the list shed some light on this and reach a consensus here?

Happy Holidays,
Maarten





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux