LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

rs232: ComRd ineffeciently polls the serial port

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
0 Kudos
Message 1 of 6
(4,770 Views)
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
0 Kudos
Message 2 of 6
(4,771 Views)
Your method of using a callback is "uncalled for" if you'll pardon
my bad pun ;-). Since you're basically polling a global flag that gets
set by the callback, you might just as well poll the serial driver
directly by using GetInQLen(), which is it's main purpose in life i.e.
to tell you when you've got enough incoming data to process. One less
global variable is a good thing, and theres less CPU overhead that way
e.g.

if (GetInQLen(ComPort) < nExpectedBytes)
return; // go do something else for a while
else // process what you've received
bValid = (ComRd(nCom, p, nExpectedBytes) == nExpectedBytes);

Nick J.

"Chris Matthews" wrote in message
news:506500000005000000C6800000-1023576873000@exchange.ni.com...
> 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
0 Kudos
Message 4 of 6
(4,770 Views)
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 over
head 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 Kudos
Message 5 of 6
(4,770 Views)
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){
ProcessSystemEv
ents();
}
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.
0 Kudos
Message 3 of 6
(4,769 Views)

I know that this was and old post...

But it triggers my curiosity:

How much loading does "SetComTime(portNum, timeOut);"  place on the PC processor when monitoring the serial port?

Does it take 100% of the CPU?

(Using LW-CVI 7.1.0)

Thanks,

JLV

===  EDIT ===

I will post this as a new thread..

Message Edited by JoeLabView on 07-14-2005 04:38 PM

Message 6 of 6
(4,647 Views)