Mail Archives: cygwin/2001/02/08/12:40:52
Sylvain,
See my setup code below. As you will see, I don't use a wide variety of
settings, but it seems to function properly.
After the initiallization, in another function I do :
while(blah blah)
{
FD_ZERO(&rset);
/* Set up fd_set and call select. */
FD_SET(udp_socket_fd,&rset);
FD_SET(serial_fd,&rset);
maxfdp = MAX(udp_socket_fd,serial_fd) +1;
/* Now pend on our input file descriptors, until data is
available or unti we timeout. */
sel_ret = select(maxfdp, &rset, NULL, NULL, &sel_timeout);
/* Check if we timed out. If so, increment a counter; if not,
try to read data */
if(sel_ret == 0)
{
/* We timed out! */
/* Do some metrics, or something */
}
else
{
/* Check if we have Serial data to get */
if( FD_ISSET(serial_fd,&rset) )
{
/* Try to receive a message!
Note that 'data' available in the serial interface
does not mean that the whole message is available! */
msg_hndlr->buffer = receive_serial_data(serial_fd,
&msg_length);
/* Other stuff */
}
/* Other stuff */
}
} /* End while */
All before I read, because I don't want to block on read (I have other
things to do). If you are OK blocking, great, but you might try
changing to select'ing first just to see what happens. If that works, I
think there's some bug in either your port setup or in cygwin.
Inside receive_serial_data() is a bunch of stuff for message
syncronization, but all my reads are like:
read_bytes =
read(sfd,
&(av_ser_if_rx_state.tmp_len.tmp_bytes[4 - need_bytes]),
need_bytes);
or :
read_bytes = read(sfd,
av_ser_if_rx_state.write_ptr,
need_bytes);
after which I check if I got all the bytes I need, twiddle state, retry
reading in the new state, until completiong or a block. At block,
(read_bytes == 0), I jump out back to the while(loop) that does
select().
Below is the full function that I use to initialize the serial port.
You'll see I had some confusion on whether I needed to fctnl() or not to
get non-blocking behavior. It seems to never block as is.
HTH,
Eric Monsler
int init_serial_if(int port, char *parity, long baudrate)
{
int fd; /* The file descriptor returned from opening port */
byte *b_ptr; /* Byte addressing pointer for placing magic bytes
into structure */
int ii;
char * serialdevice;
long int baud_enum = B0;
/*
Set up serial device text based on port number
*/
#ifdef __CYGWIN__
if(port == 2)
{
serialdevice = "/dev/com2";
}
else if(port == 1)
{
serialdevice = "/dev/com1";
}
else
{
printf("Invalid port specified, trying port 1\n");
serialdevice = "/dev/com1";
}
#else
if(port == 2)
{
serialdevice = "/dev/ttyb";
}
else if(port == 1)
{
serialdevice = "/dev/ttya";
}
else
{
printf("Invalid port specified, trying port 1\n");
serialdevice = "/dev/ttya";
}
#endif
/*
Handle baud rate enumeration
*/
switch(baudrate)
{
case 300:
baud_enum = B300 ;
break;
case 1200:
baud_enum = B1200 ;
break;
case 2400:
baud_enum = B2400 ;
break;
case 9600:
baud_enum = B9600 ;
break;
case 19200:
baud_enum = B19200 ;
break;
case 38400:
baud_enum = B38400 ;
break;
case 57600:
baud_enum = B57600 ;
break;
case 115200:
baud_enum = B115200 ;
break;
default:
printf("Specified baudrate not recognized, using 9600!\n");
baud_enum = B9600;
}
/*
Now we know we have the correct parameters to use, proceed to
open port and write
*/
fd = open(serialdevice, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd <0) {perror(serialdevice); exit(-1); }
#if DEBUG
printf("Opening serial port %s returned: %d\n",serialdevice,fd);
#endif
tcgetattr(fd,&oldtio); /* save current port settings */
/* Start with old settings, then we'll modify */
newtio = oldtio;
/*
Now do the port setup to match what the EPLD is expecting
*/
/* Set baudrate */
cfsetispeed(&newtio,baud_enum);
cfsetospeed(&newtio,baud_enum);
/* Enable the receiver and set local. */
newtio.c_cflag |= (CLOCAL | CREAD);
if(strcmp(parity,"8N1") == 0)
{
/* Set 8 bit characters, no parity, 1 stop (8N1) */
newtio.c_cflag &= ~PARENB; /* Clear previous parity bits values */
newtio.c_cflag &= ~CSTOPB; /* Clear previous stop bits values */
newtio.c_cflag &= ~CSIZE; /* Clear previous charsize bits values
*/
newtio.c_cflag |= CS8; /* Set for 8 bits. */
}
else
{
printf("Unsupported parity selection, using 8N1.\n");
/* FIXME */
printf("Actually, only 8N1 supported at this time \n");
/* Set 8 bit characters, no parity, 1 stop (8N1) */
newtio.c_cflag &= ~PARENB; /* Clear previous parity bits values */
newtio.c_cflag &= ~CSTOPB; /* Clear previous stop bits values */
newtio.c_cflag &= ~CSIZE; /* Clear previous charsize bits values
*/
newtio.c_cflag |= CS8; /* Set for 8 bits. */
}
/* I think we want to disable hardware flow control. FIXME */
newtio.c_cflag &= ~CRTSCTS;
/* When we read, we want completely raw access */
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/* I think we want to disable software flow control. FIXME */
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
/* Set output filtering to raw. */
newtio.c_oflag &= ~OPOST;
/* Set readsize and timeout to some reasonable values, just to be safe
*/
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 0; /* nonblocking read */
/*
Now we can flush, and then make the control changes!
*/
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
/* Finally, on read, we want to NOT block, so we set this such that
reads return a 0 number of bytes read rather than blocking. */
#if 0
/* Should be reduntant with above controls */
if( fcntl(fd, F_SETFL, FNDELAY) == -1)
{
perror("Failed to set non-blocking read");
}
#endif
/*
Port all set up, ready to read and write data
*/
/*
Initialize our state control structures and internal constructs
*/
/* Snipped this from example */
return fd;
}
/*
For completeness, provide a function to close and restore the port
*/
void close_serial_if(int sfd)
{
/* Restore previous terminal settings */
tcflush(sfd, TCIFLUSH);
tcsetattr(sfd,TCSANOW,&oldtio);
/* Close file descriptor for port */
close(sfd);
}
--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple
- Raw text -