Reputation: 744
I am opening serial port using following function
int open_port (unsigned char * port)
{
int fd = open(port,O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
{
return PORT_ERR;
}
else
{
struct termios new_termios;
struct termios orig_termios;
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
cfmakeraw(&new_termios);
cfsetispeed(&new_termios,B9600);
cfsetospeed(&new_termios,B9600);
tcsetattr(fd, TCSANOW, &new_termios);
return fd;
}
}
I am running the program on Cubieboard2 with Debian (raspberrypi) distribution. When I run the program manually, it works fine. But when the program is launched on boot by init.d script, it runs properly and performs other tasks (reading and writing files) well but it does not read any data sent on serial port.
lsof /dev/ttyUSB1
also shows that the port is being used by my program. Any ideas?
Upvotes: 2
Views: 269
Reputation: 17067
You should initialize the termios structure more completely, e.g. cflags, VMIN and VTIME, as in this working code, or like this using the perror() syscall:
rc = tcgetattr(sfd, &tty);
if (rc < 0) {
perror("failed to get attr");
exit (-2);
}
savetty = tty; /* preserve original settings for restoration */
spd = B115200;
cfsetospeed(&tty, (speed_t)spd);
cfsetispeed(&tty, (speed_t)spd);
cfmakeraw(&tty);
tty.c_cc[VMIN] = 1; /* wait for at least 1 char */
tty.c_cc[VTIME] = 10; /* or 1 sec after a char */
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS; /* no HW flow control */
tty.c_cflag |= CLOCAL | CREAD;
rc = tcsetattr(sfd, TCSANOW, &tty);
if (rc < 0) {
perror("failed to set attr");
exit (-3);
}
You should also be testing every return code from all syscalls, especially when you encounter issues.
Looking over your code again, the first argument to tcgetattr() is obviously incorrect:
tcgetattr(0, &orig_termios);
Defensive coding (e.g. validating parameters and checking return calls) is helpful in catching these types of silly mistakes that can consume a lot of debugging time.
ADDENDUM
I think I understand why the code seemed to work in the first situation, when started "manually" from the shell.
The file descriptor value of 0 is the value of STDIN_FILENO.
So the tcgetattr(0, &orig_termios)
statement would retrieve the termios values for stdin. (Initially I assumed you always got an undetected error return, so the structure would be returned unmodified.) Presumably you executed this on an embedded system, where the console is a serial port (and the returned values for stdin are a serial port's).
When I ran this code on a PC, cflags is provided with the CREAD flag disabled, and that should have caused a problem later. Note that setting cflags was one of my recommendations. VMIN and VTIME are returned as 8 and 4 respectively, but those unusual values would not have been fatal like the CREAD flag. There are other unusual termios values from the stdin video console, and a few would be corrected by your (minimal) initialization code or, since non-canonical mode is used, most of the unusual values are irrelevant.
Upvotes: 1