* 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 Im 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 dont 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 Im 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).