2022-03-29 14:23:57

by David Laight

[permalink] [raw]
Subject: RE: [PATCH] serial: Revert RS485 polarity change on UART open

From: Matthias Schiffer
> Sent: 29 March 2022 11:39
...
> I guess that would work. The fact that even the different
> variants of the 8250 are implemented inconsistently makes this
> especially ugly... It certainly puts a damper on the efforts to make
> the handling of RS485 in serial drivers more generic.

One thing to remember is that RS232 (IIRC really V.38) line driver
chips are typically inverting.

So the modem signals on a TTL level output will have the
opposite polarity to that required on the actual connector.

Normally a UART will have an 'active high' register bit for
a modem signal that drives and 'active low' pin so you get
the correct polarity with an inverting line driver.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


2022-03-30 11:10:06

by Matthias Schiffer

[permalink] [raw]
Subject: RE: [PATCH] serial: Revert RS485 polarity change on UART open

On Tue, 2022-03-29 at 12:55 +0000, David Laight wrote:
> From: Matthias Schiffer
> > Sent: 29 March 2022 11:39
> ...
> > I guess that would work. The fact that even the different
> > variants of the 8250 are implemented inconsistently makes this
> > especially ugly... It certainly puts a damper on the efforts to
> > make
> > the handling of RS485 in serial drivers more generic.
>
> One thing to remember is that RS232 (IIRC really V.38) line driver
> chips are typically inverting.
>
> So the modem signals on a TTL level output will have the
> opposite polarity to that required on the actual connector.
>
> Normally a UART will have an 'active high' register bit for
> a modem signal that drives and 'active low' pin so you get
> the correct polarity with an inverting line driver.
>
> David
>

Indeed. As far as I can tell, this property of UARTs is what got us
into this mess: Some people interpreted SER_RS485_RTS_ON_SEND as "set
the RTS flag in the MCR register on send", while other thought it
should mean "set the RTS pin to high on send", leading to opposite
behaviours in different UART drivers (and even different UART variants
in the same driver, in the case of the 8250 family).

Regards,
Matthias

2022-03-30 12:10:09

by David Laight

[permalink] [raw]
Subject: RE: [PATCH] serial: Revert RS485 polarity change on UART open

From: Matthias Schiffer
> Sent: 29 March 2022 14:03
>
> On Tue, 2022-03-29 at 12:55 +0000, David Laight wrote:
> > From: Matthias Schiffer
> > > Sent: 29 March 2022 11:39
> > ...
> > > I guess that would work. The fact that even the different
> > > variants of the 8250 are implemented inconsistently makes this
> > > especially ugly... It certainly puts a damper on the efforts to
> > > make
> > > the handling of RS485 in serial drivers more generic.
> >
> > One thing to remember is that RS232 (IIRC really V.38) line driver
> > chips are typically inverting.
> >
> > So the modem signals on a TTL level output will have the
> > opposite polarity to that required on the actual connector.
> >
> > Normally a UART will have an 'active high' register bit for
> > a modem signal that drives and 'active low' pin so you get
> > the correct polarity with an inverting line driver.
> >
> > David
> >
>
> Indeed. As far as I can tell, this property of UARTs is what got us
> into this mess: Some people interpreted SER_RS485_RTS_ON_SEND as "set
> the RTS flag in the MCR register on send", while other thought it
> should mean "set the RTS pin to high on send", leading to opposite
> behaviours in different UART drivers (and even different UART variants
> in the same driver, in the case of the 8250 family).

Hmmm... A complete mess.
The 'RTS pin' that needs to go high is the one on the (typically) 'D'
connector after the inverting line driver.
Not the pin on the uart package.
I'd expect TTL level serial interfaces to require active low
modem signals.

If RS485 is trying to do half duplex using RTS (request to send)
and CTS (clear to send) you've typically got bigger problems
than asserting RTS before a transmit.
The real problem is removing RTS once the last transmit data bit
(the stop bit) has left the UART pin.
I've used local loopback (tx to rx) to detect that in the past.

Of course, if it is just doing flow control that should use RFS
(ready for sending) to indicate space in the receive fifo but
using the RTS pin instead that is a different matter.

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

2022-03-30 18:42:46

by Matthias Schiffer

[permalink] [raw]
Subject: Re: (EXT) RE: [PATCH] serial: Revert RS485 polarity change on UART open

On Tue, 2022-03-29 at 13:19 +0000, David Laight wrote:
> From: Matthias Schiffer
> > Sent: 29 March 2022 14:03
> >
> > On Tue, 2022-03-29 at 12:55 +0000, David Laight wrote:
> > > From: Matthias Schiffer
> > > > Sent: 29 March 2022 11:39
> > > ...
> > > > I guess that would work. The fact that even the different
> > > > variants of the 8250 are implemented inconsistently makes this
> > > > especially ugly... It certainly puts a damper on the efforts to
> > > > make
> > > > the handling of RS485 in serial drivers more generic.
> > >
> > > One thing to remember is that RS232 (IIRC really V.38) line
> > > driver
> > > chips are typically inverting.
> > >
> > > So the modem signals on a TTL level output will have the
> > > opposite polarity to that required on the actual connector.
> > >
> > > Normally a UART will have an 'active high' register bit for
> > > a modem signal that drives and 'active low' pin so you get
> > > the correct polarity with an inverting line driver.
> > >
> > > David
> > >
> >
> > Indeed. As far as I can tell, this property of UARTs is what got us
> > into this mess: Some people interpreted SER_RS485_RTS_ON_SEND as
> > "set
> > the RTS flag in the MCR register on send", while other thought it
> > should mean "set the RTS pin to high on send", leading to opposite
> > behaviours in different UART drivers (and even different UART
> > variants
> > in the same driver, in the case of the 8250 family).
>
> Hmmm... A complete mess.
> The 'RTS pin' that needs to go high is the one on the (typically) 'D'
> connector after the inverting line driver.
> Not the pin on the uart package.
> I'd expect TTL level serial interfaces to require active low
> modem signals.
>
> If RS485 is trying to do half duplex using RTS (request to send)
> and CTS (clear to send) you've typically got bigger problems
> than asserting RTS before a transmit.
> The real problem is removing RTS once the last transmit data bit
> (the stop bit) has left the UART pin.
> I've used local loopback (tx to rx) to detect that in the past.
>
> Of course, if it is just doing flow control that should use RFS
> (ready for sending) to indicate space in the receive fifo but
> using the RTS pin instead that is a different matter.
>
> David
>


I'm aware of the difficulties of deasserting RTS after the transmission
is complete, but that's completely orthogonal to the issue I'm trying
to solve right now :)

Regards,
Matthias

2022-05-11 16:42:54

by Maarten Brock

[permalink] [raw]
Subject: Re: [PATCH] serial: Revert RS485 polarity change on UART open

David Laight wrote on 2022-03-29 15:19:
> From: Matthias Schiffer
>> Sent: 29 March 2022 14:03
>>
>> On Tue, 2022-03-29 at 12:55 +0000, David Laight wrote:
>> > From: Matthias Schiffer
>> > > Sent: 29 March 2022 11:39
>> > ...
>> > > I guess that would work. The fact that even the different
>> > > variants of the 8250 are implemented inconsistently makes this
>> > > especially ugly... It certainly puts a damper on the efforts to
>> > > make the handling of RS485 in serial drivers more generic.
>> >
>> > One thing to remember is that RS232 (IIRC really V.38) line driver
>> > chips are typically inverting.
>> >
>> > So the modem signals on a TTL level output will have the
>> > opposite polarity to that required on the actual connector.
>> >
>> > Normally a UART will have an 'active high' register bit for
>> > a modem signal that drives and 'active low' pin so you get
>> > the correct polarity with an inverting line driver.
>> >
>> > David
>> >
>>
>> Indeed. As far as I can tell, this property of UARTs is what got us
>> into this mess: Some people interpreted SER_RS485_RTS_ON_SEND as "set
>> the RTS flag in the MCR register on send", while other thought it
>> should mean "set the RTS pin to high on send", leading to opposite
>> behaviours in different UART drivers (and even different UART variants
>> in the same driver, in the case of the 8250 family).
>
> Hmmm... A complete mess.
> The 'RTS pin' that needs to go high is the one on the (typically) 'D'
> connector after the inverting line driver.
> Not the pin on the uart package.
> I'd expect TTL level serial interfaces to require active low
> modem signals.

A typical 'D' connector for RS485? I've seen all sorts of connectors
and I can't say one of them is typical. You're assuming there are
RS232 level shifters in play, but usually there aren't and the TTL
UART signals are directly connected to an RS485 transceiver. For
RS485 there is no outside RTS pin, so you will have to talk about
the UART TTL pin.

https://www.kernel.org/doc/Documentation/serial/serial-rs485.txt
is unfortunately not entirely clear:
/* Set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND;

Most (all?) UART chips have an RTSn, RTS# or /RTS pin which means RTS
inverted. So the "RTS pin" can't be set to logic level 1, but RTS can.

IMHO it would be best to let SER_RS485_RTS_ON_SEND mean that RTS is
asserted during sending. That means that RTSn should be 0V.

When the UART chip is connected directly to an RS485 driver with RTSn
connected to DE, you need SER_RS485_RTS_AFTER_SEND so RTS=0 and
RTSn=DE=1 during sending.

When a UART is not in RS485 mode and unopened it usually has RTS=0,
RTSn=1 which would make any directly connected RS485 driver claim
the bus. This is probably undesired behaviour and thus asks for an
extra inverter between RTSn and DE. With this added inverter one
would need SER_RS485_RTS_ON_SEND.

https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/serial/rs485.yaml
isn't much better either:
rs485-rts-active-low:
description: drive RTS low when sending (default is high).

Was this meant as "drive the RTSn pin low when sending"?

Finally, can these two methods be synchronized in their wording?
E.g. can we just drop "rs485-rts-active-low" and replace it with
"rs485-rts-on-send" and "rs485-rts-after-send"?

Maarten