【问题标题】:What is causing sporadic error in SerialPort.Write under Mono?是什么导致 Mono 下 SerialPort.Write 中的零星错误?
【发布时间】:2015-10-25 00:00:57
【问题描述】:

我正在使用从 Linux 到 Mono 下的 Arduino Nano 的 USB 连接 (FTDI)。这主要是有效的,但过了一段时间,我在看似随机的时间得到了一个 TimeoutException,试图写入 SerialPort。显然(参见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 错误结果。

单声道助手:

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 错误?

我的代码非常简单。这是相关的sn-p:

    _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。

【问题讨论】:

  • 出于好奇,您发送到的那个 tty 的波特率是多少?
  • @RubertN, 9600 N, 8, 1 坚持使用 Arduino 的默认值,因为它们足以满足我的需要。接下来我将使用类似的软件堆栈,但使用不同的板(RPi2 而不是 Odroid XU4)。我差不多准备好了。
  • 啊..好的...不是速度问题...我使用了很多 32 位 ARM 板(即 STM32-FO 等...)并且从未遇到过问题波特率较低的单声道串行堆栈,但这从未在 Linux/ARM 架构上,仅限 x86_64。对于高速 tty(即 567k+ 波特/1.7uS,我们有一个 3rd-party C 库,我们将其用作 Mono 的 serial.c 对这样的非阻塞速度来说是一团糟......
  • $RobertN,所以你在 Mono 中将自己的 P/Invoke 层构建成 C 中的串行包装层?如果我绝望了,我可能会尝试这样做,但为了得到更好的错误似乎需要付出很多努力。
  • 是的,我们在第 3 方 $$$ linux 串行库上的 p/invoke 程序集,我们不打算从头开始编写,当您谈论 1uS 串行时间时,必须手动调整 c。您可以在您的 linux/arm 设置上编译单声道,还是安装二进制 pkgs(?),因为我可能有一些您可以尝试的 serial.c(和匹配的 c#)更新。

标签: c# linux mono serial-port timeoutexception


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 2022-10-17
    • 2013-09-10
    • 2015-03-04
    • 1970-01-01
    相关资源
    最近更新 更多