Правильная последовательность инициализации последовательного порта Linux

Я написал приложение, которое должно использовать последовательные порты в Linux, особенно ttyUSB. Операции чтения и записи выполняются со стандартным циклом select()/read() и write(), и в них, вероятно, нет ничего плохого, но код инициализации (или отсутствие какой-то его части) что-то повреждает в подсистеме tty. Вот это:


  vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
    _fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
    if(_fd < 0) throw new io_error("cannot open port");

    // Serial initialization was written with FTDI USB-to-serial converters
    // in mind. Anyway, who wants to use non-8n1 protocol?

    tcgetattr(_fd, &_termios);

    termios tio = {0};
    tio.c_iflag = IGNPAR;
    tio.c_oflag = 0;
    tio.c_cflag = baud | CLOCAL | CREAD | CS8;
    tio.c_lflag = 0;

    tcflush(_fd, TCIFLUSH);
    tcsetattr(_fd, TCSANOW, &tio);
  }

еще один tcsetattr(_fd, TCSANOW, &_termios) сидит в деструкторе, но это не имеет никакого отношения.

С или без этой инициализации termios, странные вещи происходят в системе после выхода приложения. Иногда просто cat (или hd) немедленно выходит из печати ничего или того же материала каждый раз, иногда он ждет и не отображает какие-либо данные, которые, безусловно, отправляются на порт; и close() (read() тоже, но не каждый раз) издает странные WARNING в dmesg ссылаясь на usb-serial.c.

Я проверил оборудование и прошивки десятки раз (даже на разных машинах) и Я уверен, что он работает по назначению; более того, я снял прошивку, чтобы просто печатать одно и то же сообщение снова и снова.

как я могу использовать последовательный порт ничего не разрушая? спасибо.

5 ответов


удара WARN_ON строка может означает, что вы попали в баг ядра. Я знаю, что в последнее время было много работы по улучшению USB-последовательного драйвера; я предлагаю попробовать более новое ядро и / или попросить linux-usb@vger.kernel.org список рассылки.


Я не уверен, что не так с вашим фрагментом кода, но это может пригодиться, если вы его еще не видели:руководство по последовательному программированию для операционных систем POSIX

Мне пришлось сделать некоторые последовательный порт сопряжения совсем недавно и библиотека работало нормально, что может служить еще одним примером.


Так же, как Примечание действительно, ваша проверка ошибок на open не совсем правильно-условия ошибки сигнализируются возвращаемым значением -1. (0 является совершенно действительным fd, обычно подключенным к stdin.)


вы можете попробовать:

  vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
    _fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
    if(_fd < 0) throw new io_error("cannot open port");

    // Serial initialization was written with FTDI USB-to-serial converters
    // in mind. Anyway, who wants to use non-8n1 protocol?

    tcgetattr(_fd, &_termios);

-   termios tio;
+   termios tio;
+   memcpy(&tio, &_termios, sizeof(struct termios)); 

    tio.c_iflag = IGNPAR;
    tio.c_oflag = 0;
    tio.c_cflag = baud | CLOCAL | CREAD | CS8;
    tio.c_lflag = 0;

    tcflush(_fd, TCIFLUSH);
    tcsetattr(_fd, TCSANOW, &tio);
}

это делает его так, что любые неожиданные поля termios в вашей системе получите несколько разумных значений.


ОК. Это может быть не идеальным решением... определенно нет. Я просто выбросил конвертер FT232 (обжарил его, на самом деле) и использовал CP2102-based. Он просто работает сейчас (а также в 6 раз дешевле).