PROBLEM:Serial port stop receiving in asychronous input using "select".

Jorge Ventura (ventu04@ibm.net)
Mon, 06 Sep 1999 18:29:47 +0000


[1.]Serial port stop receiving in asychronous input using "select".

[2.]The program has a set of descriptors (3) to wake-up the process
whenever an event ocurrs on each descriptor. One of them is a descriptor
from a serial port to wake-up the process when there is data to be read.
After a random time, the drive sudenly stops receiving the data. It
seems that the select() does not receive interrupts, that is how I see
the problem. I had conected a data analyzer in the serial port and the
electrycal interface is ok. I did tests with three computers, the first
one was my notebook, an Acer/TI Extensa 616/150 Mhz and the program
worked fine. The next was an ASUS motherboard (the production
environment) with a Intel/Celeron 266Mhz, the system failure as
descripted above. We changed the motherboard to another (ASUS) with
Intel/Pentium 450Mhz and the same problem happened.

[3.]Serial port, asynchronous, select.

[4.]Kernel version 2.2.9

[5.]No output Ooops available.

[6.]This is the routine to configure the serial port. The port name I
have been using is "/dev/ttyS0" or "/dev/ttyS1".

void config_ports(char *portname)
{
/* ---- Configura portas ---- */
fd_cua = open(portname, O_RDWR | O_NONBLOCK | O_SYNC | O_NOCTTY);
fprintf(stdout, "Configurando porta serial %s ... ", portname);

if (fd_cua < 0)
{
perror("Serial port error");
exit_nicely(conn);
}

/* -------------- Port settings ---------------- */
tcgetattr(fd_cua,&oldtio); /* save current port settings */
bzero(&newtio, sizeof(struct termios));

newtio.c_iflag = IGNBRK | IGNPAR;
newtio.c_oflag = 0;

newtio.c_cflag = B4800 | CS7 | PARENB | CLOCAL | CREAD;

/* set input mode , no echo,... */
newtio.c_lflag = 0;
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VTIME] = 0;

tcflush(fd_cua, TCIOFLUSH);
tcsetattr(fd_cua,TCSANOW,&newtio);

fprintf(stdout, "Ok\n");
}

This is the loop to wait the events where the problem happen.


while (!quit)
{
/* Set read operation */

fd_sock = PQsocket(conn);
maxfd = 0;
maxfd = max(maxfd, fd_cua);
maxfd = max(maxfd, fd_sock);
maxfd++;

FD_ZERO(&rfds);
FD_SET(fd_sock, &rfds);
FD_SET(fd_cua, &rfds);

/* Set excption operation */

FD_ZERO(&rfds_excpt);
FD_SET(fd_cua, &rfds_excpt);

t1 = time(NULL);

if (difftime(t1, t0) > 59)
{
init_gate_time();
send_current_time(t1);
t0 = t1;
}

/*
Fica no select aguardando tres eventos possiveis:
1) Timeout = 100 mSeg
2) Porta serial
3) Teclado
*/
tv_cua.tv_sec = 0;
tv_cua.tv_usec = TIMEOUT;

retval = select(maxfd, &rfds, NULL, &rfds_excpt, &tv_cua);

if (retval == -1)
perror("select() interrupted");

/* --- process serial input event --- */

if (FD_ISSET(fd_cua, &rfds))
{
port_handler();
continue;
}

/* --- process data base event --- */

if (FD_ISSET(fd_sock, &rfds))
{
db_handler(pnum);
}

/* --- Process timeout event --- */

if (tv_cua.tv_usec <= 0 || FD_ISSET(fd_cua, &rfds_excpt))
{
tcflush(fd_cua, TCIOFLUSH);
poll_next();
}
}

tcflush(fd_cua, TCIOFLUSH);
tcsetattr(fd_cua,TCSANOW,&oldtio);
close(fd_cua);
sprintf(query, "UNLISTEN rmon_gates;");
res = PQexec(conn, query);
PQclear(res);
PQfinish(conn);
close(hf);
}

[7.]

To bypass the problema what I did was: If after 2 seconds I do not
receive any data I consider that the problem happen again, close and
open the serial port to continue working. Its working in this way.

Thanks in advance

Jorge Ventura

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/