Problem detecting and reacting to serial break
Paul Thornton
prt at prt.org
Sat Aug 14 17:30:59 UTC 2010
Hi,
I'm working on a small piece of code that reads a data stream from the
serial port, putting it into a buffer for processing later - for those
interested, it is receiving DMX512 lighting control data - but I'm
having trouble with the detection of a break condition on the serial
line. I'd appreciate any suggestions from anyone.
I'm using 8.0-RELEASE with uftdi and ucom driving the serial port.
The format of this data is very simple - a break is sent, followed by
513 bytes of useful information; then after some arbitrary delay another
break, and the next 513 bytes. So, I think, easy to do this - just wait
for a break and read away.
My problem is that despite setting the port up (as I think) correctly,
the break seems to be ignored at a driver level and it appears as data
byte of 0x00 (what I'd expect to see if IGNBRK was set). This is no
good as I have no way to know where I am in the chunk of 513 bytes of
data, so can't synchronize at all.
I have the following code setting up my serial port:
tcgetattr(fd, &options);
printf("before: c_iflag=%x c_oflag=%x c_cflag=%x c_lflag=%x\n",
options.c_iflag, options.c_oflag,
options.c_cflag, options.c_lflag);
options.c_iflag = (BRKINT | IGNPAR);
options.c_oflag = 0;
options.c_cflag = (CLOCAL | CREAD | CS8 | CSTOPB);
options.c_lflag = 0;
options.c_cc[VMIN] = 513;
options.c_cc[VTIME] = 0;
if (cfsetispeed(&options, BAUDRATE) < 0) {
perror("cfsetispeed");
exit(1);
}
if (cfsetospeed(&options, BAUDRATE) < 0) {
perror("cfsetospeed");
exit(1);
}
if (tcsetattr(fd, TCSANOW, &options) < 0) {
perror("tcsetattr");
exit(1);
}
/* debug test - did anything change? */
tcgetattr(fd, &options);
printf("after: c_iflag=%x c_oflag=%x c_cflag=%x c_lflag=%x\n",
options.c_iflag, options.c_oflag,
options.c_cflag, options.c_lflag);
The debug output shows my set is doing what I expect it to:
before: c_iflag=2005 c_oflag=3 c_cflag=cf00 c_lflag=443
after: c_iflag=6 c_oflag=0 c_cflag=8f00 c_lflag=0
So according to the documentation, the effect of the break should be to
flush the input and output buffers, and send a SIGINT to my process. The
buffer doesn't seem to get flushed, and I don't get sent the SIGINT.
The data I'm getting in my buffer is valid, apart from the fact that I
can't tell where byte 1 is - and every time I run the test program the
location of byte 1 changes arbitrarily depending on what was in the
receive buffer.
Have I missed something here, or is there any other way that I can
detect the presence of the break out-of-band? I cannot make any
assumptions about the 513 bytes that I'm receiving and any combination
of data may be present in there.
Many thanks,
Paul.
More information about the freebsd-hackers
mailing list