rs485 on SBC84500

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hi

I'm trying to use the RS485/COM2 port on an embedded Axiom SBC84500 card
running kernel 2.4.26. I have configured the JP9,JP10,JP10 according to the
documentation but there is no output signal when writing to /dev/ttyS1.

I read somewhere that I should use ioctls to write to the port instead of
the standard write function.

Anybody can help ?

J.P. Frencia

Re: rs485 on SBC84500

Quoted text here. Click to load it

You might have to assert RTS in order to enable the RS-485
drivers.

Quoted text here. Click to load it

I really doubt that.  I've been doing serial stuff under Unix
for 15 years, and I've never heard of using ioctl() to write
data to a serial port.

--
Grant Edwards                   grante             Yow!  Yow! I'm having a
                                  at               quadraphonic sensation
We've slightly trimmed the long signature. Click to see the full one.
Re: rs485 on SBC84500
Quoted text here. Click to load it
I have. If a sufficient driver was never created, you end up using ioctl
to control the devices registers directly from user space. It simplifies
the work of the device developer in exchange for giving the end user a
headache.
If the device doesn't have a clean "port" into the linux realm (special
non 16C550 compliance for example) then it this might be the easy way to
get a board off the ground.
T.

Re: RS485/COM2 Error in SBC84500 documentation
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).

int OpenDevice (char* device)
{
  int fd;

  fd = open(device, O_RDWR | O_NOCTTY );
  if(fd<=0) {
    fprintf(stderr, "Error opening %s\n", device);
    exit(-1);
  }
  tcgetattr(fd,&oldtio); /* save current port settings */
  tcgetattr(fd,&newtio); /* get current port settings */
  newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
  // BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD does NOT work
  newtio.c_cflag &= ~PARENB;  /* no generation of parity bit */
  newtio.c_cflag &= ~CSTOPB;  /* 1 Stop bit */
  newtio.c_iflag &= ~INPCK;  /* no input parity check */
  newtio.c_iflag = IGNPAR;
  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;

  tcflush(fd, TCIFLUSH);
  tcsetattr(fd,TCSANOW,&newtio);
  return(fd);
}


Grant Edwards wrote:

Quoted text here. Click to load it


Re: RS485/COM2 Error in SBC84500 documentation
Quoted text here. Click to load it

Here's a *very* pedantic (but also very useful) commentary on your
code.

Quoted text here. Click to load it

That should be "if (fd < 0) {", because 0 is a valid fd.

Quoted text here. Click to load it

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.

Quoted text here. Click to load it

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);

Quoted text here. Click to load it

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.

Quoted text here. Click to load it

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? :-)

Quoted text here. Click to load it

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.

Quoted text here. Click to load it

Wow, that's a pretty hefty wait interval!

Quoted text here. Click to load it

You might want to change that to TCIOFLUSH, so that both input
and output are flushed before continuing.

Quoted text here. Click to load it

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.)

Quoted text here. Click to load it

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;

Quoted text here. Click to load it

--
Floyd L. Davidson           <http://web.newsguy.com/floyd_davidson
Ukpeagvik (Barrow, Alaska)                         snipped-for-privacy@barrow.com

Re: RS485/COM2 Error in SBC84500 documentation
Hi

Thanks for your comments a bit pedantic ;) but useful to learn. I think
there is a lack of material on serial port programming for newbies. Here is
the 2 useful link I have found:

- http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single
Serial-Programming-HOWTO.html

- http://www.easysw.com/~mike/serial/serial.html

It would be fine if you could post some others

J.P. Frencia


Floyd L. Davidson wrote:

Quoted text here. Click to load it


Re: RS485/COM2 Error in SBC84500 documentation

Quoted text here. Click to load it

That last one is the one to study.

The "Serial Programming HOWTO" contains a lot of sample code
isn't "right", and it's completely missing info on several
topics.

There's a lot of bad serial port code out there (include code I
wrote) that takes shortcuts and will probably work 90% of the
time, but it will fall down when presented with certains cases.

Mike's "Serial Programming Guide for POSIX Operating Systems"
shows the right way to do things, with good explinations of
_why_ the right way is the right way.

--
Grant Edwards                   grante             Yow!  .. I
                                  at               feel... JUGULAR...
We've slightly trimmed the long signature. Click to see the full one.
Re: RS485/COM2 Error in SBC84500 documentation
Quoted text here. Click to load it

That one is unfortunately filled with bugs.  Or at least the
code examples it has are.  If you'd like some better code to go
along with the text, I've posted several example ways to write a
"terminal program" similar to the one used for the HOWTO.

  http://web.newsguy.com/floyd_davidson/code /

The one you want to look at specifically is "Terminal Programs".

Quoted text here. Click to load it

That one is the best reference available on line as far as I know.

--
Floyd L. Davidson           <http://web.newsguy.com/floyd_davidson
Ukpeagvik (Barrow, Alaska)                         snipped-for-privacy@barrow.com

Site Timeline