views:

443

answers:

2

Hi all,

I am using select call to communicate with an external subsystem (protocol for the same has been provided and implemented as a Qt thread) using serial port RS232. We do not have the hardware for the external systems and thus we have developed in house simulators using .Net 2.0 and C# to mimic the behavior of the underlying subsystem hardware. There are 5 different subsystem that communicate with our application. Every interface for the subsystem is implemented as a Qt thread. Since this isn't a real time application, and we do not have the actual hardware when we communicate using simulators, all systems do find for 24 hrs or so and after that the communication goes up and down and ultimately all communication breaks down, but when I restart the simulator machine without closing my application, things become alright. Why does this happen?

My guess is, since .Net/C# isn't a real time framework and also after the simulators have run for 24 hrs, the data sending rates start to slow down, that there is clogging of serial ports; the restart flushes everything and thus everything returns to normal. This is just a guess. If someone has a better opinion, do share it. Note, the simulators have been made by a different team of .Net guys.

Note: Each protocol has different data rates, 1 Hz, 5 Hz, 10 Hz.

There is one system which just doesn't resume communication even after simulator for the same is restarted after reboot. The port configuration for this system is

SetPortConfiguration()
{
    tcgetattr(Fd,&mOldtio); 
       mNewtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD | CRTSCTS;
       mNewtio.c_iflag = 0; //setting the input flag to icrnl causes a blank frame to be displayed after every frame.
       mNewtio.c_oflag = 0;
       mNewtio.c_lflag =ICANON;
       mNewtio.c_cflag &=~PARENB;
       mNewtio.c_cflag &= ~CSTOPB;
        //mNewtio.c_cflag &= ~HUPCL;  //added on 24/3/09
       mNewtio.c_cc[VEOL]=0; //setting VEOL to '\r' or '\n' causes a blank frame to be displayed after every frame.
       mNewtio.c_cc[VKILL] = 0;     /* @ */
       mNewtio.c_cc[VSTART] = 0;     /* Ctrl-q */
       mNewtio.c_cc[VSTOP]  = 0;     /* Ctrl-s */
       mNewtio.c_cc[VMIN]=0;
       mNewtio.c_cc[VTIME]=0;
       tcflush(Fd, TCIFLUSH);
       tcflow(Fd,TCION);
       tcsetattr(Fd,TCSANOW,&mNewtio);
}

Also there is a reset port function :

ResetPort()
{
    tcflush(Fd, TCIFLUSH); //flush all data received but not read

    tcflow(Fd,TCIOFF); //transmits a STOP character, which stops the terminal device from transmitting data to the system 
    tcsetattr(Fd, TCSANOW, &mOldtio);//set the old terminal settings

    ClosePort(); //close port
    OpenPort(mStrPortNo); //open the port specified by port number and in read mode
    SetPortConfiguration();
}

If there is any break in communication, I call the ResetPort function which closes and reopens the port. This solves the problem in all cases except one system say XYZ. XYZ system sends data in NMEA format with each packet as a string of data terminated with a Carriage Return, LineFeed combination.

Any idea fellows as to what may be the problem?

+1  A: 

The ".Net real time" bit is a red herring. Serial ports are so slow that an 8086 could control them. Any modern CPU will likely have cycles to spare, even at 115200 Baud. Even if it didn't, the depth of RS232 buffers is typically measured in milliseconds not hours.

"Clogging" of serial ports is pushing physical analogies way too far.

It's hard to figure out exactly what is causing your problem as you haven't actually told us what that is. "Breaks down" isn't something we can solve. Bytes lost, writes timing out - that's the kind of concrete behavior we can address.

MSalters
A: 

Hi all,

I have solved the problem. My apologies if I couldn't get across my point. Earlier we were using signal handling for serial interfacing with each system connected to a dedicated serial port, this design was flawed from start as signal handler in our case was way too complex. Ideally a signal handler should just set some flags, it shouldn't involve function calls as there can be synchronisation issues to be handled, then it snowballs into a synchronisation nightmare which is hard to debug as I found out in my application. This design leads to loss in packets coming from the serial ports. To deal with this situation we were using reset port function which was a crude way to rectify the packet loss problem. I dropped the signal handler and used select call for individual systems. But didn't drop reset port which was a part of earlier design. On debugging, I found resetport a spurious function and dropped it. Voila!! everything works perfect now. On record, my advice to anyone who is using serial communication on a linux paltform to use select system call. You are absolved of handling the details of serial communication and just concentrate on processing the incoming packets.

I hope this solution will help all those who are working on serial communication on linux/unix platforms. There isn't much literature on the subject and all search on the net will lead you to some documents by mike and sweet which though good aren't much help in practical applications. I acknowledge the help offered by all members of stackoverlow which gave me unthinkable perspectives to look at the problem at hand. Thanks guys, cheers!!!!!!

rocknroll