简体   繁体   English

Mono SerialPort类有多稳固?

[英]How solid is the Mono SerialPort class?

I have an application that, among other things, uses the SerialPort to communicate with a Digi XBee coordinator radio. 我有一个应用程序,除其他外,使用SerialPort与Digi XBee协调器无线电通信。

The code for this works rock solid on the desktop under .NET. 这个代码在.NET下的桌面上运行稳定。

Under Mono running on a Quark board and WindRiver Linux, I get about a 99% failure rate when attempting to receive and decode messages from other radios in the network due to checksum validation errors. 在Quo板和WindRiver Linux上运行的Mono下,由于校验和验证错误,在尝试接收和解码来自网络中其他无线电的消息时,我的失败率大约为99%。

Things I have tested: 我测试的东西:

  1. I'm using polling for the serial port, not events, since event-driven serial is not supported in Mono. 我正在使用轮询来进行串口,而不是事件,因为Mono不支持事件驱动的串行。 So the problem is not event related. 所以这个问题与事件无关。
  2. The default USB Coordinator uses an FTDI chipset, but I swapped out to use a proto board and a Prolific USB to serial converter and I see the same failure rate. 默认的USB协调器使用FTDI芯片组,但我换掉使用原型板和Prolific USB转串口转换器,我看到相同的故障率。 I think this eliminates the FTDI driver as the problem. 我认为这消除了FTDI驱动程序的问题。
  3. I changed the code to never try duplex communication. 我改变了代码,从不尝试双工通信。 It's either sending or receiving. 它发送或接收。 Same errors. 同样的错误。
  4. I changed the code to read one byte at a time instead of in blocks sized by the size identifier in the incoming packet. 我将代码更改为一次读取一个字节,而不是按传入数据包中的大小标识符大小调整的块。 Same errors. 同样的错误。
  5. I see this with a variety of remote devices (smart plug, wall router, LTH), so it's not remote-device specific. 我看到了各种远程设备(智能插头,墙壁路由器,LTH),因此它不是特定于远程设备的。
  6. The error occurs with solicited or unsolicited messages coming from other devices. 来自其他设备的请求或未经请求的消息会发生此错误。
  7. I looked at some of the raw packets that fail a checksum and manual calculation gets the same result, so the checksum calculation itself is right. 我查看了一些未通过校验和的原始数据包,并且手动计算得到了相同的结果,因此校验和计算本身是正确的。
  8. Looking at the data I see what appear to be packet headers mid-packet (ie inside the length indicated in the packet header). 查看数据,我看到在数据包中间看起来像是数据包标头(即在数据包标头中指示的长度内)。 This makes me think that I'm "missing" some bytes, causing subsequent packet data to be getting read into earlier packets. 这让我觉得我“丢失”了一些字节,导致后续的数据包数据被读入早期的数据包。

Again, this works fine on the desktop, but for completeness, this is the core of the receiver code (with error checking removed for brevity): 同样,这在桌面上工作正常,但为了完整性,这是接收器代码的核心(为简洁起见,删除了错误检查):

do
{
    byte[] buffer;

    // find the packet start
    byte @byte = 0;

    do
    {
        @byte = (byte)m_port.ReadByte();
    } while (@byte != PACKET_DELIMITER);

    int read = 0;

    while(read < 2)
    {
        read += m_port.Read(lengthBuffer, read, 2 - read);
    }

    var length = lengthBuffer.NetworkToHostUShort(0);

    // get the packet data
    buffer = new byte[length + 4];

    buffer[0] = PACKET_DELIMITER;
    buffer[1] = lengthBuffer[0];
    buffer[2] = lengthBuffer[1];

    do
    {
       read += m_port.Read(buffer, 3 + read, (buffer.Length - 3) - read);
    } while (read < (length + 1));

    m_frameQueue.Enqueue(buffer);
    m_frameReadyEvent.Set();
} while (m_port.BytesToRead > 0);

I can only think of two places where the failure might be happening - the Mono SerialPort implementation or the WindRiver serial port driver that's sitting above the USB stack. 我只能想到可能发生故障的两个地方 - Mono SerialPort实现或位于USB堆栈上方的WindRiver串行端口驱动程序。 I'm inclined to think that WindRiver has a good driver. 我倾向于认为WindRiver有一个好的驱动力。

To add to the confusion, we're running Modbus Serial on the same device (in a different application) via Mono and that works fine for days, which somewhat vindicates Mono. 为了增加混乱,我们通过Mono在同一台设备上(在不同的应用程序中)运行Modbus Serial,并且可以正常工作几天,这在某种程度上证明了Mono。

Has anyone else got any experience with the Mono SerialPort? 有没有其他人有使用Mono SerialPort的经验? Is it solid? 它结实吗? Flaky? 片状? Any ideas on what could be going on here? 关于可能会发生什么的任何想法?

    m_port.Read(lengthBuffer, 0, 2);

That's a bug, you have no guarantee whatsoever that you'll actually read two bytes. 这是一个错误,你无法保证你实际上会读到两个字节。 Getting just one is very common, serial ports are slow. 只获得一个常见,串口很慢。 You must use the return value of Read() to check. 必须使用Read()的返回值进行检查。 Note how you did it right in your second usage. 请注意您在第二次使用时是如何做到的。 Beyond looping, the simple alternative is to just call ReadByte() twice. 除了循环之外,简单的替代方法是只调用两次ReadByte()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM