Messages in this thread | | | Date | Sun, 17 Oct 1999 21:56:27 -0400 | Subject | Re: serial.c (race?) | From | tytso@mit ... |
| |
Date: Fri, 15 Oct 1999 19:30:10 +0200 (MEST) From: kees <kees@schoen.nl>
I ran into an effect which might be a race in the serial drivers of 2.2.12. I run a program which communicates via the Hart protocol. This is a simplex protocol and uses the IO port more or less like RS485.
It's not a race condition in the serial driver, as much as it is a race in the way you're trying to use the serial driver.
The problem is that the serial driver doesn't support half-duplex communications natively. I've considered putting support directly in the kernel, but there's no standard protocol for half-duplex communications. Different devices have different requires around how long to wait after raising RTS before you start transmitting, and how long to wait after transmitting to drop RTS. Some devices require that you monitor DTR before trying to raise RTS, and so on. So it's rather painful to support half-duplex serial communicatons in anything resembling a general fashion.
The fact that the serial driver doesn't support half-duplex communications is forcing you to try to support it in user space. There are a number of reasons why you might be losing. One is that on faster machines you may be violating some timing constraint on when RTS needs to be raised or lowered.
The other problem, which seems to be the one that you've discovered, is that the rs_write() routine doesn't actually send characters out the serial port, instead it filles the kernel's internal serial write buffers which are then sent out at interrupt time. ("Pseudo-DMA", in BSD speak). You're polling the UART's LSR register, and sometimes (on faster CPU's) this is happening before UART FIFO has a chance to be loaded.
I added a check in my program after the first write call to wait for the drop of the Transmitter Empty bit first before to proceed. That worked.
That, or perhaps putting in a usleep after all of the write calls before polling the transmitter empty bit may be your best bet. The problem is that putting this code into the kernel would force me to put in interlocks that would degrade the performance in the common case, which I'm very hesitent to do since half-duplex operation is *not* commonly used.
The other solution is to put some kind of half-duplex support into the driver, but accept that different users may have to customize the kernel to add their specific device-specific timing constraints, or dependencies on other RS-232 signals. We could try generalizing the support, but I suspect there will also be some kind of wierd-sh*t hardware that demands something new that we hadn't thought of.
- Ted
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |