Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct initialization sequence for Linux serial port

I wrote an application that must use serial ports on Linux, especially ttyUSB ones. Reading and writing operations are performed with standard select()/read() loop and write(), and there is probably nothing wrong in them, but initialization code (or absence of some part of it) damages something in the tty subsystem. Here it is:


  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);
  }

Another tcsetattr(_fd, TCSANOW, &_termios) sits in the destructor, but it is irrelevant.

With or without this termios initialization, strange things happen in system after the application exits. Sometimes plain cat (or hd) exits immediately printing nothing or same stuff each time, sometimes it is waiting and not displaying any of the data that is surely sent onto the port; and close() (read() too, but not every time) emits a strange WARNING to dmesg referring to usb-serial.c.

I checked the hardware and firmware tens of times (even on different machines) and I am sure it is working as intended; moreover, I stripped the firmware to just print same message over and over.

How can I use serial port without destroying anything? Thanks.

like image 856
whitequark Avatar asked Jun 05 '10 23:06

whitequark


People also ask

How do you initialize a serial port?

Click Devices and Hardware—>Serial Ports. The Serial Ports menu is displayed. Select the port to be initialized. The Serial Port window is displayed in Basic Detail mode.

How does Linux assign serial ports?

Linux uses ttySx for a serial port device name. For example, COM1 (DOS/Windows name) is ttyS0, COM2 is ttyS1, and so on. USB based serial ports might use a name such as ttySUSB0. All these devices are located under /dev/ directory.

How do I close a serial port in Linux?

To close the serial port, just use the close system call: close(fd);


1 Answers

Hitting a WARN_ON line might mean that you've hit a kernel bug. I know that there has been much work on improving the USB-serial driver lately; I suggest trying a newer kernel, and/or asking on the [email protected] mailing list.

like image 168
caf Avatar answered Oct 02 '22 19:10

caf