linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Christian Magnusson" <mag@mag.cx>
To: linux-serial@vger.kernel.org
Subject: Auto RS485 half-duplex control
Date: Sun, 3 Jan 2010 14:15:37 +0100	[thread overview]
Message-ID: <001801ca8c76$d7654bd0$862fe370$@cx> (raw)


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
 

             reply	other threads:[~2010-01-03 13:15 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-03 13:15 Christian Magnusson [this message]
2010-01-24 16:06 ` Auto RS485 half-duplex control Matthias Fuchs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='001801ca8c76$d7654bd0$862fe370$@cx' \
    --to=mag@mag.cx \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).