2008-06-26 20:56:42

by Sergey Lapin

[permalink] [raw]
Subject: Half-duplex rs-485 on full-duplex UART.

Hi, all!

I have a device with normal serial ports (at91sam9260-based) and
RS-485 half-duplex transceiver
installed for it and 1 GPIO for duplex control, 1=writing, 0=reading.
A problem is that I need to hack serial driver to support this GPIO
control, which I don't like.
I just need to set it to 1 before transmission and back to 0 when
transmission ends.

Most important thing is to set this bit to 1 before transfer starts,
so I can't just poll UART registers
from tasklet. So I had to hack into serial driver for that.

So questions are:

1. Is there some generic enough mechanism in kernel to handle such
tasks? so I mean external
serial transcievers support?

2. Is there any way to implement this task without touching, in my
case, drivers/serial/atmel_serial.c?

Thanks a lot,
S.


2008-06-27 13:49:16

by Lennart Sorensen

[permalink] [raw]
Subject: Re: Half-duplex rs-485 on full-duplex UART.

On Fri, Jun 27, 2008 at 12:56:26AM +0400, Sergey Lapin wrote:
> I have a device with normal serial ports (at91sam9260-based) and
> RS-485 half-duplex transceiver
> installed for it and 1 GPIO for duplex control, 1=writing, 0=reading.
> A problem is that I need to hack serial driver to support this GPIO
> control, which I don't like.
> I just need to set it to 1 before transmission and back to 0 when
> transmission ends.
>
> Most important thing is to set this bit to 1 before transfer starts,
> so I can't just poll UART registers
> from tasklet. So I had to hack into serial driver for that.
>
> So questions are:
>
> 1. Is there some generic enough mechanism in kernel to handle such
> tasks? so I mean external
> serial transcievers support?
>
> 2. Is there any way to implement this task without touching, in my
> case, drivers/serial/atmel_serial.c?

There are a few serial ports in linux that have RS485 support.
crisv10.c for example appears to support RS485.

The way that seems most common (as far as I know) is that drive the
transmit/receive direction using the RTS line, which if the serial port
has one would already support software control. The user application
would then set RTS, transmit the data, wait for the transmit buffer to
empty, and then when it is empty, toggle the RTS off again, and then
wait for the reply.

The simpler method if you have access to a good UART (like many of the
exars) is to simply let the hardware manage it. You can enable
autors485 mode in which whenever there is data to transmit, RTS is
asserted, and a few clock cycles after the transmit FIFO empties, the
RTS is deasserted and receive can happen. In this case the user space
doesn't even need to have a clue about RS485, although in most cases the
application already needed to know about RS485 so it may not be that
much of a gain, but it sure makes it more efficient to not have to wait
for the UART to drain the transmit FIFO.

I think having the user application control the send/receive switch
makes more sense than the driver, but perhaps it doesn't in your case.

--
Len Sorensen