* Suggested patch for linux
@ 2008-07-09 23:16 Axel Hosemann
[not found] ` <487546D5.8050908-3sKltW3hOZofv37vnLkPlQ@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Axel Hosemann @ 2008-07-09 23:16 UTC (permalink / raw)
To: linux-serial; +Cc: linux-usb
[-- Attachment #1: Type: text/plain, Size: 1465 bytes --]
Dear Sirs,
the support of the serial interface by linux systems nowadays suffers
from the disadvantage, that hardware handshake is only supported for the
full duplex mode. That means, that the RTS signal is getting always
asserted immediately after the serial was opened. So the RTS signal
under linux, as far as I understood it, carries exactly the same
information as the DTR line. That means, that there is no half-duplex
behaviour provided by linux. A half-duplex application as e.g. RS-485
controllers or radio modems are depending on a different behaviour: The
serial port asserts DTR after it was opened, but RTS must only be
asserted, when data has been written to the tx buffer for transmission.
Stimulated by the RTS signal, the DCE will then engage the channel for
transmission and release it, after the RTS has been deasserted when the
buffer had been sent. This behaviour is up to now not supported by the
linux serial drivers.
Therefore I make a suggestion for adding the half-duplex support for
linux kernels by the attached patch, which I created and tested on a
UART 16550 compliant hardware and additionally by means of a ftdi usb
to serial port adaptor. The patch was compiled and tested with an
UBUNTU 2.6.24-19-generic environment.
If you see a chance, to add this functionality for future linux kernels,
I would be interested in further discussions about this patch.
Regards
Axel Hosemann
Bergstrasse 6f
CH 5644 Auw
[-- Attachment #2: serialHalfDuplex.patch --]
[-- Type: text/x-patch, Size: 11594 bytes --]
diff -urN linux-2.6.24/drivers/serial/serial_core.c linux-2.6.24-new/drivers/serial/serial_core.c
--- linux-2.6.24/drivers/serial/serial_core.c 2008-02-11 06:51:11.000000000 +0100
+++ linux-2.6.24-new/drivers/serial/serial_core.c 2008-07-07 22:36:16.000000000 +0200
@@ -75,6 +75,9 @@
*/
BUG_ON(!info);
tasklet_schedule(&info->tlet);
+#ifdef RTSHDX
+ wake_up_interruptible(&port->rts_wait);
+#endif
}
static void uart_stop(struct tty_struct *tty)
@@ -181,8 +184,15 @@
* Setup the RTS and DTR signals once the
* port is open and ready to respond.
*/
- if (info->tty->termios->c_cflag & CBAUD)
+ if (info->tty->termios->c_cflag & CBAUD){
+#ifdef RTSHDX
+ port->toggleRTS = false;
+ uart_set_mctrl(port, TIOCM_DTR);
+ uart_clear_mctrl(port, TIOCM_RTS);
+#else
uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
+#endif
+ }
}
if (info->flags & UIF_CTS_FLOW) {
@@ -473,6 +483,47 @@
uart_start(tty);
}
+#ifdef RTSHDX
+static void uart_wait_infinite_until_sent(struct tty_struct *tty)
+{
+ struct uart_state *state = tty->driver_data;
+ struct uart_port *port = state->port;
+ unsigned long char_time;
+
+ BUG_ON(!kernel_locked());
+
+ char_time = (port->timeout - HZ/50) / port->fifosize;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+
+ if (port->type == PORT_UNKNOWN || port->fifosize == 0)
+ return;
+
+ /*
+ * Check whether the transmitter is empty every 'char_time'.
+ */
+ while (!port->ops->tx_empty(port)) {
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ }
+ //wait again until shift register is empty
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ set_current_state(TASK_RUNNING); /* might not be needed */
+}
+
+static void simplified_sleep_on(wait_queue_head_t *queue)
+{
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
+ current->state = TASK_INTERRUPTIBLE;
+
+ add_wait_queue(queue, &wait);
+ schedule();
+ remove_wait_queue (queue, &wait);
+}
+#endif
+
static int
uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
@@ -497,6 +548,9 @@
if (!circ->buf)
return 0;
+#ifdef RTSHDX
+ uart_set_mctrl(port, TIOCM_RTS);
+#endif
spin_lock_irqsave(&port->lock, flags);
while (1) {
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
@@ -513,6 +567,16 @@
spin_unlock_irqrestore(&port->lock, flags);
uart_start(tty);
+#ifdef RTSHDX
+ if(port->toggleRTS){
+ //first wait until the device indicates transmission started
+ simplified_sleep_on(&port->rts_wait);
+ //second wait until the device indicates transmission done
+ uart_wait_infinite_until_sent(tty);
+ //now we are ready to deassert RTS
+ uart_clear_mctrl(port, TIOCM_RTS);
+ }
+#endif
return ret;
}
@@ -1143,6 +1207,15 @@
unsigned int cflag = tty->termios->c_cflag;
BUG_ON(!kernel_locked());
+#ifdef RTSHDX
+ state->port->toggleRTS = tty->termios->c_lflag & RTSHDX ? true : false;
+ if(state->port->toggleRTS){
+ uart_clear_mctrl(state->port, TIOCM_RTS);
+ }
+ else {
+ uart_set_mctrl(state->port, TIOCM_RTS);
+ }
+#endif
/*
* These are the bits that are used to setup various
@@ -1167,8 +1240,14 @@
if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
unsigned int mask = TIOCM_DTR;
if (!(cflag & CRTSCTS) ||
- !test_bit(TTY_THROTTLED, &tty->flags))
+ !test_bit(TTY_THROTTLED, &tty->flags)){
+#ifdef RTSHDX
+ if(!state->port->toggleRTS)
+ mask |= TIOCM_RTS;
+#else
mask |= TIOCM_RTS;
+#endif
+ }
uart_set_mctrl(state->port, mask);
}
@@ -1413,8 +1492,15 @@
/*
* And finally enable the RTS and DTR signals.
*/
- if (tty->termios->c_cflag & CBAUD)
+ if (tty->termios->c_cflag & CBAUD){
+#ifdef RTSHDX
+ //uart_update_mctrl(port,TIOCM_DTR,TIOCM_RTS);
+ uart_clear_mctrl(port, TIOCM_RTS);
+ uart_set_mctrl(port, TIOCM_DTR);
+#else
uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+#endif
+ }
}
}
@@ -1527,6 +1613,9 @@
if (state->info) {
init_waitqueue_head(&state->info->open_wait);
init_waitqueue_head(&state->info->delta_msr_wait);
+#ifdef RTSHDX
+ init_waitqueue_head(&state->port->rts_wait);
+#endif
/*
* Link the info into the other structures.
diff -urN linux-2.6.24/drivers/usb/serial/ftdi_sio.c linux-2.6.24-new/drivers/usb/serial/ftdi_sio.c
--- linux-2.6.24/drivers/usb/serial/ftdi_sio.c 2008-02-11 06:51:11.000000000 +0100
+++ linux-2.6.24-new/drivers/usb/serial/ftdi_sio.c 2008-07-07 22:40:30.000000000 +0200
@@ -301,6 +301,12 @@
unsigned long tx_bytes;
unsigned long tx_outstanding_bytes;
unsigned long tx_outstanding_urbs;
+#ifdef RTSHDX
+ unsigned char charLen;
+ bool toggleRTS;
+ char extended_status;
+ wait_queue_head_t rts_wait; // Used for blocking write
+#endif
};
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
@@ -722,6 +728,20 @@
return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
}
+#ifdef RTSHDX
+static void simplified_sleep_on(wait_queue_head_t *queue)
+{
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
+ current->state = TASK_INTERRUPTIBLE;
+
+ add_wait_queue(queue, &wait);
+ schedule();
+ remove_wait_queue (queue, &wait);
+}
+#endif
+
#define set_mctrl(port, set) update_mctrl((port), (set), 0)
#define clear_mctrl(port, clear) update_mctrl((port), 0, (clear))
@@ -1221,6 +1241,9 @@
spin_lock_init(&priv->rx_lock);
spin_lock_init(&priv->tx_lock);
init_waitqueue_head(&priv->delta_msr_wait);
+#ifdef RTSHDX
+ init_waitqueue_head(&priv->rts_wait);
+#endif
/* This will push the characters through immediately rather
than queue a task to deliver them */
priv->flags = ASYNC_LOW_LATENCY;
@@ -1372,8 +1395,13 @@
/* FIXME: Flow control might be enabled, so it should be checked -
we have no control of defaults! */
/* Turn on RTS and DTR since we are not flow controlling by default */
+#ifdef RTSHDX
+ priv->toggleRTS = false;
+ set_mctrl(port, TIOCM_DTR);
+ clear_mctrl(port, TIOCM_RTS);
+#else
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-
+#endif
/* Not throttled */
spin_lock_irqsave(&priv->rx_lock, flags);
priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
@@ -1453,7 +1481,9 @@
int status;
int transfer_size;
unsigned long flags;
-
+#ifdef RTSHDX
+ int baud;
+#endif
dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
if (count == 0) {
@@ -1529,6 +1559,9 @@
usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
buffer, transfer_size,
ftdi_write_bulk_callback, port);
+#ifdef RTSHDX
+ set_mctrl(port, TIOCM_RTS);
+#endif
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
@@ -1545,10 +1578,25 @@
/* we are done with this urb, so let the host driver
* really free it when it is finished with it */
usb_free_urb(urb);
+#ifdef RTSHDX
+ if(priv->toggleRTS){
+ priv->extended_status &= (~FTDI_RS_TEMT);
+ while((priv!=NULL)&&(!(priv->extended_status & FTDI_RS_TEMT))){
+ simplified_sleep_on(&priv->rts_wait);
+ }
+ baud = tty_get_baud_rate(port->tty);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies((2000000 * priv->charLen) / baud));
+ clear_mctrl(port, TIOCM_RTS);
+ }
+#endif
dbg("%s write returning: %d", __FUNCTION__, count);
return count;
error:
+#ifdef RTSHDX
+ clear_mctrl(port, TIOCM_RTS);
+#endif
usb_free_urb(urb);
error_no_urb:
kfree (buffer);
@@ -1769,12 +1817,22 @@
/* N.B. packet may be processed more than once, but differences
* are only processed once. */
if (priv != NULL) {
+#ifdef RTSHDX
+ char new_ext_status;
+#endif
char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
priv->diff_status |= new_status ^ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = new_status;
}
+#ifdef RTSHDX
+ new_ext_status = data[packet_offset+1] & FTDI_RS_TEMT;
+ if ((new_ext_status != (priv->extended_status & FTDI_RS_TEMT)) && (new_ext_status != 0)){
+ priv->extended_status |= new_ext_status;
+ wake_up_interruptible(&priv->rts_wait);
+ }
+#endif
}
length = min(PKTSZ, urb->actual_length-packet_offset)-2;
@@ -1940,6 +1998,9 @@
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct ktermios *termios = port->tty->termios;
unsigned int cflag = termios->c_cflag;
+#ifdef RTSHDX
+ unsigned int lflag = termios->c_lflag;
+#endif
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
@@ -1974,25 +2035,67 @@
/* Set number of data bits, parity, stop bits */
+#ifdef RTSHDX
+ priv->charLen = 1;
+#endif
termios->c_cflag &= ~CMSPAR;
urb_value = 0;
urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
FTDI_SIO_SET_DATA_STOP_BITS_1);
+#ifdef RTSHDX
+ priv->charLen += cflag & CSTOPB ? 2 : 1;
+#endif
urb_value |= (cflag & PARENB ?
(cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD :
FTDI_SIO_SET_DATA_PARITY_EVEN) :
FTDI_SIO_SET_DATA_PARITY_NONE);
- if (cflag & CSIZE) {
- switch (cflag & CSIZE) {
- case CS5: urb_value |= 5; dbg("Setting CS5"); break;
- case CS6: urb_value |= 6; dbg("Setting CS6"); break;
- case CS7: urb_value |= 7; dbg("Setting CS7"); break;
- case CS8: urb_value |= 8; dbg("Setting CS8"); break;
+#ifdef RTSHDX
+ priv->charLen += cflag & PARENB ? 1 : 0;
+#endif
+ if (cflag & CSIZE){
+ switch (cflag & CSIZE){
+ case CS5:
+#ifdef RTSHDX
+ priv->charLen += 5;
+#endif
+ urb_value |= 5;
+ dbg("Setting CS5");
+ break;
+ case CS6:
+#ifdef RTSHDX
+ priv->charLen += 6;
+#endif
+ urb_value |= 6;
+ dbg("Setting CS6");
+ break;
+ case CS7:
+#ifdef RTSHDX
+ priv->charLen += 7;
+#endif
+ urb_value |= 7;
+ dbg("Setting CS7");
+ break;
+ case CS8:
+#ifdef RTSHDX
+ priv->charLen += 8;
+#endif
+ urb_value |= 8;
+ dbg("Setting CS8");
+ break;
default:
err("CSIZE was set but not CS5-CS8");
}
}
+#ifdef RTSHDX
+ if(lflag & RTSHDX){
+ priv->toggleRTS = true;
+ }
+ else{
+ priv->toggleRTS = false;
+ set_mctrl(port, TIOCM_RTS);
+ }
+#endif
/* This is needed by the break command since it uses the same command - but is
* or'ed with this value */
@@ -2025,7 +2128,17 @@
}
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
+#ifdef RTSHDX
+ set_mctrl(port, TIOCM_DTR);
+ if(priv->toggleRTS){
+ clear_mctrl(port, TIOCM_RTS);
+ }
+ else{
+ set_mctrl(port, TIOCM_RTS);
+ }
+#else
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+#endif
}
}
diff -urN linux-2.6.24/include/asm-x86/termbits.h linux-2.6.24-new/include/asm-x86/termbits.h
--- linux-2.6.24/include/asm-x86/termbits.h 2008-02-11 06:51:11.000000000 +0100
+++ linux-2.6.24-new/include/asm-x86/termbits.h 2008-06-15 00:24:00.000000000 +0200
@@ -176,6 +176,7 @@
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
+#define RTSHDX 0020000
#define PENDIN 0040000
#define IEXTEN 0100000
diff -urN linux-2.6.24/include/linux/serial_core.h linux-2.6.24-new/include/linux/serial_core.h
--- linux-2.6.24/include/linux/serial_core.h 2008-02-11 06:51:11.000000000 +0100
+++ linux-2.6.24-new/include/linux/serial_core.h 2008-06-16 00:28:06.000000000 +0200
@@ -297,6 +297,10 @@
unsigned char suspended;
unsigned char unused[2];
void *private_data; /* generic platform data pointer */
+#ifdef RTSHDX
+ bool toggleRTS;
+ wait_queue_head_t rts_wait; // Used for blocking write
+#endif
};
/*
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
[not found] ` <487546D5.8050908-3sKltW3hOZofv37vnLkPlQ@public.gmane.org>
@ 2008-07-10 8:59 ` Alan Cox
2008-07-10 14:16 ` Matt Schulte
2008-07-10 14:47 ` Grant Edwards
0 siblings, 2 replies; 11+ messages in thread
From: Alan Cox @ 2008-07-10 8:59 UTC (permalink / raw)
To: Axel Hosemann
Cc: linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA
> Stimulated by the RTS signal, the DCE will then engage the channel for
> transmission and release it, after the RTS has been deasserted when the
> buffer had been sent. This behaviour is up to now not supported by the
> linux serial drivers.
Actually you can drive this behaviour from user space which is what
software like scarabd has done for many years.
> If you see a chance, to add this functionality for future linux kernels,
> I would be interested in further discussions about this patch.
The big problem is that the kernel does not know what is a "transmission"
it just sees a series of writes to the device. In many cases the
multi-drop or radio systems also need the caller to wait for a
transmission slot either by beacon, by timing or by monitoring the
carrier detect to avoid collisions.
That seems to best be done in user space as the algorithms are quite
variable and some are complex.
Do we really benefit from having this in kernel ?
Alan
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-10 8:59 ` Alan Cox
@ 2008-07-10 14:16 ` Matt Schulte
2008-07-12 21:49 ` Axel Hosemann
` (2 more replies)
2008-07-10 14:47 ` Grant Edwards
1 sibling, 3 replies; 11+ messages in thread
From: Matt Schulte @ 2008-07-10 14:16 UTC (permalink / raw)
To: Alan Cox; +Cc: Axel Hosemann, linux-serial, linux-usb
> The big problem is that the kernel does not know what is a "transmission"
> it just sees a series of writes to the device. In many cases the
> multi-drop or radio systems also need the caller to wait for a
> transmission slot either by beacon, by timing or by monitoring the
> carrier detect to avoid collisions.
I believe that he is referring to something much simpler than you are
thinking. He is talking about 2-wire RS485 transmissions in which the
RTS signal is used to enable the driver chips just before transmitting
data and disabling (tri-stating) them just after transmitting data.
There are some UARTs that have this behavior built into them.
>
> That seems to best be done in user space as the algorithms are quite
> variable and some are complex.
>
> Do we really benefit from having this in kernel ?
The problem that can come up when executing this feature in user-land
(though not exactly common) is when the hardware on the other end
responds to your message faster than your user app was able to detect
that the UART is finished and then toggle RTS. When this happens both
ends are trying to drive the line and you have bus contention, lost data
and possibly damage to the driver chips themselves.
Matt Schulte
Commtech, Inc.
http://www.commtech-fastcom.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-10 8:59 ` Alan Cox
2008-07-10 14:16 ` Matt Schulte
@ 2008-07-10 14:47 ` Grant Edwards
2008-08-04 13:28 ` Tosoni
1 sibling, 1 reply; 11+ messages in thread
From: Grant Edwards @ 2008-07-10 14:47 UTC (permalink / raw)
To: linux-serial; +Cc: linux-usb
On 2008-07-10, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> Stimulated by the RTS signal, the DCE will then engage the
>> channel for transmission and release it, after the RTS has
>> been deasserted when the buffer had been sent. This behaviour
>> is up to now not supported by the linux serial drivers.
>
> Actually you can drive this behaviour from user space
That doesn't generally work. You often can't respond quickly
enough in user space. You need to turn the line around within
as little as a few bit-times. At high baud rates, you simply
can't do that from user space (especially when the UART is
attached via something like USB or Ethernet).
> which is what software like scarabd has done for many years.
>
>> If you see a chance, to add this functionality for future
>> linux kernels, I would be interested in further discussions
>> about this patch.
>
> The big problem is that the kernel does not know what is a
> "transmission" it just sees a series of writes to the device.
"Transmission" is when the UART is sending data (when the shift
register is not empty).
> In many cases the multi-drop or radio systems also need the
> caller to wait for a transmission slot either by beacon, by
> timing or by monitoring the carrier detect to avoid
> collisions.
That's obviously beyond the scope of the serial driver.
Controlling RTS in half-duplex mode isn't.
> That seems to best be done in user space as the algorithms are
> quite variable and some are complex.
>
> Do we really benefit from having this in kernel ?
People who do industrial communications sure would. I maintain
a couple serial drivers that support half-duplex mode exactly
as described by the OP, and we have to control that feature via
non-standard hacks.
In the past, I added half-duplex mode support into the standard
Linux 16x50 driver, but could never get it to work reliably
across various chipsets (PC motherboard UART designs don't all
seem to set the shift register empty bit at the same time).
If there was at least a standard way to enable half-duplex
mode, it would be easier to support on hardware that correctly
implements RTS control for half-duplex operation.
--
Grant Edwards grante Yow! Here we are in America
at ... when do we collect
visi.com unemployment?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-10 14:16 ` Matt Schulte
@ 2008-07-12 21:49 ` Axel Hosemann
2008-07-12 22:33 ` Alan Cox
2008-07-18 10:19 ` Laurent Pinchart
2 siblings, 0 replies; 11+ messages in thread
From: Axel Hosemann @ 2008-07-12 21:49 UTC (permalink / raw)
To: Matt Schulte; +Cc: linux-usb, linux-serial
Dear Matt,
first of all, I must apologise for not being familiar with the mailing
rules of your organisation. I already received a mail by a female
developer, who was annoyed by me addressing her as "Dear Sirs". Oops!
I'm sorry.
From your reply I see, that you understood the reason for the suggested
patch: I try to port a half duplex application from Windows to Linux,
which on one hand controls a radio modem by means of a 2 wire RS-485
bus, and on the other hand exchanges payload data over the half duplex
radio channel across an asynchronous port. There is no chance for me
doing that without this patch, because Linux does not support a feature
similar to the Windows "RTS_CONTROL_TOGGLE" option.
To the problem you mentioned. Yes, your right: If the RS-485 slave
device would reply a request with hardware timings within a few
microseconds, a collision would occur. This would certainly not destroy
the RS-485 chips, because they are generally protected against these
collision situations. But theoretically the application would not work,
when the slave would reply faster, than the PC could release the RTS
signal. In practice, I did not face this situation (yet!) Probably
because the receiving slave needs a micro controller itself, checking
the checksum, interpreting the request and preparing the response. But
the problem persists: The OS controlled deassertion of the RTS signal
may be too slow for fast RS-485 slaves. Anyway, up to now, I had no
problems with that issue with the mentioned Windows application. But
when I'm back from my holydays I will do some measurements to compare
the timing between the Windows application and the suggested Linux patch.
For radio modem transmission, there will be no problem at all: Radio
modems will always utilise FEC functionalities, which imply interleaving
and deinterleaving delays. The deinterleaving delay of the receiver is
in the range of hundreds of milliseconds. Even on legacy PC hardware
platforms, the OS should be able to deassert RTS in time.
However, the half duplex feature could extend the Linux functionality. I
read in a few forum threads, that there would be a demand for this
functionality besides my personal interests.
Best Regards
Axel Hosemann
Matt Schulte wrote:
>
>> The big problem is that the kernel does not know what is a
>> "transmission"
>> it just sees a series of writes to the device. In many cases the
>> multi-drop or radio systems also need the caller to wait for a
>> transmission slot either by beacon, by timing or by monitoring the
>> carrier detect to avoid collisions.
> I believe that he is referring to something much simpler than you are
> thinking. He is talking about 2-wire RS485 transmissions in which the
> RTS signal is used to enable the driver chips just before transmitting
> data and disabling (tri-stating) them just after transmitting data.
> There are some UARTs that have this behavior built into them.
>>
>> That seems to best be done in user space as the algorithms are quite
>> variable and some are complex.
>>
>> Do we really benefit from having this in kernel ?
> The problem that can come up when executing this feature in user-land
> (though not exactly common) is when the hardware on the other end
> responds to your message faster than your user app was able to detect
> that the UART is finished and then toggle RTS. When this happens both
> ends are trying to drive the line and you have bus contention, lost
> data and possibly damage to the driver chips themselves.
>
> Matt Schulte
> Commtech, Inc.
> http://www.commtech-fastcom.com
>
>
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-10 14:16 ` Matt Schulte
2008-07-12 21:49 ` Axel Hosemann
@ 2008-07-12 22:33 ` Alan Cox
2008-07-15 20:43 ` Matt Schulte
2008-07-18 10:19 ` Laurent Pinchart
2 siblings, 1 reply; 11+ messages in thread
From: Alan Cox @ 2008-07-12 22:33 UTC (permalink / raw)
To: Matt Schulte; +Cc: Axel Hosemann, linux-serial, linux-usb
On Thu, 10 Jul 2008 09:16:40 -0500
> I believe that he is referring to something much simpler than you are
> thinking. He is talking about 2-wire RS485 transmissions in which the
> RTS signal is used to enable the driver chips just before transmitting
Its all the same thing. And actually the radios are often RS485
> > That seems to best be done in user space as the algorithms are quite
> > variable and some are complex.
> > Do we really benefit from having this in kernel ?
> The problem that can come up when executing this feature in user-land
> (though not exactly common) is when the hardware on the other end
> responds to your message faster than your user app was able to detect
> that the UART is finished and then toggle RTS. When this happens both
> ends are trying to drive the line and you have bus contention, lost data
> and possibly damage to the driver chips themselves.
The chips are quite safe. Can we stick to real reasons.
In terms of performance you can manage RTS with a real time application
if need be and that will give you very close to kernel side response time.
Alan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-12 22:33 ` Alan Cox
@ 2008-07-15 20:43 ` Matt Schulte
[not found] ` <1860bbce0807151343rf5cf4apecdc422ba747dd7d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 11+ messages in thread
From: Matt Schulte @ 2008-07-15 20:43 UTC (permalink / raw)
To: Alan Cox; +Cc: Axel Hosemann, linux-serial, linux-usb
> > > Do we really benefit from having this in kernel ?
> > The problem that can come up when executing this feature in user-land
> > (though not exactly common) is when the hardware on the other end
> > responds to your message faster than your user app was able to detect
> > that the UART is finished and then toggle RTS. When this happens both
> > ends are trying to drive the line and you have bus contention, lost data
> > and possibly damage to the driver chips themselves.
>
> The chips are quite safe. Can we stick to real reasons.
>
> In terms of performance you can manage RTS with a real time application
> if need be and that will give you very close to kernel side response time.
>
> Alan
I apologize if this is a duplicate to anyone, but I've been trying to
get my response through to the board and kept getting rejected, I
think this one will make it through...
The chips may or may not be safe, that isn't the point. There are
real world applications where response time is an issue and meeting
these criteria is sometimes impossible from a user application.
Switching to an RTOS is certainly an option, it would very likely
allow you to manage RTS withing spec. However this might not be very
practical for many users. I suppose another option is to switch to a
serial card that uses a UART that has this capability built in. I
don't want to sound like an advertisement, but several of my line of
Fastcom serial cards have this feature, where the RS485 gating signal
is governed autonomously by the UART itself.
Matt Schulte
Commtech, Inc.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
[not found] ` <1860bbce0807151343rf5cf4apecdc422ba747dd7d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2008-07-15 20:46 ` Alan Cox
0 siblings, 0 replies; 11+ messages in thread
From: Alan Cox @ 2008-07-15 20:46 UTC (permalink / raw)
To: Matt Schulte
Cc: Axel Hosemann, linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA
> The chips may or may not be safe, that isn't the point. There are
> real world applications where response time is an issue and meeting
> these criteria is sometimes impossible from a user application.
> Switching to an RTOS is certainly an option, it would very likely
Firstly: Linux has an RT patch and its expected to get merged soon
Second: Linux has RT processes already
Third: A non RT Linux kernel space and user space will not give much
different performance
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-10 14:16 ` Matt Schulte
2008-07-12 21:49 ` Axel Hosemann
2008-07-12 22:33 ` Alan Cox
@ 2008-07-18 10:19 ` Laurent Pinchart
2008-07-18 13:55 ` Grant Edwards
2 siblings, 1 reply; 11+ messages in thread
From: Laurent Pinchart @ 2008-07-18 10:19 UTC (permalink / raw)
To: Matt Schulte; +Cc: Alan Cox, Axel Hosemann, linux-serial, linux-usb
[-- Attachment #1: Type: text/plain, Size: 4206 bytes --]
On Thursday 10 July 2008, Matt Schulte wrote:
>
> > The big problem is that the kernel does not know what is a "transmission"
> > it just sees a series of writes to the device. In many cases the
> > multi-drop or radio systems also need the caller to wait for a
> > transmission slot either by beacon, by timing or by monitoring the
> > carrier detect to avoid collisions.
> I believe that he is referring to something much simpler than you are
> thinking. He is talking about 2-wire RS485 transmissions in which the
> RTS signal is used to enable the driver chips just before transmitting
> data and disabling (tri-stating) them just after transmitting data.
> There are some UARTs that have this behavior built into them.
And that feature is currently not supported by Linux, even with UARTs that have hardware support for "Auto RS485" mode, such as the 8250-compatible XR16C2850.
The issue is that no flag is defined for the c_cflag field of the termios structure to enable that feature. The following patch is an example of what would be required.
-----------------------------------------------------------------------------
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 62a2e49..a1351d5 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2071,6 +2071,20 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
if (up->port.type == PORT_16750)
serial_outp(up, UART_FCR, fcr);
+#ifdef CARTS
+ /* Auto RS485 Direction Control on 16850 UARTs */
+ if (up->port.type == PORT_16850) {
+ unsigned char fctr;
+
+ serial_outp(up, UART_LCR, 0xbf);
+ fctr = serial_inp(up, UART_FCTR) & ~UART_FCTR_RS485;
+ if (termios->c_cflag & CARTS)
+ fctr |= UART_FCTR_RS485;
+ serial_outp(up, UART_FCTR, fctr);
+ serial_outp(up, UART_LCR, 0);
+ }
+#endif
+
serial_outp(up, UART_LCR, cval); /* reset DLAB */
up->lcr = cval; /* Save LCR */
if (up->port.type != PORT_16750) {
diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h
index 5e79198..7b7ee27 100644
--- a/include/asm-powerpc/termbits.h
+++ b/include/asm-powerpc/termbits.h
@@ -166,6 +166,7 @@ struct ktermios {
#define HUPCL 00040000
#define CLOCAL 00100000
+#define CARTS 004000000000 /* auto RTS control */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 3c8a6aa..3db78cc 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -188,6 +188,7 @@
#define UART_FCTR_RTS_8DELAY 0x03
#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */
#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */
+#define UART_FCTR_RS485 0x08 /* Auto RS485 direction control */
#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */
#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */
#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */
-----------------------------------------------------------------------------
As we need a new flag which isn't Posix-compliant as far as I know, the scope of this change can be broader than just the Linux kernel.
Would the above patch be acceptable (I'm open to changes to the CARTS name) as-is, or does it have to be discussed with userspace developers first ?
> > That seems to best be done in user space as the algorithms are quite
> > variable and some are complex.
> >
> > Do we really benefit from having this in kernel ?
> The problem that can come up when executing this feature in user-land
> (though not exactly common) is when the hardware on the other end
> responds to your message faster than your user app was able to detect
> that the UART is finished and then toggle RTS. When this happens both
> ends are trying to drive the line and you have bus contention, lost data
> and possibly damage to the driver chips themselves.
Best regards,
--
Laurent Pinchart
CSE Semaphore Belgium
Chaussee de Bruxelles, 732A
B-1410 Waterloo
Belgium
T +32 (2) 387 42 59
F +32 (2) 387 42 75
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: Suggested patch for linux
2008-07-18 10:19 ` Laurent Pinchart
@ 2008-07-18 13:55 ` Grant Edwards
0 siblings, 0 replies; 11+ messages in thread
From: Grant Edwards @ 2008-07-18 13:55 UTC (permalink / raw)
To: linux-serial; +Cc: linux-usb
On 2008-07-18, Laurent Pinchart <laurentp@cse-semaphore.com> wrote:
>> I believe that he is referring to something much simpler than
>> you are thinking. He is talking about 2-wire RS485
>> transmissions in which the RTS signal is used to enable the
>> driver chips just before transmitting data and disabling
>> (tri-stating) them just after transmitting data. There are
>> some UARTs that have this behavior built into them.
>
> And that feature is currently not supported by Linux, even
> with UARTs that have hardware support for "Auto RS485" mode,
> such as the 8250-compatible XR16C2850.
>
> The issue is that no flag is defined for the c_cflag field of
> the termios structure to enable that feature. The following
> patch is an example of what would be required.
I'd definitely be in favor of such a flag. It sucks having to
resort to various hacks to control support of that feature in
Linux serial drivers.
--
Grant Edwards grante Yow! In Newark the
at laundromats are open 24
visi.com hours a day!
^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: Suggested patch for linux
2008-07-10 14:47 ` Grant Edwards
@ 2008-08-04 13:28 ` Tosoni
0 siblings, 0 replies; 11+ messages in thread
From: Tosoni @ 2008-08-04 13:28 UTC (permalink / raw)
To: 'Grant Edwards', linux-serial
> -----Original Message-----
> From: Grant Edwards
> Sent: Thursday, July 10, 2008 4:48 PM
...
>
> On 2008-07-10, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
...
> > Do we really benefit from having this in kernel ?
>
> People who do industrial communications sure would. I maintain
> a couple serial drivers that support half-duplex mode exactly
> as described by the OP, and we have to control that feature via
> non-standard hacks.
...
I fully agree with Grant Edwards. I, as well, have been myself maintaining
two serial drivers that support half-duplex mode exactly as described, and I
have to control that feature via non-standard hacks !!!
I have been porting them over and over again with each Linux version and
subversion, since Linux 2.2, and there IS a demand for it.
About the benefit to have this in the kernel: well, we would be enabled to
implement it for any UART, not just the 16550 series !
Now, about Linux RT and response times: The TXD-to-RTS delay must be as
short as possible. To do this, several UARTS i.e. (Ox950) have a special
mode. How could you do this in a user land program for any baud rate ? I
speak about baud rates up to 2 Mbps, they are in use nowadays on
RS2422/RS485 lines.
Really, I would like AT LEAST some commonly defined way to activate this
behaviour. Russell King once suggested to create a line discipline to handle
the RTS, but even like this we need a way (an ioctl) to activate the
behaviour in the UART driver, to make it independent from the specific UART.
JP Tosoni
Acksys
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-08-04 13:55 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-09 23:16 Suggested patch for linux Axel Hosemann
[not found] ` <487546D5.8050908-3sKltW3hOZofv37vnLkPlQ@public.gmane.org>
2008-07-10 8:59 ` Alan Cox
2008-07-10 14:16 ` Matt Schulte
2008-07-12 21:49 ` Axel Hosemann
2008-07-12 22:33 ` Alan Cox
2008-07-15 20:43 ` Matt Schulte
[not found] ` <1860bbce0807151343rf5cf4apecdc422ba747dd7d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-07-15 20:46 ` Alan Cox
2008-07-18 10:19 ` Laurent Pinchart
2008-07-18 13:55 ` Grant Edwards
2008-07-10 14:47 ` Grant Edwards
2008-08-04 13:28 ` Tosoni
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).