C# Mono SerialPort类有多坚固?

C# Mono SerialPort类有多坚固?,c#,mono,C#,Mono,我有一个应用程序,其中包括使用SerialPort与Digi XBee协调器无线电通信 此代码在.NET下的桌面上运行稳定 在Quark板和WindRiver Linux上运行Mono的情况下,由于校验和验证错误,我尝试接收和解码来自网络中其他无线电的消息时,失败率约为99% 我测试过的东西: 我对串行端口使用轮询,而不是事件,因为Mono不支持事件驱动的串行端口。因此,问题与事件无关 默认的USB协调器使用FTDI芯片组,但我换了一个原型板和一个丰富的USB到串行转换器,我看到了相同的故障率。

我有一个应用程序,其中包括使用SerialPort与Digi XBee协调器无线电通信

此代码在.NET下的桌面上运行稳定

在Quark板和WindRiver Linux上运行Mono的情况下,由于校验和验证错误,我尝试接收和解码来自网络中其他无线电的消息时,失败率约为99%

我测试过的东西:

  • 我对串行端口使用轮询,而不是事件,因为Mono不支持事件驱动的串行端口。因此,问题与事件无关
  • 默认的USB协调器使用FTDI芯片组,但我换了一个原型板和一个丰富的USB到串行转换器,我看到了相同的故障率。我认为这消除了FTDI驱动程序的问题
  • 我更改了代码,不再尝试双工通信。它不是发送就是接收。同样的错误
  • 我将代码更改为一次读取一个字节,而不是按传入数据包中的大小标识符大小的块来读取。同样的错误
  • 我在各种远程设备(智能插头、墙壁路由器、LTH)中看到了这一点,因此它不是特定于远程设备的
  • 来自其他设备的请求或未经请求的消息发生错误
  • 我查看了一些未通过校验和的原始数据包,手动计算得到了相同的结果,因此校验和计算本身是正确的
  • 查看数据时,我看到的似乎是数据包中间的数据包头(即数据包头中指示的长度)。这使我认为我“丢失”了一些字节,导致后续数据包被读入早期数据包
  • 同样,这在桌面上也可以正常工作,但为了完整性,这是接收器代码的核心(为了简洁起见,删除了错误检查):

    do
    {
    字节[]缓冲区;
    //找到数据包开始
    字节@字节=0;
    做
    {
    @字节=(字节)m_port.ReadByte();
    }while(@byte!=数据包分隔符);
    int read=0;
    while(读取<2)
    {
    read+=m_port.read(lengthBuffer,read,2-read);
    }
    var length=lengthBuffer.NetworkToHostUShort(0);
    //获取数据包数据
    缓冲区=新字节[长度+4];
    缓冲区[0]=数据包分隔符;
    缓冲区[1]=长度缓冲区[0];
    缓冲区[2]=长度缓冲区[1];
    做
    {
    读取+=m_端口读取(缓冲区,3+读取,(缓冲区长度-3)-读取);
    }而(读<(长度+1));
    m_frameQueue.Enqueue(缓冲区);
    m_frameReadyEvent.Set();
    }而(m_port.BytesToRead>0);
    
    我只能想到两个可能发生故障的地方——Mono SerialPort实现或位于USB堆栈上方的WindRiver串行端口驱动程序。我倾向于认为WindRiver有一个好司机

    更让人困惑的是,我们通过Mono在同一台设备上(在不同的应用程序中)运行Modbus串行,这可以正常工作几天,这在一定程度上证明了Mono的正确性

    其他人有没有使用Mono SerialPort的经验?它是固体的吗?片状的?你知道这里会发生什么吗

        m_port.Read(lengthBuffer, 0, 2);
    

    这是一个bug,你不能保证你能读到两个字节。只有一个是很常见的,串行端口很慢。必须使用Read()的返回值进行检查。请注意,在第二次使用中,您是如何正确操作的。除了循环,简单的替代方法是只调用ReadByte()两次。

    facepalm该位是我使用事件驱动代码时留下的,ReceiveThreshold为3,因此始终有3个字节可用。我已经盯着这段代码看了12个小时,一直在做
    Console.WriteLine
    调试(yay-Linux),并一直在讨论这个问题。我欠你一杯啤酒。一两个,本来已经很糟糕了。ReceiveThreshold无法工作,您的数据包分隔符检查很容易需要更多。糟糕的故障模式,得到一个坏字节,您将永远无法再次重新同步:)有趣。我猜是缓慢的硬件揭开了它的面纱——尽管它也总是在缓慢的WinCE设备上工作。
        m_port.Read(lengthBuffer, 0, 2);