LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Missing chunks of text with CVI ComRd inside a COM callback

 

Hello all,

 

I am confronting with a problem while reading data from a COM port.

I used InstallComCallback in CVI 7.0 to install a callback function that reads the data from the COM into a buffer.

This data is then copied into a relevant queue or memory space using a pointer to a function and the callback returns.

When I look at this data I find that large sums of text are missing from time to time.

For instance if I send to this COM 10,000 lines (all are CR terminated and numbered) of text, about every 500 to 700 lines I get a missing set of lines and portions of lines.

For example:

 <8046> This is line number = 8046 *

 <8047> This is line number = 8047 *

 <8048> This is line number = 8048 *

 <8049> This is line number = 8049 *

 <8050> This is line num <8374> This is line number = 8374 *

 <8375> This is line number = 8375 *

 <8376> This is line number = 8376 *

 <8377> This is line number = 8377 *

 <8378> This is line number = 8378 *

 

 

I use a baud rate of 38400 and the callback is invoked on LWRS_RXFLAG or LWRS_RECEIVE. When I tried decrease the baud rate or increase the buffer size I got the same result).

 

What could be the cause of it?

 

Thanks,

 

           Gil

 

   

0 Kudos
Message 1 of 11
(4,716 Views)
LWRS_RXFLAG  is a flag that looks for a certain character before it invokes.  What did you set this character to?
LWRS_RECEIVE waits for "x" number of bytes to be received before it invokes.  What was this set to?
How big of a space do you reserve for copying?
 
My guess is that your callback is "re-invoked" at times before you finish copying.
 
0 Kudos
Message 2 of 11
(4,705 Views)
As noted in the file attached to my question:
 
The LWRS_RXFLAG  should fire on VALUE_CALLBACK_EVENT_CHAR = '\r'
The LWRS_RECEIVE should fire on VALUE_INPUT_QUEUE_NOTIFY_COUNT = 500
My buffer size is VALUE_INPUT_BUFFER_SIZE = 512 ( a bit bigger then the LWRS_RECEIVE limit)
 
I will try to remove one of these flags and see what happends.
 
Thanks,
           Gil
0 Kudos
Message 3 of 11
(4,694 Views)
Hi again,

 

I have tried to use only the LWRS_RECEIVE with a limit of 256 bytes, reading it into a buffer of 8192 on a COM callback call.

And also tried using only LWRS_RXFLAG (with the CR char '\r') and Zero in the Notify count field.

I even tried to copy all data from COM directly to a large memory buffer (to avoid slow access to files or screen), with no success.

In all cases the results were the same... I still get missing lines or portions of lines.

What am I doing wrong? Smiley Sad

 

Has anyone ever saw a good terminal example written using CVI (event driven that can work with baud of 38400 and up).

I never seem to get the results of SW terminals such as Symantec ProComm or even Microsoft HyperTerminal.

 

Is the CVI layer built so high over the Windows API that the system cannot respond as fast?

 

            Gil

 

 

0 Kudos
Message 4 of 11
(4,692 Views)

A few years back one of our chaps had terrible trouble trying to use CVI's com callback scheme at Baud rates of 57600 (was using CVI 5.0, then). With the data flow system that we had in place, it looked as though CVI was actually losing com data in between the time delay of recognising the programmed interrupt character ('\n') and actually being able to respond to the callback. In the end we had to abandon the callback scheme and instead implemented our own polling system based on a CVI Timer and inspection of the com input queue status. Worked fine after that and we vowed never to use the com callback scheme again! (Perhaps later versions of CVI have fixed this problem?)

JR

Message 5 of 11
(4,687 Views)

I have run cvi com ports at 115k with a com callback without issue a number of times.  There are probably more than a dozen ways to implement this but the scheme I use is to only use the callback to move data to a thread safe queue.  The callback can use LWRS_RXCHAR, LWRS_RECEIVE, etc to execute as often as is practical to move data to the TSQ.  I can then use the functions for TSQ or a TSQ callback to process the data.  The key being that I avoid some of the issues with processing the events from the windows driver, the way the windows driver works, you are not guaranteed to get an event if you are already processing a com callback.  You have to build some redundancy into your callback scheme to handle these dropped events. This is the source of a lot of issues when processing com callbacks in CVI.   

If the physical system hardware is fast enough, the windows driver buffer is large enough to avoid dropped characters with any of the 16550 (16 bit hardware fifo buffer) and higher class uart chips.  The only way you can really drop data is a buffer overun at the windows level, so as long as your callback routines service the windows buffer fast enough, you should not see data loss. 

Looking at your code a couple of places stand out as possible areas of concern:
- It is possible for you to get a length of zero returned from GetInQLen(), would the OnNewDataReceived routine handle that correctly.

- Does the OnNewDataReceived routine do anything that would make the com callback routine re-entrant, if so you may have problems.

- You will only get the LWRS_RECEIVE event the first time the buffer exceeds 500 bytes, if you do not process faster than the data comes in, you will only receive LWRS_RXFLAG events on each '\r'.  If you drop any of these events you will continue to get further behind in your processing until eventually you get a buffer overun.

- I personally avoid delays in callback processing routines, and would instead just process as much as possible and then return, this of course works much better with the design above using an intermediate queue.

- You really need to process, or at least setup and event to process, the remaining data in the input queue before you exit the callback.   

- In debugging this you may want to check to see if Data->OnNewDataReceived is getting stuck or corrupted in the False state.      

Good Luck     

Message Edited by mvr on 08-29-2006 08:32 AM

Message 6 of 11
(4,681 Views)
One more thing to look at: bytes from ComRd() could be a negative number.  Some error checking is probably required. 
Message 7 of 11
(4,668 Views)

Dear mvr,

 

As you suggested, I do write to a memory Queue and the data is processed outside the callback by a separate process.

The OnNewDataReceived simply does the copying into the given queue.

 

I have removed the DELAY and added a check for zero from the GetInQLen() and I exit the callback  without doing anything when zero is returned.

This still did not improve the results.

 

For now I must agree with jr_2005 and may have to result in abandoning the usage of a callback although I think this is the correct way it should be done.

 

Could you provide an example of the COM callback you mentioned?

 

Thanks,

            Gil

 

 

 

0 Kudos
Message 8 of 11
(4,620 Views)
I am having similar com issues. Could you send a copy of how you solved this problem?
0 Kudos
Message 9 of 11
(4,012 Views)

Hi,

Eventually I did not use COM callback in my code, but serial reading/writing procedure.

You are welcome to get this code:  gil.groman@alcatel-lucent.com

Gil

0 Kudos
Message 10 of 11
(3,948 Views)