devc-ser8250 and flaky Uart

QNX 6.3 default starts devc-ser8250 on my ziatech board that sits on an std32 backplane.

I successfully use the following (pseudo) code to read/write to the serial port:

fd = open("/dev/ser1", O_RDWR);

/* Write 1 byte to port */
numWritten = write(fd, packet, 1);

In another spawned off thread I wait for incoming bytes via
numRead = read(fd, buffer, 1);

Now this all works quite nicely under ‘normal’ conditions and data transfers back and forth with no problems.

However if the cable gets disconnected from the other side or there is excessive noise the ability to ‘send’ bytes over the Uart can be lost (not everytime there is a disconnect but sometimes when I least expect it).

When this happens I look via pidin I see my sending thread is blocked on devc-ser8250 and the ‘send’ call never returns (obvious since I opened with the default blocking mode). At this point devc-ser8250 is reply blocked on 1 (a thread in the kernal).

Looking at some old DOS code that used this board I found reference to the fact that the Uart on this Ziatech board is flaky in send mode. What that old code did was count sending interrupts from the Uart and if they didn’t total the number of bytes sent the code manually reset the Uart. This according to people here fixed the problem.

So it appears that there is a flaky Uart issue in hardware. My question is, how can I do this under QNX with the serial driver? I don’t see any options to send to the driver to ‘reset’ the Uart or any way that the driver knows the Uart has stopped being able to send.

The only thing I can think of to do is spawn a 3rd thread that opens /dev/ser1 in non-blocking mode and say every half second it wakes up and tries to send to the driver and if it gets an error with EAGAIN I will manually reset the Uart from this thread (I have the address’s to do that from the old code I was looking at). Note: I don’t want the open in my original 2 threads to be O_NONBLOCK mode because I want my read call to block for input rather than returning and forcing me to delay in a polled mode for input.

Is this the best method to handle this or is there something else I might consider doing to determine when the Uart is failing to send data?



My idea doesn’t seem to work.

I spawned another thread and instead used the ‘select’ call to determine if the driver was available to write to.

But for some reason a shared fd between threads doesn’t play nicely with select.

Select aways times out if another thread is writing to the driver (even tho both threads share the same fd) and only when I stop that other thread completely does the select call correctly determine that I can write to the driver.

So I’m at a loss right now to determine when the driver is in a hung state.


Some more info here.

I’ve been playing around with this for the past couple of days not making much progress even if I wrote directly to the Uart itself in an attempt to reset it.

Then I took a look at the stty settings for the serial port while the Uart is running correctly (transmitting) and incorrectly (not transmitting and the serial driver hangs when sending data to it).

I noticed something right away. The speed on the serial port in both cases is 38400. This is strange because I use stty to specifically set it to 1200 (the speed the other side runs at) when my program starts. So when I get to the hung state of not being able to transmit any more from another console I did a 'stty baud=1200 </dev/ser1" and lo and behold everything started transmitting again.

So now I am really puzzled. Is there any reason why the Uart or the QNX serial driver would change the speed back to 38400 right away even when I am connecte? It seems everything works fine transmission wise when it jumps back to 38400 as long as I am continually connected to the other side but if the connection is lost (disconnected cable or noise) there is no way it re-established itself correctly.

As a very quick and dirty hack I spun off a thread that checks the speed and re-sets it via the stty command to 1200 baud when I lose connection and the writes to the driver hang. This works and fixes the connection but surely this isn’t the right way to go about keeping the speed of the line set.