Auto RS485 half-duplex control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
 
ÿôèº{.nÇ+?·?®?­?+%?Ëÿ±éݶ¥?wÿº{.nÇ+?·¥?{±þÇ«?©ÿ?{ayºÊ?Ú?ë,j­¢f£¢·h??ï?êÿ?êçz_è®(­é???Ý¢j"?ú¶m§ÿÿ¾«þG«?éÿ¢¸??¨è­Ú&£ø§~?á


[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux