linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Auto RS485 half-duplex control
@ 2010-01-03 13:15 Christian Magnusson
  2010-01-24 16:06 ` Matthias Fuchs
  0 siblings, 1 reply; 2+ messages in thread
From: Christian Magnusson @ 2010-01-03 13:15 UTC (permalink / raw)
  To: linux-serial


I have searched in the lists for some kernel support to control the RTS-pin
while sending characters to through an external RS232->RS485 adapter.
The RS485 device I’m writing to, respond with an answer within approximately
2ms after my last sent character, and therefore I need to release the
RTS-pin before that.
If not, the returning characters will be unreadable due to the
send-collision.

Will this feature be implemented in the i386 arch (as it is for chris), or
is there any reason to never include it in the future?

/Christian



Right now I have implemented the feature in my application with pretty good
result, but I don’t like the busy-while loop I need to do.
This is a part from my code where I write to the serial-device

        COM_set_RTS(in->file_descriptor, 1); // Tell RS485 converter to
activate TX-pin
        i = COM_write(tmp, size, in);
#ifdef HAVE_TIOCSERGETLSR
        // 79 bytes takes 180.88ms to send  (2.2896ms / char at 4800 baud)
        // (2.289*4800 = 10990)
        if(i == 0) {
            signed int lsr;
            int loops = 0;
            int pre_sleep = ((size*10990)/COM_BaudRate(in->baud)) - 1;
            if(pre_sleep > 3) {
                // Sleep most of the time before the busy-while loop.
                LEVEL_DEFAULT("Pre-sleep %d ms (%d baud)\n", pre_sleep,
COM_BaudRate(in->baud));
                UT_delay(pre_sleep);
            }
            gettimeofday(&tv2, NULL);
            do {
                /* Busy while loop until transmit buffer is empty */
                loops++;
                rc = ioctl(in->file_descriptor, TIOCSERGETLSR, &lsr);
                if(rc < 0) {
                    LEVEL_CALL("TIOCSERGETLSR failed\n");
                    break;
                }
                if(lsr & TIOCSER_TEMT) {
                    /* Transmitter empty */
                    break;
                }
                gettimeofday(&tv2, NULL);
                timersub(&tv2, &tv_start, &diff);
                if(diff.tv_sec != 0) {
                    LEVEL_DEFAULT("TEMT never set within 1 sec\n");
                    break;
                }
            } while(1);

            // tcdrain should return at once after all chars have been sent
            if((rc = tcdrain(in->file_descriptor)) < 0) {
                LEVEL_DEFAULT("drain failed rc=%d\n", rc);
            }
            gettimeofday(&tv_end, NULL);
            timersub(&tv_end, &tv_start, &diff);
            LEVEL_CALL("%d chars sent after %d.%06ld secs (%d loops +
tcdrain)\n", size, diff.tv_sec, diff.tv_usec, loops);
            // 27.5ms - 27.7ms for 12 chars.
            // Waiting for TIOCSER_TEMT is reliable & tcdrain return at once
            // Consumes some CPU-time in the busy-while loop though.
        }
#else
        if(i == 0) {
            // If all bytes were written, then wait until all bytes are sent
            // Seem to wait about 3ms after last char is sent, and that's
too long delay
            if((rc = tcdrain(in->file_descriptor)) < 0) {
                LEVEL_DEFAULT("drain failed rc=%d\n", rc);
            }
        }

        gettimeofday(&tv2, NULL);
        timersub(&tv2, &tv_start, &diff);
        // 28.6-32.8ms for 12 chars  (tcdrain is not very reliable)
        LEVEL_CALL("%d chars sent after %d.%06ld secs (called tcdrain)\n",
size, diff.tv_sec, diff.tv_usec);

#endif

        // Tell RS485 converter to deactivate TX-pin
        COM_set_RTS(in->file_descriptor, 0);
    }



 

__________ Information from ESET NOD32 Antivirus, version of virus signature
database 4738 (20100102) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com
 

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Auto RS485 half-duplex control
  2010-01-03 13:15 Auto RS485 half-duplex control Christian Magnusson
@ 2010-01-24 16:06 ` Matthias Fuchs
  0 siblings, 0 replies; 2+ messages in thread
From: Matthias Fuchs @ 2010-01-24 16:06 UTC (permalink / raw)
  To: Christian Magnusson; +Cc: linux-serial

Christian,

> 
> I have searched in the lists for some kernel support to control the RTS-pin
> while sending characters to through an external RS232->RS485 adapter.
> The RS485 device I’m writing to, respond with an answer within approximately
> 2ms after my last sent character, and therefore I need to release the
> RTS-pin before that.
> If not, the returning characters will be unreadable due to the
> send-collision.
> 
> Will this feature be implemented in the i386 arch (as it is for chris), or
> is there any reason to never include it in the future?
> 
manually controlling the RTS (or any other pin) pin for RS485 duplex
control has been discussed here several time. Because it is not possible
to guarantee the correct timing in any situation this was always nack'd.

The only chance you have is to use a proper UART that is capable to do this
by hardware (e.g. some Exar UARTs or some UARTs that can be found on some
SoCs that are used in the embedded world).

Matthias
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-01-24 16:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-03 13:15 Auto RS485 half-duplex control Christian Magnusson
2010-01-24 16:06 ` Matthias Fuchs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).