RTS/CTS handshaking for embedded devices

From: Oleksiy Kebkal
Date: Fri Mar 02 2007 - 15:06:32 EST


Hi,

I use arm-linux platform to program some peripheral where pecular
serial flow control is required:

- There is no flow control for the arm-linux device -> control unit
- For the control unix -> arm-linux device
* RTS must be kept low, the device keeps CTS low as well.
* when the device wants to send data, it raises CTS. RTS must
be raised as well. Data can then pass, CTS and RTS are lowered.

Actually it's pretty simillar to the problem, described here:
http://groups.google.de/group/linux.kernel/browse_thread/thread/b5a059bfba931188/1d8cfeef17431180?lnk=gst&q=crtscts&rnum=5&hl=ru#1d8cfeef17431180
and I suppose, here:
http://groups.google.de/group/linux.kernel/browse_thread/thread/9479f1a2336e6aaa/b2d0cccb7cdb1f2a?lnk=gst&q=crtscts&rnum=2&hl=ru#b2d0cccb7cdb1f2a

It looked for me obvios that the solution is to switch off the flow
control (CRTSCTS) and to assert/deassert RTS via
ioctl. But I have found, that:
* even if flow control is switched off, serial_core.c asserts RTS
during opening the serial device.
* there is no possibility (at least I didn't find it) to preconfigure
serial interface in the user space before opening
serial device (looks logically), but there is a time gap between
opening the serial device and configuring it, there
control device "thinks" that arm is ready to get data (RTS is
asserted), but the configuration parameters are
potentially wrong.

So the first question is, is there any provided by kernel way to solve
the described above task?

If not, maybe it would be more correct just to don't touch RTS, if
flow control is switched off, like here:

Index: drivers/serial/serial_core.c
===================================================================
--- a/drivers/serial/serial_core.c (mode:100644)
+++ b/drivers/serial/serial_core.c (mode:100644)
@@ -212,7 +212,7 @@
* is open and ready to respond.
*/
if (info->tty->termios->c_cflag & CBAUD)
- info->mctrl |= TIOCM_RTS | TIOCM_DTR;
+ info->mctrl |= TIOCM_DTR | (info->flags &
ASYNC_CTS_FLOW ? 0 : TIOCM_RTS );
info->ops->set_mctrl(info->port, info->mctrl);

info->flags |= ASYNC_INITIALIZED;
@@ -1001,8 +1001,8 @@
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
info->mctrl |= TIOCM_DTR;
- if (!(cflag & CRTSCTS) ||
- !test_bit(TTY_THROTTLED, &tty->flags))
+ if (/*!(cflag & CRTSCTS) ||*/
+ !test_bit(TTY_THROTTLED, &tty->flags))
info->mctrl |= TIOCM_RTS;
info->ops->set_mctrl(info->port, info->mctrl);
}
@@ -1301,7 +1301,7 @@
spin_lock_irqsave(&info->lock, flags);
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
(tty->termios->c_cflag & CBAUD)) {
- info->mctrl |= TIOCM_DTR | TIOCM_RTS;
+ info->mctrl |= TIOCM_DTR | (info->flags &
ASYNC_CTS_FLOW ? 0 : TIOCM_RTS );
info->ops->set_mctrl(info->port, info->mctrl);
}
spin_unlock_irqrestore(&info->lock, flags);

---
Oleksiy
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/