0

I have writen some Linux program to comunicate my device. I have "same" my program for Windows ("same" because of it's same logic). I'm using 8N2 data frame format @ 9600 bps, with neither software (XOn/XOff) nor hardware (RTS/CTS) flow control. I don't use DTR, DCD, RI, DSR pins of RS-232 9-pin D-sub. I use only RX and TX pins to communicate with my device. In Linux I have this part of code:

 struct termios PortOpts, result;
 int fd; /* File descriptor for the port */

/* Configure Port */
 tcgetattr(fd, &PortOpts);
 // BaudRate - 9600
 cfsetispeed(&PortOpts, B9600);
 cfsetospeed(&PortOpts, B9600);
 // enable reciever and set local mode, frame format - 8N2, no H/W flow control
 PortOpts.c_cflag &= (~(CLOCAL | CREAD | CSIZE | CSTOPB));
 PortOpts.c_cflag |= ((CLOCAL | CREAD | CS8 | CSTOPB) & (~PARENB));
 PortOpts.c_cflag &= (~CRTSCTS);
// PortOpts.c_cflag &= ~PARENB
// PortOpts.c_cflag |= CSTOPB
// PortOpts.c_cflag &= ~CSIZE;
// PortOpts.c_cflag |= CS8;
 // no parity check, no software flow control on input
 PortOpts.c_iflag |= IGNPAR;
 PortOpts.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY | INPCK);
 // raw data input mode
 PortOpts.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
 // raw data output
 PortOpts.c_oflag &= ~OPOST;
 // setting timeouts
 PortOpts.c_cc[VMIN] = 1; // minimum number of chars to read in noncanonical (raw mode)
 PortOpts.c_cc[VTIME] = 5; // time in deciseconds to wait for data in noncanonical mode (raw mode)

 if (tcsetattr(fd, TCSANOW, &PortOpts) ==  0) {
    tcgetattr(fd, &result);
    if ( (result.c_cflag != PortOpts.c_cflag) ||
         (result.c_oflag != PortOpts.c_oflag) ||
         (result.c_iflag != PortOpts.c_iflag) ||
         (result.c_cc[VMIN] != PortOpts.c_cc[VMIN]) ||
         (result.c_cc[VTIME] != PortOpts.c_cc[VTIME]) ) {
        perror("While configuring port1");
        close(fd);
        return 1;
    }
 } else {
    perror("While configuring port2");
    close(fd);
    return 1;
 };

File descriptor 'fd' is for '/dev/ttyS0' device. I get that message: While configuring port2: Input/output error I have a laptop, though I don't have any serial ports except for USB. Is this a reason? I run program as 'root'.

Sorry for my broken English.

dsolimano
  • 8,870
  • 3
  • 48
  • 63
Sergey Kanaev
  • 570
  • 5
  • 18
  • The obvious question is "What is the value of `fd`?" That is, did you check the return value from the `open()`? Why are you not checking the return value of `tcgetattr()`? For a simpler code example using `cfmakeraw()`, see http://stackoverflow.com/questions/12437593/how-to-read-a-binary-data-over-serial-terminal-in-c-program/12457195#12457195 – sawdust Mar 04 '13 at 01:29
  • @sawdust fd is 3 for this moment. Device file is opened just ok. I've read manual about `cfmakeraw()` but it will make 8N1 frame format. Sure thing it's not a big deal about how many stop bits there are when you have to transmit no more than 1 byte at a time, but it is fundamental. You were right. I've got the same error while getting serial port paramters. So this is because of there is no physical device? – Sergey Kanaev Mar 04 '13 at 01:38
  • If you are using a USB-RS232 adapter, then issue shell command `ls /dev/ttyUSB*`. Use that device name for `open()` instead of `/dev/ttyS0`. It is very rare for modern UARTs or USARTs to require two stop bits. I (and many others) use 1 stop bit for 115200 baud with zero or minimal intercharacter gaps without any issues. Typical reason for more than 1 stop bit is inaccurate baud rate generator. – sawdust Mar 04 '13 at 01:51
  • @sawdust I don't have any adapters. I need to check my program for it is running ok (at least pre-transmition block). Thanks for the tip about stop bits. I'll try using 1 stop bit. – Sergey Kanaev Mar 04 '13 at 02:06
  • I've been writing drivers for decades, and do not see how you can use actual system calls with hardware that does not exist. The `open()` should have failed; that's a device driver that is too forgiving. If there is no device, then all system calls for I/O and device control have to be bypassed & replaced with simulated functions. – sawdust Mar 04 '13 at 02:18
  • @sawdust - about hardward that doesn't exist; the serial port in Linux doesn't know if there's actual hardware attached to the serial port. And since most mother boards have a serial port built-in even if there is no hardware connected, the kernel will talk to it. If there just is no serial port controller on the system, that's another point; the kernel boot messages (visible with dmesg) can tell if a serial port was found. – ash Aug 26 '13 at 20:51
  • @ash - I don't understand the point you are trying to make. You seem to be overusing the word `serial port` to mean different things like the (software) device driver and the hardware(?). The *"serial port controller"* is usually the hardware device called a UART. – sawdust Aug 27 '13 at 03:36
  • @sawdust - it felt like it wasn't clear as it came out. I'll try again; note this is related to the point that the open() should have failed... if there is serial hardware (a UART) in the system, the kernel will talk to it. Not having that connected to any external hardware - serial devices or even cables - will not cause open() of the device driver to fail in that case. And, even systems that do not have a serial port on the outside may have a UART on the inside. Hope that clarifies. – ash Aug 27 '13 at 03:48

1 Answers1

1

Can you run strace on the program; that will give more specifics of just where the IO error is occurring.

One thing to keep in mind - errno doesn't get reset, so the actual error could be from any system call before the perror.

ash
  • 4,867
  • 1
  • 23
  • 33