Re: RS485/COM2 Error in SBC84500 documentation
From: Floyd L. Davidson (floyd_at_barrow.com)
Date: 06/20/05
- Next message: neer: "PCI Device Driver on SBC 104+ with White Dwarf Linux"
- Previous message: linnix: "Re: Embedded Platform"
- In reply to: Frencia: "Re: RS485/COM2 Error in SBC84500 documentation"
- Next in thread: Frencia: "Re: RS485/COM2 Error in SBC84500 documentation"
- Reply: Frencia: "Re: RS485/COM2 Error in SBC84500 documentation"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 20 Jun 2005 12:51:32 -0800
Frencia <jean.pierre.frencia@wanadoo.fr> wrote:
>Hi
>
>There is an error in the SBC84500 documentation concerning RS485/COM2 pins
>assignment.
>The signal is between pin 1 (DATA-) and pin 2 (DATA+) instead of pin 1 and
>pin 3 as stated page 29 of the documentation.
>
>I also have removed CRTSCTS flag when tuning the termios.
>
>Here is my OpenDevice routine (if it could be helpful for somebody else).
Here's a *very* pedantic (but also very useful) commentary on your
code.
>int OpenDevice (char* device)
>{
> int fd;
>
> fd = open(device, O_RDWR | O_NOCTTY );
> if(fd<=0) {
That should be "if (fd < 0) {", because 0 is a valid fd.
> fprintf(stderr, "Error opening %s\n", device);
> exit(-1);
The argument for exit() is an int, but its value is taken as an
unsigned character. Hence, -1 is not -1, but 255.
Useful arguments are in the range 0 to 255.
> }
> tcgetattr(fd,&oldtio); /* save current port settings */
> tcgetattr(fd,&newtio); /* get current port settings */
You could just as well save the second function call, and
do
newtio = oldtio;
But at that point there is another problem. POSIX says that the
above is the one and only correct way to initialize a termios
structure. (Which rules out using something like memset() to
clear it entirely.) But, that also means you *must* set each
and every element of the structure to an appropriate value for
your application, because whatever just happens to be in "oldtio"
might not be compatible with your app. That sounds easy, but
POSIX doesn't specify _everything_ that might be there! It says
certain things must exist, but each implementation is allowed to
add non-POSIX specified members to termios. So, for a portable
program, it is *impossible* to know how to initialize termios!
It happens that Linux has such an addition to termios, the
c_line member, which is not POSIX, does not exist in any other
OS, and if set to the wrong value will cause a port to appear
to be dead.
So you are left with, in my opinion, two options. One is to
use something like this:
#if __linux__
#include <sys/ioctl.h> /* defines N_TTY */
newtio.c_line = NTTY; /* or skip the header, and set it to 0 */
#endif
*and* make sure that you set each and every POSIX member of
the termios structure.
The other way, which is not POSIXly correct, is easier and
more likely to always be right!
memset(&newtio, 0, sizeof newtio);
> newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
> // BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD does NOT work
You probably shouldn't put the BAUDRATE there either; and
regardless of whether it is there or not, you should use
cfsetispeed() and cfsetospeed() to set the bitrate.
> newtio.c_cflag &= ~PARENB; /* no generation of parity bit */
> newtio.c_cflag &= ~CSTOPB; /* 1 Stop bit */
The above are unnecessary. You properly *set* (using '=') only
some of the bits above, and all others are cleared. Clearing
them again won't make the twice as cleared, eh? :-)
> newtio.c_iflag &= ~INPCK; /* no input parity check */
> newtio.c_iflag = IGNPAR;
That doesn't make sense either. Just do the second line, and it
will also do the first at the same time. I'm not sure what is
implemented in the driver you are using, but commonly for the
c_iflag on RS-232 ports one would also set IGNBRK.
> newtio.c_oflag = 0;
>
> /* set input mode (non-canonical, no echo,...) */
> newtio.c_lflag = 0;
>
> newtio.c_cc[VTIME] = 10;
> newtio.c_cc[VMIN]= 0;
Wow, that's a pretty hefty wait interval!
> tcflush(fd, TCIFLUSH);
You might want to change that to TCIOFLUSH, so that both input
and output are flushed before continuing.
> tcsetattr(fd,TCSANOW,&newtio);
You should check this for an error. But also note that if it
returns -1, that means *nothing* worked. And if anything at all
was set as requested, it will return 0. That means most of it
might be other than what you expect, and the error return won't
indicate it. (The only way to know for sure, is obnoxious...
you'd have to use tcgetattr() again, and compare what you get
to the newtio struct, and even that isn't easy because the bitrate
bits won't be the same and have to be compared separately from
the rest of the struct.)
> return(fd);
There is no need to put parens around fd in the return
statement, though it doesn't hurt anything. (I said it was a
pedantic commentary... :-)
return fd;
>}
-- Floyd L. Davidson <http://web.newsguy.com/floyd_davidson> Ukpeagvik (Barrow, Alaska) floyd@barrow.com
- Next message: neer: "PCI Device Driver on SBC 104+ with White Dwarf Linux"
- Previous message: linnix: "Re: Embedded Platform"
- In reply to: Frencia: "Re: RS485/COM2 Error in SBC84500 documentation"
- Next in thread: Frencia: "Re: RS485/COM2 Error in SBC84500 documentation"
- Reply: Frencia: "Re: RS485/COM2 Error in SBC84500 documentation"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|