Hi folks,

I'm working on an application that runs under uClinux on a custom board (arm7) and deals with serial port. It's kind of a data acquisition app that uses serial port to yield the data from remote sensors.

Application uses "request->response" technique: sends an appropiate command to the sensors periodically and waits response from them. Sensors work fine and respond within 15-25 ms right after they get the command. But application doesn't work as we want. The problem is that the time between "write" syscall (write to serial port) and the moment when the data physically appears on a pin is huge - up to 200 ms and it varies from one cycle to another. And it's unacceptable for us.

You may find the configuration of serial port which i'm using at the moment. I have only 2 questions to the whole maillist:

1. how to decrease this latency down to ... 50 ms (i guess, would be fine)?
2. what information do you want me to provide to help fixing this issue?


Thank you!

--
Agava Design Bureau
620026, Russia, Yekaterinburg, Bazhova str. 174
tel./fax. +7 (343) 262-92-76, 262-92-78, 262-92-87
http://kb-agava.ru

int set_up_comms( char *device, int baud_i, 
                  char *parity, int stopbits, int readtimeout )
{
        int ttyfd;
        struct termios settings;
        struct serial_struct ser;
        speed_t baud_rate;
        
        /* get integral part (in seconds) of MODBUS reading timeout */
        read_timeout_s  = readtimeout / 1000;

        /* get fractional part (in microseconds) of MODBUS reading timeout */
        read_timeout_us = (readtimeout - read_timeout_s * 1000) * 1000;
        
#ifdef DEBUG
        fprintf( stderr, "opening %s\n", device );
#endif

        switch( baud_i )
        {
                case 110:
                        baud_rate = B110;
                        char_interval_timeout = TO_B110;
                        break;
                case 300:
                        baud_rate = B300;
                        char_interval_timeout = TO_B300;
                        break;
                case 600:
                        baud_rate = B600;
                        char_interval_timeout = TO_B600;
                        break;
                case 1200:
                        baud_rate = B1200;
                        char_interval_timeout = TO_B1200;
                        break;
                case 2400:
                        baud_rate = B2400;
                        char_interval_timeout = TO_B2400;
                        break;
                case 4800:
                        baud_rate = B4800;
                        char_interval_timeout = TO_B4800;
                        break;
                case 9600: case 0:
                        baud_rate = B9600;
                        char_interval_timeout = TO_B9600;
                        break;
                case 19200:
                        baud_rate = B19200;
                        char_interval_timeout = TO_B19200;
                        break;
                case 38400:
                        baud_rate = B38400;
                        char_interval_timeout = TO_B38400;
                        break;
                case 57600:
                        baud_rate = B57600;
                        char_interval_timeout = TO_B57600;
                        break;
                case 115200:
                        baud_rate = B115200;
                        char_interval_timeout = TO_B115200;
                        break;
                case 230400:
                        baud_rate = B230400;
                        char_interval_timeout = TO_B230400;
                        break;                  
                case 460800:
                        baud_rate = B460800;
                        char_interval_timeout = TO_B460800;
                        break;  
                case 921600:
                        baud_rate = B921600;
                        char_interval_timeout = TO_B921600;
                        break;  
                default:
                        baud_rate = B9600;
                        char_interval_timeout = TO_B9600;
                        fprintf(stderr, "Unknown baud rate %d for %s.", baud_i, 
device);
        }



        if(( ttyfd = open( device, O_RDWR  | O_NOCTTY |  O_NDELAY ) ) < 0 )
        {
                fprintf( stderr, "Error opening device %s.   ", device );
                        
                fprintf( stderr, "Error no. %d \n",errno );
                
                return -1;
        }
        
        ioctl( ttyfd, TIOCGSERIAL, &ser );
        ser.flags |= ASYNC_LOW_LATENCY;
        ioctl( ttyfd, TIOCSSERIAL, &ser );

#ifdef DEBUG
        fprintf( stderr, "%s open\n", device );
#endif

        bzero( &settings, sizeof(settings) );

        cfsetispeed( &settings, baud_rate );/* Set the baud rate */
        cfsetospeed( &settings, baud_rate );

        settings.c_line = 0; 

        settings.c_iflag |=  IGNBRK;  /* ignore BREAK condition on input */
        settings.c_iflag |=  IGNPAR;  /* ignore framing errors and parity 
errors */
        settings.c_iflag &= ~PARMRK;
        settings.c_iflag &= ~INPCK;   /* disable input parity checking */
        settings.c_iflag &= ~ISTRIP;  /* disable strip off eighth bit */
        settings.c_iflag &= ~INLCR;       /* don't map NL to CR-NL on input */
        settings.c_iflag &= ~IGNCR;   /* don't ignore carriage return(CR) on 
input */
        settings.c_iflag &= ~ICRNL;       /* don't map CR to NL on input */
        settings.c_iflag &= ~IUCLC;   /* don't map uppercase->lowcase on input 
*/
        settings.c_iflag &= ~IXON;    /* disable XON/XOFF flow control on input 
*/ 
        settings.c_iflag |=  IXANY;
        settings.c_iflag &= ~IXOFF;   /* disable XON/XOFF flow control on 
output */ 
        settings.c_iflag &= ~IMAXBEL; /* not implemented in Linux */

        settings.c_oflag &= ~OPOST;   /* disable implementation-defined output 
processing */
        settings.c_oflag &= ~OLCUC;       /* don't map uppercase->lowcase on 
output */
        settings.c_oflag &= ~ONLCR;   /* don't map NL to CR-NL on output */
        settings.c_oflag &= ~OCRNL;   /* don't map CR to NL on output */
        settings.c_oflag |=  ONOCR;   /* don't output CR at column 0 */
        settings.c_oflag &= ~ONLRET;
        settings.c_oflag &= ~OFILL;       /* use a timed delay rather than send 
fill chars */
        settings.c_oflag &= ~OFDEL;       /* not implemented in Linux */

        settings.c_cflag &= ~CSIZE;       /* mask the character size bits */
        settings.c_cflag |=  CS8;         /* 8 data bits */     
        settings.c_cflag |=  CLOCAL;  /* ignore modem control lines */
        settings.c_cflag |=  CREAD;   /* enable receiver */
        settings.c_cflag &= ~HUPCL;
        settings.c_cflag &= ~CRTSCTS; /* disable RTS/CTS (hardware) flow 
control */
        settings.c_lflag &= ~ISIG;    /* disable generation of EOF and other 
signals */
        settings.c_lflag &= ~ICANON;  /* disable canonical mode */
        settings.c_lflag &= ~ECHO;    /* disable echo input characters */
        settings.c_lflag &= ~IEXTEN;  /* disable implementation-defined input 
processing */
                
        /********** applying stopbits count settings ***************/
        
        if( stopbits == 2 )
        {
                settings.c_cflag |=  CSTOPB;    /* explicitly set up 2 stopbits 
*/              
        }
        else    
        {
                settings.c_cflag &= ~CSTOPB;    /* one stopbit in any other 
cases */
        }

        /*********** applying parity settings **********************/

        if( strncmp( parity, "none", 4 ) == 0 )
        {
                settings.c_cflag &=~ PARENB;
                settings.c_cflag &=~ PARODD;
        }
        else
        if( strncmp( parity, "even", 4 ) == 0 )
        {
                settings.c_cflag |= PARENB;
                settings.c_cflag &=~ PARODD;
        }
        else
        {
                settings.c_cflag |= PARENB;
                settings.c_cflag |= PARODD;
        }

        settings.c_cc[VMIN]  = 0; //4
        settings.c_cc[VTIME] = 0; //1

        tcflush(ttyfd, TCOFLUSH | TCIFLUSH );

        if( tcsetattr( ttyfd, TCSANOW, &settings ) < 0 )
        {
                fprintf( stderr, "tcsetattr failed\n");
                return -1;
        }


        return( ttyfd );
}
_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to