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

rs232: ComRd ineffeciently polls the serial port

550 views
Skip to first unread message

Daniel_Jackson_Peacock

unread,
Jun 17, 2002, 6:15:08 PM6/17/02
to
Hi,
I've been tasked with improving the effeciency of a LabWindows/CVI
program developed in my department. One significant area of
ineffeciency that I've noticed is that ComRd and ComRdByte use polling
(I used portmon to observed it sending the Windows system I/O request
code IRP_MJ_READ upto 40,000 times per second). At a slow baud rate
this can cause 100% of the CPU to be taken up waiting for serial port.
I don't mind that the program is blocked while waiting for the serial
port, but the CPU waste is unacceptable, as we have other time
critical software running on the system as well. I do know that this
problem can be solved by using the InstallComCallback instead of doing
a ComRd. However, the program is upwards of 20,000 lines of code and
has a complex interaction of both constant serial port communication
to refresh displays as well as serial port communication to issue
commands to the device on the other end of the serial port at the
user's convienience. Furthermore, the sweeping the modification is the
more testing it will have to undergo before we can use it and we would
like to have this improvement in time for an upcomming experiment. For
these reasons I would prefer not to convert all the IO calls in the
program over to a callback method unless absolutely necissarry. Is it
at all possible for me to somehow replace ComRd with an equivilant
non-polling version? Any other ideas for solutions?
Thank you,

Daniel Jackson Peacock
Sandia National Laboratories

Chris Matthews

unread,
Jun 18, 2002, 10:58:30 AM6/18/02
to
The InstallCOMCallback method is the only great way that I'm sure you
would be able to fix this issue. You could also set your timeout
really low or disable it with SetComTime and then loop over the ComRd
yourself with a small Delay until you read data. That would control
the rate of the polling. You could see if SetSleepPolicy with Sleep
More helps this as well, but I doubt it since it doesn't seem to be
message driven polling.

Best Regards,

Chirs Matthews
National Instruments

Daniel_Jackson_Peacock

unread,
Jun 18, 2002, 11:12:29 AM6/18/02
to
Hi,
You know it always works like this. I spend 3 days trying to figure
something out and after I give up and ask someone for help I come up
with a solution :)

For anyone who might be in a simular position, I'll explain how I
solved this. The code that I had that was constantly refreshing first
sent a request over the serial port and then read a responce which was
always X bytes long. What I did was install a callback that is called
every time that X bytes are received.
In this callback all I do is set a flag variable (x_bytes_read) to
one. Then in my function that does the constant updateing I put the
following
//send request
x_bytes_read = 0;
ti = Timer();
while (!x_bytes_read && Timer()-ti < COM_TIMEOUT){
ProcessSystemEvents();
}
if (!x_bytes_read) {
// we timed out return error
}
// read responce
This way, when I'm in the refreshing code I wait for the callback to
be called before proceding, so I know that the data is already there.
And if the callback is called when I am using the comport for
something else it is harmless (and my main loop garentees that all
events are processed before the refresh code is run again, so I know
that the callback was one that was issued after I sent the request not
left over from some other communication). Hope this will help someone
else in the future.
Cheers

D. Jackson Peacock

up a callback for the code that is constantly refreshing.

Daniel_Jackson_Peacock

unread,
Jun 19, 2002, 10:34:04 AM6/19/02
to
Hi,
What you say makes a lot of sense and that is one of the solutions
that I tried originally but it did not provide nearly as efficient of
an implementation that I've settled on and outlined in my earlier(2nd)
post. The attempt was something like this (with additional precautions
added for timeout), where 'size' is the number of bytes that I needed
to read:

// send request
in = GetInQLen (COM_PORT);
while (in < size){
Delay ((size-in)*8/(double)COM_RATE);
in = GetInQLen (COM_PORT);
}
// read responce
For some reason this was far less effecient (2x-3x slower depending on
the sleep policy) than the previous solution I posted. I have not
noticed any signs that the callback has significant overhead while
running. The most overhead I noticed was installing the callback,
which is why I chose to run it constantly instead of installing it
just before each wait, and disabling it afterwards. I agree that what
you say appears to be a fine way of solving the problem, it just
unfortunately did not turn out that way for some reason.
Thank you for your post.
jackson

0 new messages