什么导致Mono下的SerialPort.Write零星错误?

时间:2015-10-25 00:00:58

标签: c# linux mono serial-port timeoutexception

我在Linux下使用USB连接(FTDI)和Mono下的Arduino Nano。这主要是有效的,但过了一段时间,我在一个看似随机的时间得到一个试图写入SerialPort的TimeoutException。显然(参见the FIXME和关联的bug report),Write中的任何错误都会导致TimeoutException,并且没有时间延迟,所以我认为假设它实际上不是超时,但只是一个错误。

单声道代码:

// FIXME: this reports every write error as timeout
if (write_serial (fd, buffer, offset, count, write_timeout) < 0)
    throw new TimeoutException("The operation has timed-out");

Here(参见write_serial)是被调用的Mono包装器,它似乎将任何错误结果从“poll”或“write”转换为简单的-1错误结果。

Mono Helper:

int
write_serial (int fd, guchar *buffer, int offset, int count, int timeout)
{
    struct pollfd pinfo;
    guint32 n;

    pinfo.fd = fd;
    pinfo.events = POLLOUT;
    pinfo.revents = POLLOUT;

    n = count;

    while (n > 0)
    {
        ssize_t t;

        if (timeout != 0) {
            int c;

            while ((c = poll (&pinfo, 1, timeout)) == -1 && errno == EINTR)
                ;
            if (c == -1)
                return -1;
        }       

        do {
            t = write (fd, buffer + offset, n);
        } while (t == -1 && errno == EINTR);

        if (t < 0)
            return -1;

        offset += t;
        n -= t; 
    }

    return 0;
}

我从Windows / .NET到同一设备进行通信并使用相同的写代码时没有问题(您将在下面看到)。

如果不编写一些广泛的C测试,我希望能够重现与当前代码相同的IO模式和时序,这让我有点不知道如何诊断它。有端口嗅探器,但这只会捕获数据,而不是诊断和错误。有没有办法在Linux内核中捕获并记录IO错误?

我的代码很简单。以下是相关摘录:

    _port = new SerialPort(portName, Configuration.BaudRate);
    _port.NewLine = "\n";
    _port.ReadTimeout = Configuration.StartupCommandTimeout; // 7000ms
    _port.WriteTimeout = Configuration.StartupCommandTimeout;
    _port.Open();

    _port.WriteLine(command);

这总是远离主线程,但可能并不总是出现在构造,读取和写入端口的同一线程上。

使用Mono版本3.2.8,虽然下面的代码来自Master,但似乎没有改变。我在ARM上运行Ubuntu 15.10。

1 个答案:

答案 0 :(得分:0)

在我的控制系统中,我有许多线程同时执行。通过增加线程优先级(ThreadPriority.AboveNormal)给为串口提供服务的actor(本质上是线程),我似乎已经最小化或可能已经消除了这个问题。也许Linux对串口服务饥饿问题比Windows更敏感,或者它是不同的硬件。