Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Serial port: ClearCommError problems (don't want the internal error-flag reset)

978 views
Skip to first unread message

R.Wieser

unread,
Oct 16, 2015, 9:50:48 AM10/16/15
to
Hello all,

I'm reading the serial port in a polling fashion, and have the need to be
able to retrieve a specific ammount of bytes in a single go (could be a
value of a certain number of bytes, but also a fixed-length string). For
this I have to retrieve the ammount of available bytes, so that I can check
if I can read all the bytes in a certain ammount of time, and if not return
(and this is important) without having read anything.

The problem is that, as far as I can tell, the only command this can be done
with, ClearCommError, also clears an internal "no communications allowed"
flag (enabled by "fAbortOnError"), which gets set as a result of a
communications (frame, parity) error.

This means that communications can start again, even though I've not emptied
the input buffer yet (meaning that *somewhere* in the buffer there will be a
data corruption (new data appended to the faulty-ended old data), without me
being able to tell where (a problem becomes even more pronounced when more
failures occur).

TL;DR:
How do I use ClearCommError (retrieving the current error states as well as
the read- and writebuffer sizes) *without* allowing the communications to
restart.

By the way: I've though about using the command, check the error states and
than manually disable further communications if any state was set, but #1: I
don't think I can actualy disable port reading (or writing) in the same
fashion the internal flag does, and #2: although the time between the
ClearCommError's re-allowing of communications and my subsequent
re-disallowing would be short there is no guarantee nothing will slip thru
in that time (especially not at higher speeds). In short, not an acceptable
method.

Regards,
Rudy Wieser



JJ

unread,
Oct 19, 2015, 7:53:56 AM10/19/15
to
Once a communication error occurred, the OS stops fetching data from the
hardware buffer into the software buffer. The external device might still be
sending data to the serial port and overflows the hardware buffer. So,
you'll have to restart polling the data from the device.

I suggest you research the data structure sent from the external device.
Know which byte is the start of a data packet (e.g. header or data-start ID
byte) and which is the last byte of a data packet. Knowing the fixed number
of data packet size isn't enough if you can't control when the external
device start sending the data.

Use async I/O so you'll know how many bytes and what data bytes have been
received. Determine which is the start of a data packet, and which is the
end.

Use another buffer (the 3rd buffer) to place the ready-to-use data fetched
from the software buffer, piece by piece as they arrived.

R.Wieser

unread,
Oct 19, 2015, 9:45:35 AM10/19/15
to
JJ,

> So, you'll have to restart polling the data from the device.

True. But, as far as I'm concerned, only if-and-when my side is ready for
it, not as an attempt to empty the software read buffer upto the point of
the error.

> I suggest you research the data structure sent from the external device.

Can't do, as there is no single external device involved, nor a fixed
datastructure.
What I'm writing is ment to be generic, being able to cope with different
circumstances.

> Use another buffer (the 3rd buffer) to place the ready-to-use data
> fetched from the software buffer, piece by piece as they arrived.

I thought of that too, but rejected it as I didn't want to believe that
would be the only solution to the problem. :-|

I must say I'm a bit baffled about MSes approach to accessing the serial
port. Almost as if its written for a specific app, with disregard to any
generic usage ...

Regards,
Rudy Wieser


-- Origional message:
JJ <jj4p...@vfemail.net> schreef in berichtnieuws
1rkxsqngzxtkk$.147g7mogwgiwt$.dlg@40tude.net...

Charlie Gibbs

unread,
Oct 19, 2015, 2:17:40 PM10/19/15
to
On 2015-10-19, R.Wieser <add...@not.available> wrote:

> I must say I'm a bit baffled about MSes approach to accessing the serial
> port. Almost as if its written for a specific app, with disregard to any
> generic usage ...

I keep it as generic as possible by disabling all timeouts and doing
nonblocking reads on the serial port. I handle my own polling; if
there's no activity I avoid hogging the CPU by sleeping until a timer
tick wakes me up. Here's how I open a port:

HANDLE commhandle;
COMMTIMEOUTS commtimeouts;
DWORD errflags;

commhandle = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(commhandle == INVALID_HANDLE_VALUE) {
... error routine ...
}

SetupComm(commhandle, 8192, 8192); /* Set buffer size. */

if(!PurgeComm(commhandle,
PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR)){
... error routine ...
}

if(!ClearCommError(commhandle, &errflags, NULL)) {
... error routine ...
}

memset((void *) &commtimeouts, 0, sizeof(commtimeouts));
commtimeouts.ReadIntervalTimeout = MAXDWORD;
commtimeouts.ReadTotalTimeoutMultiplier = 0;
commtimeouts.ReadTotalTimeoutConstant = 0;
commtimeouts.WriteTotalTimeoutMultiplier = 0;
commtimeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(commhandle, &commtimeouts);

--
/~\ cgi...@kltpzyxm.invalid (Charlie Gibbs)
\ / I'm really at ac.dekanfrus if you read it the right way.
X Top-posted messages will probably be ignored. See RFC1855.
/ \ HTML will DEFINITELY be ignored. Join the ASCII ribbon campaign!

JJ

unread,
Oct 19, 2015, 3:37:42 PM10/19/15
to
On Mon, 19 Oct 2015 15:48:26 +0200, R.Wieser wrote:
> JJ,
>
>> So, you'll have to restart polling the data from the device.
>
> True. But, as far as I'm concerned, only if-and-when my side is ready for
> it, not as an attempt to empty the software read buffer upto the point of
> the error.

By restart, I meant the port read operation, which clearing the error
states, and then read the port again. Continue reading, to be exact. Of
course, you won't be able to do anything about any corrupted data and
overflowed buffer during the error, since you can't control the data source
device.

>> I suggest you research the data structure sent from the external device.
>
> Can't do, as there is no single external device involved, nor a fixed
> datastructure.
> What I'm writing is ment to be generic, being able to cope with different
> circumstances.

A serial port won't have any readable data without a device connected to it,
whether physically, or virtually. The device may actually be a USB device
that use serial port standard for its main function. e.g. a mobile GSM USB
modem, or USB based serial port adapter.

If you're writing a blind, generic serial port device reader library, for
devices that only spit out data, async and overlapped I/O should be used.

>> Use another buffer (the 3rd buffer) to place the ready-to-use data
>> fetched from the software buffer, piece by piece as they arrived.
>
> I thought of that too, but rejected it as I didn't want to believe that
> would be the only solution to the problem. :-|

Unfortunately, that's likely the only practical solution. Whether roll your
own, or let third party library handle it.

> I must say I'm a bit baffled about MSes approach to accessing the serial
> port. Almost as if its written for a specific app, with disregard to any
> generic usage ...

The current serial port API already have everything you need. You just need
to functions that fits nicely for your application.

R.Wieser

unread,
Oct 19, 2015, 3:58:15 PM10/19/15
to
Charlie,

> I keep it as generic as possible by disabling all timeouts
> and doing nonblocking reads on the serial port.

Well, my idea was to provide both methods, leaving it upto whomever uses it
to choose which one would best fit the requirements.

So, both a timed-out reading (with initial and interval timeouts) as wel as
an instant, but only when all bytes are available method -- and most likely
a combination of both too, a timeout on if all required bytes are available.

And there I am, with no clear way to implement any of those.

On the first I'm twarthed by the absense of an "initial timeout" possibility
and for all by the absense of a method to check for the available bytes
without resetting an error condition. :-(

Thanks for your code though.

A question though: How do you handle read (and/or write) errors ? Purge
everything and start new ? Something else ?

Regards,
Rudy Wieser


-- Origional message:
Charlie Gibbs <cgi...@kltpzyxm.invalid> schreef in berichtnieuws
n03c3...@news3.newsguy.com...

Charlie Gibbs

unread,
Oct 19, 2015, 4:46:28 PM10/19/15
to
On 2015-10-19, R.Wieser <add...@not.available> wrote:

> Thanks for your code though.
>
> A question though: How do you handle read (and/or write) errors ? Purge
> everything and start new ? Something else ?

I reset everything - close the port and re-open it. My code is part
of a data collection routine which runs 24/7; my first priority is
to make sure it stays up no matter what happens. My routine collects
data on several ports concurrently; it uses round-robin polling,
sleeping as necessary to provide rapid response with minimal CPU usage.

R.Wieser

unread,
Oct 20, 2015, 5:44:21 AM10/20/15
to
JJ,

> A serial port won't have any readable data without a device
> connected to it,

True. But with the "can't do" I ment that I can't "research the data
structure sent from the external device", as its unknown which device will
be connected.

> If you're writing a blind, generic serial port device reader
> library, for devices that only spit out data, async and
> overlapped I/O should be used.

I've not been mentioning anything about writing data, as currently reading
seems to generate enough problems to keep me/us busy. :-) But yes, that is
something which the program also needs to be able to do.

As for overlapped I/O, why ? Thats only needed when I would want to read
and write *to the filehandle* at the same time. As I'm currently writing
for a single-threaded environment *and* am using a polling approach there
will be no chance that will ever happen.

> The current serial port API already have everything you need.

Obviously not. :-\

> You just need to functions that fits nicely for your application.

Yeah, thank you. :-(

I though that ClearComError function is in itself a good example of how
*not* to combine quite unrelated functionality (which is nowhere else to be
gotten).

Or how the "total timeout" might be good to get outof a lengthy read action
and keep the rest of the program responsive, but that only applies to
single-thread, event-driven apps. What about the others ?

Regards,
Rudy Wieser


-- Origional message:
JJ <jj4p...@vfemail.net> schreef in berichtnieuws
azckao3i8v0k.1m...@40tude.net...

R.Wieser

unread,
Oct 20, 2015, 5:51:20 AM10/20/15
to
Charlie,

> I reset everything - close the port and re-open it.

Thanks.

I was hoping you maybe had another method, allowing the read buffer to be
drained of its, upto/near the point of failure, perfect valid data. :-)

Regards,
Rudy Wieser


-- Origional message:
Charlie Gibbs <cgi...@kltpzyxm.invalid> schreef in berichtnieuws
n03ko...@news4.newsguy.com...

JJ

unread,
Oct 20, 2015, 12:43:07 PM10/20/15
to
On Tue, 20 Oct 2015 10:45:55 +0200, R.Wieser wrote:
>
> I've not been mentioning anything about writing data, as currently reading
> seems to generate enough problems to keep me/us busy. :-) But yes, that is
> something which the program also needs to be able to do.
>
> As for overlapped I/O, why ? Thats only needed when I would want to read
> and write *to the filehandle* at the same time. As I'm currently writing
> for a single-threaded environment *and* am using a polling approach there
> will be no chance that will ever happen.

I never mention *anything* about writing to the serial port. Why you always
do assumptions?

A mere async I/O is not enough, because you can only access the received
data after all of the requested number of bytes are receved.

A single threaded serial port application/library is a big mistake. Main
reason is that it'll get buffer overflow easily.

> I though that ClearComError function is in itself a good example of how
> *not* to combine quite unrelated functionality (which is nowhere else to be
> gotten).

ClearComError() is a serial port error recovery function which can't be
ignored.

> Or how the "total timeout" might be good to get outof a lengthy read action
> and keep the rest of the program responsive, but that only applies to
> single-thread, event-driven apps. What about the others ?

Multi thread is the key to get responsive program (and serial port polling
with minimum interruption). Keep things separate. Each thread do their own
job.

Charlie Gibbs

unread,
Oct 20, 2015, 2:04:10 PM10/20/15
to
On 2015-10-20, JJ <jj4p...@vfemail.net> wrote:

> Multi thread is the key to get responsive program (and serial port polling
> with minimum interruption). Keep things separate. Each thread do their own
> job.

Nevertheless, with a bit of care it's possible to write a single-threaded
routine that does the job, using polling, sleeps, and a timer. It's all
a matter of choosing between the complexities of doing it this way and
the complexities of multi-threading, overlapped I/O, etc. My routine has
been running in hundreds of customer sites for years; it never drops data
and uses neglegible CPU - and the code runs on *n*x as well.

R.Wieser

unread,
Oct 20, 2015, 3:14:39 PM10/20/15
to
JJ,

> > I've not been mentioning anything about writing data,

My apologies. Somehow for me your "async and overlapped I/O" translated to
it (as you could have noticed from the paragraph just below my statement).

> A mere async I/O is not enough, because you can only access
> the received data after all of the requested number of bytes are
> receved.

For the second part of that statement ? Untrue. I've mentioned how I
think I can tackle that problem a few times now (in two different ways), so
I fail to see why you now bring that problem up.

As for the first part ? I think I've made quite known that I'm after a
polling solution, not an interrupt-driven one.

... But if that is the *only* way it will work than you've actually proven
my point that the serial communications API doesn't actually provide the
tools to create *a* solution (as opposed to "a specific, effectivily
mandated" one). :-)

> A single threaded serial port application/library is a big mistake.
> Main reason is that it'll get buffer overflow easily.

Bull. That can happen regardles if app/lib is mutithreaded or not -- as a
result from not calculating the size of the buffer correctly (as a function
of the choosen baudrate and the read-cycle time) or not reading (enough)
data from the buffer in the time you allowed for it.

Even with a DCB's highest baudrate shown, 256000 bps, a buffer of a mere 256
KByte would give you a cycle-time of 10 seconds. That should be enough for
most situations, even polling ones.

> ClearComError() is a serial port error recovery function which
> can't be ignored.

I would have been *very* happy if it would be only that. :-(

But I do not understand you fully: A function *I* have to call, but "cannot
be ignored" ?

Or do you maybe mean that its an always needed function to keep the program
running ? In that case, I don't think so. At least, not for its "reset an
internal errorflag" part. There are, AFAICS, at least two other ways to get
that done.

> Multi thread is the key to get responsive program

I'm sorry, but that is not an answer to the question I asked I'm afraid. :-\

Regards,
Rudy Wieser


-- Origional message:
JJ <jj4p...@vfemail.net> schreef in berichtnieuws
ippflwjk2vr0.1c62a8vlgs0el$.dlg@40tude.net...
0 new messages