From: Yigal Goldberger <yigal_gold@domain.hid>
To: xenomai@xenomai.org
Subject: [Xenomai-help] serial com errors
Date: Mon, 7 Dec 2009 01:57:11 -0800 (PST) [thread overview]
Message-ID: <801038.31731.qm@domain.hid> (raw)
Hi Again,
I hope it's not too long and tiring ...
But the relevant code (I think...) is the initialization stage , and the select and read loop that blocks and reads .
The problem is as follows :
I have 2 threads listening on two different serial coms . running the same code below . Using select to block and wait for bytes to be available on the port , and then reading them with the read function .
These 2 threads are Xenomai threads with priority higher then the thread that is responsible of working on the data .
I see that when reaceiving with BAUDRATES lower than 115200 (38400) no problem occures , and when receving on both port with BAUDRATE 115200 , I get errors in the received bytes ( which is identified by a wrong checksum ,and sometimes with a "No more room in flip buffer" printout on the console as well as errno 11 (EAGAIN) ) . When I added a 10 mili second sleep to the executing thread (the thread that uses the data )the problem seems to disappear .
Below is the 2 code parts that Initialize the file descriptor of the reading thread , and the reading select - read loop :
The code creating the file descriptor :
fd = open (devname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK );
memset ((void *)&ttykey, 0, sizeof (ttykey));
ttykey.c_cflag = 0;
ttykey.c_cflag |= CLOCAL;
ttykey.c_cflag |= CREAD;
ttykey.c_cflag |= CS8;
ttykey.c_lflag = 0;
#if 0
ttykey.c_lflag |= ECHO;
#endif
ttykey.c_iflag = 0;
ttykey.c_iflag |= IGNPAR;
ttykey.c_iflag |= IGNBRK;
ttykey.c_oflag = 0;
DPRINT( ("setting speed\n") );
cfsetispeed (&ttykey, B9600);
cfsetospeed (&ttykey, B9600);
if (fd > 0)
{
DPRINT( ("setting terminal attributes\n") );
tcsetattr (fd, TCSANOW, &ttykey);
}
/**********************************************************************/
/**********************************************************************/
//The code of the reading thread :
void *CTlp::ReadThread (CTlp *thistlp)
{
int nbytes;
int buf_ix;
fd_set input;
FD_ZERO(&input);
FD_SET(thistlp->fd, &input);
unsigned char bigbuf [IN_COMMAND_BUF_SIZE];
unsigned char cmdbyte;
BOOL receive_error;
int inbytes_ix = 0;
unsigned char inbytes [3];
int totalbytes = 0;
inbytes [2] = 0;
timeval io_timeout ;
timeval * pIo_timeout;
thistlp->state = &CTlp::tlp_await_first_byte;
// thistlp->fd = thistlp->init_port (thistlp->device_name);
pIo_timeout = NULL ;
DPRINT( ("readthread\n") );
thistlp->Tlp_Exec_mqd = mq_open (thistlp->pconn_info->toexecq->message_queue_name, O_WRONLY);
pthread_cleanup_push ((void(*)(void*))cleanwrite, (void *)thistlp->Tlp_Exec_mqd);
thistlp->SetBaudRate (thistlp->requested_baud_rate);
while (TRUE)
{
if (thistlp->nbytes_to_read == 1)
{
int xxx = tcgetattr (thistlp->fd, &thistlp->ttykey);
}
if ((nbytes = select (thistlp->fd+1, &input, NULL, NULL,pIo_timeout /*NULL*/)) < 0)
{
DPRINT( ("select problem: %s\n", strerror (errno)) );
break;
}
else
{
DPRINT( ("select returned %d\n", nbytes));
if (nbytes)//there are bytes to read from IO device -serial port
{
char *stopstring;
thistlp->CommandIO_In_progress = true ;
int nread = read (thistlp->fd, bigbuf, sizeof (bigbuf));
//This is a sync point , we try to lock this mutex and if we block
//it means that the frame list has not yet been deleted by the
//OutThread
pthread_mutex_lock (&thistlp->mutexSyncFrameListDestruction);
pthread_mutex_unlock (&thistlp->mutexSyncFrameListDestruction);
totalbytes += nread ;
buf_ix = 0;
while (buf_ix < nread)
{
receive_error = FALSE;
inbytes [inbytes_ix] = bigbuf [buf_ix++];
inbytes_ix = (inbytes_ix+1) % thistlp->nbytes_to_read;
if (inbytes_ix == 0)
{
if (thistlp->nbytes_to_read == 2)
{
//In this case bytes are sent over the line in ASCII code
//two chars per data byte , each char being a 0..F ascii code .
DPRINT( ("read bytes = %02x (%c), %02x (%c)\n", inbytes [0], inbytes [0], inbytes [1], inbytes [1]) );
//strtoul with 16 expects that each char in inbytes will be
//a the ascii value representing '0..F' hexadecimal values
cmdbyte = strtoul ((char *)inbytes, &stopstring, 16);
DPRINT( ("translated to %08x\n", cmdbyte) );
if (stopstring != (char *)&inbytes [2])
{
//if this code is reached it means that a corrupted
//byte which cannot be interpreted as an ascii rep' of
//a hex digit was read from the line indicating a com error !
DPRINT( ("couldn't translate\n") );
receive_error = TRUE;
// ?? what to do now - bad hex digit in ascii???
}
}
else
{
//This code is run in case we are using a BAUDRATE higher than
//9600 in which case the stream is sent as is - not ASCII !!!
//hence there's no need to interpret the ASCII code .
//Another possibility is that we reached the last byte EOT .
//in which case it also isn't sent in ASCII
DPRINT( ("read one byte : %02x\n", inbytes [0]) );
cmdbyte = inbytes [0];
}
stateptr funtorun = thistlp->state;
if (!receive_error)
(thistlp->*funtorun)(&cmdbyte);
else
thistlp->state = thistlp->NackToHost (M_BAD_HEADER);
}
}
}
else
{
if (!FD_ISSET(thistlp->fd,&input ) )
FD_SET(thistlp->fd, &input);
//in the event of a timeout during command reception we release
//all the resources (frames ) allocated to the command and restart the tlp machine
thistlp->post();
thistlp->ReleaseCommandFrames( thistlp->current_frame);
thistlp->current_frame = all_my_frames->Alloc (thistlp->pconn_info);
thistlp->current_frame->request_header->length = 0;
thistlp->CommandIO_In_progress = false ;
thistlp->overrunflag = false ;
pIo_timeout = NULL ;
thistlp->state = &CTlp::tlp_await_first_byte;
thistlp->SetBaudRate ( B9600 );
printf(" IO Timeout Occured on com %d , restarting tlp ... \n", thistlp->default_port );
}
if (thistlp->CommandIO_In_progress)
{ //If we are in the middle of a command we must enforce
//a timeout ,if not we can wait infinitely
io_timeout.tv_sec = 6 ;
io_timeout.tv_usec = 0 ;
pIo_timeout = &io_timeout ;
}
else
pIo_timeout = NULL ;
} //big else
}//while
pthread_cleanup_pop (TRUE);
return (void*)NULL;
}
Ideas will be more than welcome .
Thanks,
Yigal Goldberger.
next reply other threads:[~2009-12-07 9:57 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-07 9:57 Yigal Goldberger [this message]
2009-12-13 15:05 ` [Xenomai-help] serial com errors Gilles Chanteperdrix
2009-12-13 15:12 ` Gilles Chanteperdrix
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=801038.31731.qm@domain.hid \
--to=yigal_gold@domain.hid \
--cc=xenomai@xenomai.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.