Что вызывает спорадическую ошибку в SerialPort.Write под Mono?

Я использую USB-соединение (FTDI) от Linux к Arduino Nano под Mono. Это в основном работает, но через некоторое время я получаю, по-видимому, случайное время, TimeoutException, пытаясь записать в SerialPort. Очевидно (см. FIXME и соответствующий отчет об ошибке), любая ошибка в 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");

Здесь (смотрите 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-тестов, которые, я надеюсь, будут воспроизводить те же шаблоны ввода-вывода и синхронизацию, что и мой текущий код. Есть снифферы портов, но это будет просто захватывать данные, а не диагностировать и выдавать ошибку. Возможно, есть способ отловить и записать ошибки ввода-вывода в ядре Linux?

Мой код довольно прост. Вот соответствующий фрагмент:

    _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, так как не изменился. Я использую Ubuntu 15.10 на ARM.

1 ответ

В моей системе управления у меня много потоков, выполняющихся одновременно. Давая повышенный приоритет потока (ThreadPriority.AboveNormal) субъекту (по существу, потоку), который обслуживает последовательный порт, я, кажется, минимизировал или, возможно, устранил проблему. Возможно, Linux более чувствителен к проблемам с нехваткой службы последовательного порта, чем Windows, или это различное оборудование.

Другие вопросы по тегам