1

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)

Ahmed Fawzy
  • 309
  • 2
  • 8
  • Suggest you study the man page for termios. There's a lot more to configuring a Linux serial terminal than just baud rate, character framing, and flow control. E.G. certain conditions will cause insertion of null characters. If the serial terminal is not in raw mode, then you might see some "*weird behavour* [sic]". – sawdust Oct 11 '22 at 21:00
  • The following may be helpful: https://stackoverflow.com/a/70614758/10024425, [SerialPort.NewLine](https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.newline?view=dotnet-plat-ext-6.0&viewFallbackFrom=net-6.0), and [SerialPort.ReceivedBytesThreshold](https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.receivedbytesthreshold?view=dotnet-plat-ext-6.0). You really should read all of the [SerialPort](https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=dotnet-plat-ext-6.0) documentation though. – Tu deschizi eu inchid Oct 12 '22 at 03:55
  • So How can I set the .net serial port to raw mode? – Ahmed Fawzy Oct 15 '22 at 15:32
  • @sawdust The problem is currently I am not able to set raw mode in my app, but even when I set it via stty in the command there is still insertion of null characters – Ahmed Fawzy Oct 15 '22 at 20:07
  • If you want more than vague comments, then stop writing vague summations and provide details. For a start, PCs nowadays don't have COM ports, so what are you using? – sawdust Oct 15 '22 at 21:04
  • My setup is I have a texus instrument "tiva C" board connected to my laptop running ubuntu via usb to micro-usb cable and the device name is /dev/ttyACM0 (if that is relavent) – Ahmed Fawzy Oct 16 '22 at 05:22
  • Why does this "*tiva C*" board send packets of 138 or 10 bytes? Are these responses to request messages, or unsolicited? If these messages contain bytes other than text in ASCII code, then software flowcontrol (i.e. XON/XOFF) is inappropriate. But why does this link require flowcontrol? (The system buffer is 4KB.) IOW does this link use a request-response dialog, or is this "*tiva C*" board sending unsolicited packets??? – sawdust Oct 17 '22 at 03:36
  • This link does not require flowcontrol at least on Windows but on ubuntu I could not receive the 138 bytes without the inserted 0x00 until I used flowcontrol (I do not know why it only works with flowcontrol) If you know how can I receive the 138 without the inserted 0x00 it would solve my problem – Ahmed Fawzy Oct 18 '22 at 14:15
  • @sawdust some packets are unsolicited and others are request-response dialog for example the 138 bytes packet that I am having the problem with is unsolicited while the 10 bytes packet that is working are responses – Ahmed Fawzy Oct 18 '22 at 14:20

1 Answers1

1

You can't use XON/OFF flow control for binary data. The missing 0x11 byte is an XON that will be eaten by the serial driver on the receiving end. You have to use hardware flow control like RTS/CTS for binary data, but both ends and the cable must support it.

Jon Wyatt
  • 11
  • 1