Sorry if this has been asked and answered before, but a quick search did not reveal much.
I am accessing a serial port using the CreateFile, SetupComm, BuildCommDCB and SetCommTimeouts functions. I have set the input and output queue lengths to 16k bytes using SetupComm.
I am then using GetOverlappedResult to read from the file/stream.
Sorry if this is an unusual way of doing things, but I am using/modifying historic code, and at this point I am to far into the development of the new application to change things.
When I request 8192 bytes from the connected device, all is well. However when I request 12288 or 16384 from the connected device, I only receive between 10300 and 10500 bytes and calling the ClearCommError, seems to reveal a error code 1, which links to an overflow in the input buffer/queue.
My timeout is around 5 seconds, so more than long enough for the 12k or 16k bytes to arrive at the port. I am using a baud rate of 333,330 - unusual, but we are also developing the connected hardware. The same code runs on the hardware regardless of how much data is requested. So I don't think the problem is there, but I can check later using a terminal application.
Based on the above, while a request of 16384 might fail (as it the same as the input buffer size), a request of 12288 bytes should work because it is under the input buffer size set.
Is there anything I am missing?
Is it to do with the serial port I am using - a MOXA uPort 1250. I have looked at this device's config and cannot see anything about a buffer sizes. Unfortunately, I do not have any other serial port that I can try at the moment.
Solved! Go to Solution.
Your basically calling the Windows API COMM functions and this has technically nothing to do with LabWindows/CVI.
Are you sure you use TRUE for the bWait parameter of GetOverlappedResult()?
And yes the device driver for your hardware certainly can have an influence and for instance handle things in a non standard or even buggy way.
Thank you for your reply.
Yes, I am sure I am using TRUE for the bWait parameter of GetOverlappedResult().
I have since tried using a commercial serial port utility and when I request 12k and 16k bytes of data, I receive all of it without a problem. I have even tried 32k and 64k bytes and both work well.
Based on this, it does not look like a buggy device driver. It more looks like either something I am doing when coding or something inherent with the way CVI operates or interacts with the driver.
Do you or anyone else have any other thoughts?
Try using one of the CVI RS-232 example programs in place of your commercial serial port utility? Shouldn't take too much modification to get it to work with your device, as the RS-232 API is really straightforward and pretty well documented.
Well, your use of a commercial serial port utility proofs absolutely nothing. That utility may as well not use GetOverlappedResult() at all but rather a synchronous ReadFile() instead. And if it uses GetOverlappedResult() (and ReadFile() too) it may (in fact it can) NOT rely on it returning all the data and hoping on the intermediate buffer to be large enough and work correctly and not do some fancy stuff, but rather check the returned data to be as large as it requested and if not, request up to N times for extra data.
Robust IO handling requires any app to not rely on the IO routines to just return whatever buffer it requested but instead check that the function returned with the requested amount of data and either bail out with an error or attempt to request the missing data again (with some maximum retry to not stay in an endless loop if the cable broke or something similar for instance).
The fact that it did work in the past is no guarantee that it does now, and you always need to program defensively when you require robust operation.
If you would use VISA instead you can make a few such assumptions as VISA is programmed to provide a pretty clean and reliable API, but you can not expect the Windows API to behave in a certain way unless the MSDN documentation explicitedly states that the API works in that way. And when you think that it states such things, read it again and again and you will usually find out that it doesn't guarantee what you think it should.
I second the advice from rolfk. Why use the windows API at all? Are you trying to maximize your portability? This is a CVI project, so you already have limited portability right there.
Just switch that bad boy over to the CVI RS-232 Library. I've used it on many, many projects with a range of instruments. Smaller footprint and learning curve than VISA too.
It's small, robust, and clearly defined.
Thank you rolfk, thank you ElectroLund
Based on a previous suggestion by Sporty, I gave one of the CVI RS-232 examples a go (I only had about 30 minutes to spare at the time). Unfortunately I could not get it to function with my target device. I will probably try again soon.
I have also been pointed at NI-VISA by my colleague, which I might also try.
With regards to why I am using Windows API. I have developed this application from historic code given to me by my colleague. This reason for this is because the larger functions which have been written which use the Windows API functions are still valid for communication with the new hardware we are developing. The only difference is that the response lengths have become many magnitudes bigger - and hence why I am probably running into problems.
With regards to my Commercial Serial Port utility, it has no idea how many bytes to expect back from the connected device, so it cannot request multiple times until the expected data is received. However, I do agree that I have absolutely no idea how it's receive mechanism might be coded. I was using it a proof that the problem is not with my connected hardware or the USB-Serial port that I am using.
Yeah, those are good steps. I (and we all) have a set of "toolbox" utilities that I use as sanity check. Two that I regularly return to when first starting a new serial protocol project are:
1) RealTerm (very old, but incredibly useful open source serial app)
2) Device Monitoring Studio (commercial, port sniffing)
In both cases, the receiver code tends to be always listening in a secondary thread, and will print whatever it gets to terminal. So while that help you verify your hardware is good, it doesn't really help you in your own development.
Just a quick headsup. I have just tried the CVI-RS232 example again and modified it to my needs.
I think I have managed to get it to work. I can now receive 32kb as requested to my target hardware.
Now it is a case of reworking my code to use CVI-RS232 instead of the the Windows API - it is probably going to be a bit of a struggle!
Thank you (and to Sporty) for your suggested us of CVI-RS232.
Thank you rolfk for your help and suggestions - if CVI-RS232 did not work for me, I would have moved onto NI-VISA.
Thank you once again to everyone who has helped.