Re: Interrupt-driven serial comm for Linux ?



mpv <nospam@xxxxxxxxx> wrote:

"Jens Thoms Toerring" <jt@xxxxxxxxxxx> wrote in message
news:6aaojeF36mn16U1@xxxxxxxxxxxxxxxxxxxx

Strange. Would you be prepared to show your code? Otherwise
it seems to be a bit difficult to comment;-) If you do you may
also have a chance to get a reply by Floyd Davidson who's one
of *the* experts on dealing with serial port issues (which, un-
fortunately, is a bit difficult to get right, given the huge
number of possible settings where one can go wrong-:)

I am following Michael Sweet's tutorial to the letter.
I set up the port exactly as he describes:

if (!(fd = open("/dev/ttyS0",O_RDWR | O_NOCTTY | O_NDELAY)))
QMessageBox::critical(this, tr("QT4 Demo"),
tr("Could not open COM1"),
QMessageBox::Ok, QMessageBox::Ok);
fcntl(fd, F_SETFL, 0); // reset all statusflags
struct termios options;
tcgetattr(fd, &options); // set baud rate to 115200 bps
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag &= ~PARENB; // parity N
options.c_cflag &= ~CSTOPB; // no stopbit

That comment is does not reflect what you're doing, you set
1 stopbit instead of 2.

options.c_cflag &= ~CSIZE; // 8 databits
options.c_cflag |= CS8;
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag |= ~(ICANON | ECHO | ECHOE |ISIG); // Raw input

I am rather sure you meant '&=' here!

options.c_iflag &= ~(IXON | IXOFF | IXANY); // disable software flow
control
options.c_oflag &= ~OPOST; // Raw output
options.c_cc[VTIME] = 100; // 10 second time_out
tcsetattr(fd, TCSANOW, &options);

I can't even guess if the settings you made here for the
serial port are the ones you need. I often have seen the
recommendation to zero out all the option flags and really
rebuild them from scratch in order not to get nasty sur-
prises by forgetting to reset a bit or two.

I send out the command to the device like this :

if (write(fd,bufout,sizeof(bufout)) != sizeof(bufout))
QMessageBox::critical(this, tr("QT4 Demo"),
tr("Writing to COM1 failed"),
QMessageBox::Ok, QMessageBox::Ok);

when I then poll the inputbuffersize with:

ioctl(fd, FIONREAD, &bytes); // 15 bytes ????

it is already 15 bytes, I would have expected 97 bytes here.

What makes you sure 97 bytes should have arrived if the return
value tells you that there are just 15 to be read? Perhaps they
haven't arrived yet (or at least are not available for reading).

Actually, I never used ioctl() with FIONREAD. When I want to
determine if there's anything to read I call select() on the
file descriptor (which also gives me a chance to set a timeout
on how long I want to wait for data to become readable).

I can read these 15 bytes without any problem with:

if (read(fd,(char*) &Avs_Id,sizeof(Avs_Id)) < 0)

Read returns the number of bytes that got read and you shouldn't
throw away that information like that. The typical way to read
is calling it in a loop until you have read as many bytes as you
could expect to receive.

QMessageBox::critical(this, tr("QT4 Demo"),
tr("Reading from COM1 failed"),
QMessageBox::Ok, QMessageBox::Ok);
else SerialNum->setText(QString(Avs_Id.SerialNumber).left(9));

The 15 bytes are the correct bytes, the rest of the buffer is garbage bytes.

Looks not unreasonable to me, given that you got before the
information that there would be only 15 bytes to read. If you
would look at the return value of read() you could make sure
how many bytes in the buffer actually have been read in. Of
course, the rest of the buffer will be garbage.

On another point: you wrote that your "program did not start anymore".
when you tried to use libcssl. I don't know what you mean exactly
by this.

I am using QDevelop, and try to start the program in debugging mode (which
uses gdb)
The program compiles and links without warnings (aside from some unused
variables).
The main window is not even shown, nothing happens at all.
Looks like some incompatibility with QT.
I do not have much appetite to debug the startup sequences of a huge
application framework with a low level debugger.

Looks to me as if would be hanging in some loop. One way to find
out where about that happens is simply start the program in the
debugger and the press CTRL-C to make debugger stop and tell
you were it is.

You mentioned the dubious quality of serial port tutorials.
Even Michael Sweet's has only an example where he reads 'OK'#13#10 from a
modem, a full 4 bytes! He could of course have sent not just 'AT#13', but
'ATI#13', and that would have given a lot more input.
The input buffer itself is nowhere to be seen in the tutorial, it just
'should work' by reading from the file descriptor.
I have been using serial ports to read out lab equipment since 1980, under
many operating systems. It is very rare that serial comm 'just works'. Most
of the time there are nasty intricacies like interrupt handling/thread
priorities etc. Best to leave that to the experts. Why do you think there is
a healthy market for serial port libraries ? Why should linux be the
exception ?

Perhaps because there aren't that many "nasty intricacies" as
you expect;-) Once you have got the setup for the serial port
right (that's the real complicated part) you simple read from
the serial ports device file. You don't have to care about
interrupts etc. yourself since the driver for the serial port
already does all that for you. It simply is following the UNIX
paradigm of "everything is a file". If you want some data from
it you call read(). If you want to write something you call
write(). And if you want to know if there are data to be read
without blocking you call select(). So it makes no real diffe-
rence to e.g. reading from a normal file, the console, a socket
etc. All the "nasty intricacies" are being taken care of by the
driver for the serial port to make it lock just Like another file.

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@xxxxxxxxxxx
\__________________________ http://toerring.de
.



Relevant Pages

  • Re: WriteFile is sending screwy data to the Serial Port
    ... try putting it in a debugger and change to CreateFile on ... That will allow you to debug the code first, ... the debugger may have helped my sanity though, ... The serial port reads fine given the same settings (GENERIC_READ | ...
    (microsoft.public.windowsce.embedded.vc)
  • Re: 7.0-STABLE amd64 kernel trap during boot-time device probe
    ... problem still occurs with 7.0-STABLE (csup on 20080301). ... A trap triggering a panic is still a panic. ... anything once I got into the debugger. ... This means that the serial port is expecting to talk to a remote GDB ...
    (freebsd-stable)
  • Re: Connectivity problem with PB 5.0
    ... why it doesn't boot when uploaded from PB ... ... you still have upload image from PB using the ... have a serial cable attached to the serial port ... Debugger service map is set to none. ...
    (microsoft.public.windowsce.platbuilder)
  • Re: point-to-point protocol and pc data
    ... Posting from groups.google.com (or some web-forums) dramatically ... reduces the chance of your post being seen. ... A serial port doesn't have a hardware address ... machine hardware identifier. ...
    (comp.protocols.ppp)
  • sio / puc wedging on both -current and -stable
    ... shorts across the serial port *or* plug the serial port into a working ... I have a remote debugger setup and I can send a break and drop the unit ... but kernel debugging is a little beyond our skillset. ...
    (freebsd-current)