[문의] 시리얼 포트가 제대로 열릴 때가 있고, 그렇지 않을 때가 있네요..
글쓴이: 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:
댓글 달기