[문의] 시리얼 포트가 제대로 열릴 때가 있고, 그렇지 않을 때가 있네요..
글쓴이: liveeasily / 작성시간: 화, 2007/08/07 - 8:30오후
시리얼 통신을 이용한 프로그램을 짜고 있습니다.
시리얼 포트를 열면 쓰레드가 생성됩니다.
그 쓰레드는 select 를 통하여 수신할 데이트가 도착하면 큐에 저장해 둡니다.
그리고 응용해서 필요할 때 그 큐에서 읽어가는 방식으로 짜보았습니다.
문제는 프로그램을 실행해 보면 정상작동할 때가 있고, 그렇지 않은 경우가 있습니다.
소스는 다음과 같습니다.
#include "CSerial.h"
#include <errno.h>
/* ---------------------------------------------------------------- */
// description : 생성자
/* ---------------------------------------------------------------- */
CSerial::CSerial()
{
m_bConnect = FALSE;
//signal(SIGINT, HandlerSignal);
}
/* ---------------------------------------------------------------- */
// description : 소멸자
/* ---------------------------------------------------------------- */
CSerial::~CSerial()
{
printf("called destructor\n");
if( FALSE == m_bConnect )
ClosePort();
pthread_cancel(m_tidWatchPort);
}
/* ---------------------------------------------------------------- */
// description : 시리얼 포트를 연다.
/* ---------------------------------------------------------------- */
int CSerial::OpenPort(char *szDevName, int nBaud)
{
int nBaudBit;
m_fdSerial = open(szDevName, O_RDWR | O_NOCTTY | O_NONBLOCK);
if( m_fdSerial < 0 ) {
printf("%s open failed.. \n", szDevName);
return FALSE;
}
printf("m_fdSerial = %d\n", m_fdSerial);
tcgetattr(m_fdSerial, &m_tioOld);
if( -1 == (nBaudBit = ConvertBaud(nBaud)) ) {
printf("wrong baud rate.. \n");
return FALSE;
}
m_tioNew.c_cflag = nBaudBit | CRTSCTS | CS8 | CLOCAL | CREAD;
m_tioNew.c_iflag = IGNPAR;
m_tioNew.c_oflag = m_tioNew.c_lflag = 0;
m_tioNew.c_cc[VMIN] = 1;
m_tioNew.c_cc[VTIME] = 0;
tcflush(m_fdSerial, TCIFLUSH);
tcsetattr(m_fdSerial, TCSANOW, &m_tioNew);
m_bConnect = TRUE;
if( (pthread_create(&m_tidWatchPort, NULL, ThreadWatchPort, this)) < 0 ) {
printf("thread create failed..\n");
tcsetattr(m_fdSerial, TCSANOW, &m_tioOld);
return FALSE;
}
return TRUE;
}
/* ---------------------------------------------------------------- */
// description : 시리얼 포트를 닫는다.
/* ---------------------------------------------------------------- */
void CSerial::ClosePort()
{
tcsetattr(m_fdSerial, TCSANOW, &m_tioOld);
if( TRUE == m_bConnect)
close(m_fdSerial);
m_fdSerial = 0;
m_bConnect = FALSE;
}
/* ---------------------------------------------------------------- */
// description : 정수형으로 된 baud 를 c_cflag 용 bit로 변환하여 반환
/* ---------------------------------------------------------------- */
int CSerial::ConvertBaud(int nBaud)
{
switch( nBaud ) {
case 9600:
return B9600;
case 19200:
return B19200;
case 38400:
return B38400;
case 57600:
return B57600;
case 115200:
return B115200;
}
return -1;
}
/* ---------------------------------------------------------------- */
// description : 큐 버퍼로 부터 데이터를 읽는다.
/* ---------------------------------------------------------------- */
int CSerial::Read(char *pBuff, int nToRead)
{
int i;
int nRead; // 실제 읽은 바이트 수
int nQueueSize = m_quRead.GetSize();
if( nQueueSize < nToRead )
nToRead = nQueueSize;
for( i=0; i<nToRead; i++ )
{
if( FALSE == m_quRead.GetByte(pBuff+i) ) {
printf("get data from queue failed..\n");
return 0;
}
}
return <!--break-->nToRead;
}
/* ---------------------------------------------------------------- */
// description : 시리얼 포트로 데이터를 전송시킨다.
/* ---------------------------------------------------------------- */
int CSerial::Write(char *pBuff, int nToWrite)
{
int nWrite; // 실제 전송한 바이트 수
nWrite = write(m_fdSerial, pBuff, nToWrite);
return nWrite;
}
/* ---------------------------------------------------------------- */
// description : 시리얼 포트를 감시하는 스레드
/* ---------------------------------------------------------------- */
void* ThreadWatchPort(void* arg)
{
fd_set readSet;
int fdSerial;
int nRead, i;
char buf[255] = "";
CSerial *serial = (CSerial*)arg;
extern int errno;
fdSerial= serial->GetFD();
FD_ZERO(&readSet);
FD_SET(fdSerial, &readSet);
while( serial->isConnect() ) {
printf("select.....\n");
if( select(fdSerial+1, &readSet, NULL, NULL, NULL) == -1 ) {
perror("fdSerial");
printf("errno = %d\n", errno);
printf("fd = %d\n", fdSerial);
return FALSE;
}
if( FD_ISSET(fdSerial, &readSet) != 0 ) {
printf("fd_isset.....\n");
nRead = read(fdSerial, buf, 255);
printf("read in thread %d byte : %s\n", nRead, buf);
for( i=0; i<nRead; i++) {
if( FALSE == serial->m_quRead.PutByte(buf[i]) ) {
return FALSE;
}
}
memset(buf, 0, 255);
}
}
printf("thread end\n");
return (void*)TRUE;
}에러 발생시 쓰레드의 select 부분에서 발생합니다. 리턴값이 -1이며 errno=29 입니다.
정상적으로 실행이 안되는 경우에는 포트가 제대로 열리지 않은 것으로 추측해봤지만,
fd 값이 양수값(보통 3으로 잡히더군요) 인 것으로 보아 그 문제는 아닌 것으로 판단했습니다.
아무리 생각해도 무엇이 문제인지 잘 모르겠습니다.
조언 부탁드리겠습니다.
Forums:


댓글 달기