So I have a .net application that I intend to release to (windows, mac, linux), One of the functions of the app is to read and write bytes to serial port, I have tested it on two PCs, Here are the result
Ubuntu version: Ubuntu 22.04.1 LTS
Serial Port Settings:
Baud Rate: 115200
Stop Bits: 1
Parity: None
RTS: True
DTR: True
Handshake: XOnXOff or None (Depending on experiment)
Experiment 1
Operating system: Windows
Details: Sending and receiving bytes works perfecty
Experiment 2
Operating system: Ubuntu
Details: Sending works, but receiving is a different story
Receiving bytes on Linux
- On The first test i tried receiving a frame of 138 bytes (which I know is being correctly sent because I had already received them on windows) , but instead of receiving 138 bytes I receive 140 bytes with 0x00 at the start and another 0x00 in the middle
- Then I set handshake to XONXOFF which solves the problem and I could receive the 138 bytes correctly
- On the second test I tried receiving a frame of 10 bytes but instead of 10 I received 9 only missing a 0x11 byte in the middle (This is while the handshake still XONXOFF),
- Then I set handshake to None and suddenly I could receive the 10 bytes correctly
So as you can see I am in a pretty bad situation setting handshake to XONXOFF works for big frames only and setting it to none works for small frames only, (ON UBUNTU)
Here is the code (although I think that it is not relevant because this bug is reproducible on any ubuntu machine with C#, and I have already several C# serial tools that gave the same result)
public class RS232Service : IDisposable, IRS232Service
{
public event EventHandler<ReceivedSerialDataEventArgs>? DataReceived;
public event EventHandler<FrameEventArgs>? DataSent;
private SerialPort _comPort = new();
private readonly List<byte> _receivedDataBuffer = new();
public void Dispose()
{
_comPort.Dispose();
GC.SuppressFinalize(this);
}
public void Connect(SerialPort comPort)
{
_comPort = comPort;
if (_comPort.IsOpen) return;
_comPort.ReadTimeout = 1000;
_comPort.DataReceived += OnComPortDataReceived;
_comPort.Open();
}
public void Disconnect()
{
if (_comPort.IsOpen)
{
_comPort.Close();
}
_comPort.DataReceived -= OnComPortDataReceived;
}
private void OnComPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
ReceivedSerialDataEventArgs objReceivedSerialDataEventArgs = new ReceivedSerialDataEventArgs();
int dataLength = _comPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _comPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
Console.WriteLine("Got data length: " + dataLength);
_receivedDataBuffer.AddRange(data);
int parsedbytes = 0;
if (DataReceived != null)
{
objReceivedSerialDataEventArgs.ReceivedData = _receivedDataBuffer;
DataReceived(this, objReceivedSerialDataEventArgs);
parsedbytes = objReceivedSerialDataEventArgs.ReadLength;
_receivedDataBuffer.RemoveRange(0, parsedbytes);
}
Console.WriteLine("removed length: " + parsedbytes);
}
public bool IsConnected()
{
return _comPort.IsOpen;
}
public void SendData(byte[] data, string dataDescription)
{
_comPort.Write(data, 0, data.Length);
DataSent?.Invoke(this, new FrameEventArgs(data, dataDescription));
}
}
****NOTE: **** For some reason there is a tool called moserial on ubuntu which somehow works perfectly with the 138 bytes and the 10 bytes frame when the handshake is XONXOFF (ie it does not lose the 10th byte of the 10 bytes frame)