|
Home > Archive > Unix Programming > March 2006 > Interrupt a Blocking Serial Port Read
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Interrupt a Blocking Serial Port Read
|
|
| heilig@iname.com 2006-03-17, 5:55 pm |
| I'd like to implement an overall timeout for a read from a serial port.
Consider the following requirements:
Receive data in packets of 10 bytes. If 10 bytes do not arrive after
500 ms send an "Are You There?" message and retry.
My first thought was to set VMIN to 10 and VTIME to 5. But the read
does not time out after 500 ms if no data is received. It blocks
forever. So my second thought was to set VMIN to 0 and VTIME to 5 (this
is what the termios man page describes as an overall timeout). But now
the read returns immediately if any data is received. What I want is a
read that will block until 10 characters are received or 500 ms
elapses.
What I would like is a read operation that performs as follows:
If 0 to 9 bytes are received and 500 ms elapses after the read was
called then the read returns with the data and number of bytes that
were read (even if that number is zero). If 10 bytes are received then
the read returns as soon as the 10 bytes are available.
The only solution I can think of is to perform multiple read as
follows:
set VMIN = 0
LOOP:
If elapsed_time < 500 and bytes_received < 10 then
set VTIME = 500 - elapsed_time
read a maximum of 10 - bytes_received;
goto LOOP;
If a single byte is received then the read will return. The loop will
continue as long as the total elapsed time has not exceeded 500 ms and
less than 10 bytes were received.
If no data is received (on any read operation) then the read will
timeout.
This is not great. It is very possible that the loop will read one byte
at a time. There must be a way that doesn't eat up so much processor
time?
Is it possible to interrupt the read from another thread?
Thanks for your attention and help,
Brian
| |
| Simon Elliott 2006-03-17, 5:55 pm |
| On 17/03/2006, heilig@iname.com wrote:
> I'd like to implement an overall timeout for a read from a serial
> port. Consider the following requirements:
>
> Receive data in packets of 10 bytes. If 10 bytes do not arrive after
> 500 ms send an "Are You There?" message and retry.
If your app doesn't need to do anything else while waiting for the data
to arrive, and there isn't any advantage in responding to the packet
arriving before the 500 ms have elapsed, one very simple way of doing
this would be to sleep for 500 ms with nanosleep() then do a
nonblocking read() for 10 bytes. If you get 10 bytes, you've got all
the packet within 500 ms and can proceed. If you get 9 or less bytes or
there's an error, you can send your nak message.
If there's an advantage in your app being responsive and replying as
soon as it's received 10 bytes, you can set VTIME to zero for infinite
delay, try to read() 10 bytes, and use alarm() to hit read() with a
signal after 500 ms.
(Caveat: this is my understanding and I've done this with QNX, a POSIX
compliant realtime OS, but I haven't tried it in linux/unix. More
experienced unix developers here may be able to advise on this.)
In linux/unix I've done this using poll() and nonblocking read() so
that my app can get on with other things while waiting for the packet
to arrive. poll() has a millisecond timeout argument.
--
Simon Elliott http://www.ctsn.co.uk
| |
| heilig@iname.com 2006-03-19, 12:02 pm |
| Simon Elliott wrote:
> If there's an advantage in your app being responsive and replying as
> soon as it's received 10 bytes, you can set VTIME to zero for infinite
> delay, try to read() 10 bytes, and use alarm() to hit read() with a
> signal after 500 ms.
Yes, this is exactly what I was looking for. Thank you.
I found the following information in:
http://www.opengroup.org/onlinepubs/009695399/toc.htm
Signals affect the behavior of certain functions defined by this volume
of IEEE Std 1003.1-2001 if delivered to a process while it is executing
such a function. [...] If the action of the signal is to invoke a
signal-catching function, the signal-catching function shall be
invoked; in this case the original function is said to be
``interrupted'' by the signal. If the signal-catching function executes
a return statement, the behavior of the interrupted function shall be
as described individually for that function, except as noted for unsafe
functions.
If a read() is interrupted by a signal before it reads any data, it
shall return -1 with errno set to [EINTR].
If a read() is interrupted by a signal after it has successfully read
some data, it shall return the number of bytes read.
I guess this is pretty basic Unix programming, but hey, now I know!
Brian
| |
|
|
|
|
|