jcurl / RJCP.DLL.SerialPortStream

SerialPortStream is an independent implementation of System.IO.Ports.SerialPort and SerialStream for better reliability and maintainability. Default branch is 2.x and now has support for Mono with help of a C library.
Microsoft Public License
614 stars 196 forks source link

No more data #139

Closed wvdvegt closed 1 year ago

wvdvegt commented 1 year ago

Not a bugreport but a question:

For many years I have been using .Net40's Serialport class to communicate with devices. I use polling as async or event driven approaches do not match the type of communication. I send commands to the device (it runs a command interpreter to parse whatever the application sends) and wait for output to be returned (might take a while) everytime followed by a command prompt.

The waiting is the issue, on a small number of PC's it seems the Serial port returns that there is no more data (or it hangs reading depending on the code i use). I tried ReadExisting() and testing BytesToRead to be nonzero but all approaches fail on some PC's (and works 'as usual' flawless for 100's of Mbytes of data on my development laptop). I was able to rule out the mBed device hanging or crashing.

So I took the approach to shakeup the communication code and use your SerialPortStream as replacement for .NET4's SerialPort (which had it's issues) in a small test application (which was VERY easy btw) to pinpoint the problem. Note: I read data in a while loop with a Thread.Sleep(1) in each iteration. I can't use Application.DoEvents() as it allows things that interfere (as be able to close the application).

Strangly enough does SerialPortStream exhibits the same issue as the .Net SerialPort and I do not see any exceptions.

I can't verify if all data is send as i need to kill the test application before i can examine the state of the mBed device.

Any suggestions where to look?

jcurl commented 1 year ago

Does sound strange. If using my SerialPortStream, you can certainly enable logging. On .NET framework it is easier (see test code with the App.Config).

SerialPortStream doesn't do event based. It issues a read and waits until the read is done in a tight loop. Debugging can show you if a read is blocked when you'd expect data.

You could also enable logging using SysInternal tools to try and see the IRP commands.

My experience is that the driver is buggy. Early PL2303 didn't like some timeout settings. You could change them. In some weird cases I saw striping of invalid data. Definitely a driver bug.

You could also look for sniffers.

With Com0Com I observed write blocks unless I opened the other port. For that I was able to understand this is a driver issue reading the code.

If it is USB, you could try sniffing the USB bus. But that will only help that the driver received the data.

On Bluetooth, lots of Semaphore Timeout. People on SO have indicated likely a driver bug.

Data can be lost at any time with serial (but it shouldn't happen because of crappy software), and my experience shows that serial protocols must have a robust retry/reset mechanism.

One of the big differences between my code and from MS, they don't buffer. Some devices don't like large buffer requests. I buffer everything.

wvdvegt commented 1 year ago

All the installs use the same driver (supplied by mBed.org) based on FTDI if i'm correct.

Sniffing might help if i could reproduce it at my laptop. Otherwise i would need to install pretty low-level stuff on a company's desktop and test it remotely using TeamViewer.

Hanging does not occur directly, it might take many megabytes of data to occur.

Btw I like the design choices you made ( buffering and no event driven stuff).

Maybe i'll try Com0Com to run the software against an emulator of the hardware normally used. I'll also have to look into the logging (I don't think i have an app.config). Using .Net 4.0

jcurl commented 1 year ago

I use lots of buffering. The MS SerialPortStream calls the underlying driver read functions when client code reads. Because I buffer, I try to avoid overflows in receive where possible.

Also, drivers don't like parity errors very much. I've seen all sorts of weird things trying to test of it properly detects parity errors. But that won't lead to a hang, but rather corruption.

First step would be to enable logging with .NET. See if anything is obvious there. Then a sniffer at the driver level would help.

If you have some kind of support contract with mBed, they might give you further debugging tips. Perhaps a Reg Key to log to disk.

There are also some commercial serial port sniffers. But I'd try the SysInternal tools first.