Closing a serial port

I am unable to close a serial port handle that was successfully opened in blocking mode. The reason, I believe, is that a thread was blocked on a read and then terminated. Is there a way to free a blocked thread in software from a blocked serial port access so the thread can be properly terminated or to force the port to close?

Eric

Have you tried the tc functions, like tcflush() and tcsendbreak()?

Yes, I have tried those and others both before terminating the thread to see if it unblocks it and after to see if it will allow closure of the serial port; both had no effect. I would think that someone would have run in this problem already but perhaps they just band-aid the problem by putting the port in polling mode. Did anyone figure out how to use a serial port in blocking mode and still be able to close it from another controlling thread?

Eric

I am afraid that I used your “band-aid”. In my case I am doing a lot of ethernet I/O so it was easy to put it in the polling for that.

How are you terminating your threads? Externally? I would avoid that. Try using a mutex or semaphore to tell your thread to terminate itself. Then you can do cleanup.

-Erik

Can someone give me an example of using serial port in non-blocking or polling (is that the same) mode?

I am having this same problem - I can’t close serial port.

mik

///////Opending the port

#define BAUD 9600

termios stSerialData;

hSerialPort = open(stPort, O_RDWR | O_NONBLOCK);//Use for polling
//hSerialPort = open(stPort, O_RDWR);//Used for event driven
if(hSerialPort == -1)
{
printf("Failed to open serial port
");
}
else
{
tcgetattr(m_hSerialPort, &stSerialData);
stSerialData.c_cflag = CREAD | CS8;
stSerialData.c_iflag = 0;
stSerialData.c_oflag = 0;
stSerialData.c_xflag = 0;
stSerialData.c_lflag = 0;

if(//**YOU want hardware flow control**//)
{
	stSerialData.c_cflag |= CRTSCTS;
}

cfsetospeed(&stSerialData, BAUD);
cfsetispeed(&stSerialData, BAUD);

if(tcsetattr(hSerialPort, TCSANOW, &stSerialData) != 0)
{
	printf("Error configuring port

");
}
}

////////Reading from the port
////////Strucured to have a dedicated polling and data handling thread
int nBytesRead;

//Used for polled IO
while(1)
{
nBytesRead = read(hSerialPort, Buffer, nLength);
if(nBytesRead != -1)
{
break;
}
tx_thread_sleep(1);
}

//Used for blocked IO
nBytesRead = read(m_hSerialPort, Buffer, nLength);

It may be better to use the function tcgetbuffers() to see if there is anything received before calling read().

Here is how I use the buffer size:

//////////////////////////////////////
int nSize;
char Buffer[256];
struct serial_buffer_t sbt;
tcgetbuffers(s_fds, &sbt);

// Check for serial overflows and fix 'em
if( sbt.rxbuf > 512 && sbt.txbuf > 1024 )
{
tcflush(s_fds, TCIOFLUSH);
tcgetbuffers(s_fds, &sbt);
tcflow(s_fds, TCOON);
tcflow(s_fds, TCION);
}
else if( sbt.rxbuf > 512 )
{
tcflush(s_fds, TCIFLUSH);
tcgetbuffers(s_fds, &sbt);
tcflow(s_fds, TCION);
}
else if( sbt.txbuf > 1024 )
{
tcflush(s_fds, TCOFLUSH);
tcgetbuffers(s_fds, &sbt);
tcflow(s_fds, TCOON);
}

// get the data from the 320
while( sbt.rxbuf >= 1 && s_pfifo320IN->size() < 1024 )
{
nSize = read(s_fds, Buffer, sizeof(Buffer)-1);

if( nSize &lt;= 0 ) break;

if( s_pfifo320IN )
	s_pfifo320IN-&gt;write(Buffer, nSize);

sbt.rxbuf -= nSize;

}

//////////////////////////////////////

the s_pfifo320IN is a FIFO.

To reset the tx:
//////////////////////////////////////
tcflush(s_fds, TCOFLUSH);
tcsendbreak(s_fds, 1);
tcflow(s_fds, TCOON);
//////////////////////////////////////

I use an NATotalTicks and NADeltaTicks to determine if the port is jammed.

-Erik