시리얼 통신시 read 함수 오동작
글쓴이: rexmoon / 작성시간: 화, 2007/04/24 - 2:34오후
안녕하세요
S3C2800 보드의 UART1 통신을 테스트 하기 위해 PC와 연결하여 아래의 프로그램으로
송/수신 테스트를 하고 있는데요 PC로 송신은 잘 되는데 수신이 안됩니다.
우선 아래 프로그램을 한번 봐주시기 바랍니다.
#include <unistd.h> #include <fcntl.h> #include <termios.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #define MODEMDEVICE "/dev/ttyS1" //UART1 사용 #define BAUDRATE B9600 //보레이트 9600 설정 int main( int argc, char **argv ) { int fd; int res; unsigned char buf[255]; unsigned char buf2[6] = "HELLO"; struct termios oldtio, newtio; //터미널 구조체 int txemptystate; fd = open( MODEMDEVICE, O_RDWR | O_NOCTTY ); //UART1 디바이스 파일 오픈 if( fd < 0 ) { perror( MODEMDEVICE ); exit( -1 ); } printf( "\n%s open!!\n",MODEMDEVICE ); //정상적으로 오픈되었을때 출력 tcgetattr(fd, &oldtio); //현재 설정을 oldtio에 저장 memset( &newtio, 0x0, sizeof( newtio ) ); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; //baud 통신 속도, CS8 (8bit, No Parity, 1 Stop Bit)설정 newtio.c_iflag = IGNPAR; //Parity 오류가 있는 문자 무시 newtio.c_oflag = 0; //출력처리 설정 0이면 아무것도 안함 newtio.c_lflag = 0; //Local Mode 설정, ICANON이면 널 문자가 들어올때까지 수신 newtio.c_cc[VTIME] = 0; //time-out 값으로 사용, time-out 값은 TIME*0.1초 newtio.c_cc[VMIN] = 1; //read가 리턴되기 위한 최소한의 문자 개수 tcflush( fd, TCIFLUSH ); //설정을 초기화 tcsetattr( fd, TCSANOW, &newtio ); //newtio 터미널 구조체의 속정으로 설정을 적용 fcntl( fd, F_SETFL, FNDELAY ); write(fd, buf2, sizeof(buf2)); //송신 테스트, HELLO를 전송, nDVR 리눅스 커널 /linux-2.4.26/drivers/char/tty_io.c 파일의 tty_write 함수 while( 1 ) { if( (res = read( fd, buf, sizeof(buf))) > 0 ) //입력을 기다림, 문자의 갯수가 리텀됨, nDVR 리눅스 커널 /linux-2.4.26/drivers/char/tty_io.c 파일의 tty_read 함수 { printf( "read size = %d\n",res ); write( fd, buf2, sizeof(buf2) ); //입력을 받으면 HELLO를 전송하고 다시 read함수에서 기다림 } else { //printf("-"); } } tcsetattr( fd, TCSANOW, &oldtio ); //이전 상태로 되돌린다. close( fd ); }
PC상의 터미널 프로그램에서 문자를 보내보면
에코가 나옵니다. 위 소스부분에는 그런 부분이 없거든요.
정상적으로 read가 동작한다면 HELLO가 출력되어야 하는데 왜 이런지 모르겠습니다.
그리고 read 함수가 리턴 되지도 않습니다. read 함수 자체에서 이런 동작을 하는듯 한데...
보드에 오실로 스코프를 이용하여 정확한 데이터가 S3C2800 RxD1으로 들어가는것을 확인하였습니다.
그래서 하드웨어 문제는 아닌 것 같고요...
newtio.c_cc[VMIN] = 0; 이렇게 수정하면 처음 한번은 에코가 나오고 한 10초가량 정상동작 하다가 시리얼이
죽어버립니다.
혹시 프로그램상 문제가 있는 지 알고계신분의 도움을 부탁드립니다..
아니면 디버깅 접근방법에 대한 조언도 괜찮습니다.
꼭 좀 부탁드리겠습니다.
그럼 모두 즐거운 하루 되십시오~ ^^
Forums:
답이 아니라 죄송합니다만... 소스 코드가 많이 짤렸습니다.
<code> ... </code> 태그로 감싸 주시면 소스가 제대로 올라올 겁니다.
음...
코드가 좀 짤렸군요..
제생각엔 먼저
쉘 프롬프트 상에서
echo hello > /dev/ttyS1
을 치셔서 ttyS1 쪽 콘솔에서 hello가 찍히는지 확인해보시면 도움이되실것 같습니다.
hello가 찍히지 않으면 하드웨어 연결이 잘못되었거나
시리얼 포트 설정이 잘못된것 같으니 확인해보시면 될것 같구요.
(시리얼 포트 설정은 stty 명령으로 가능합니다)
hello가 잘 찍힌다면 그다음에 프로그램 상에 이상이 없는지 확인해보시면 될것 같습니다.
http://www.easysw.com/~mike/serial/serial.html
설정등은 이 싸이트 참고하시면 좋을것 같네요
이렇게 한번 해보시죠.. 제가 사용하는 소스입니다..
------------------------------------------------
가끔은 하늘을 보고 살자...
아.. 소스는 요렇게 올려야하는군요..^^; 감사합니다~
답변 감사합니다~ ^^
그런데 올려주신 소스대로 해봐도 똑같네요..ㅜㅡ
위에도 말씀 드렸지만 보드에서 PC로 보내는 것은 잘 되거든요.. 그런데 read 함수가 1바이트 만이라도 데이터가 들어오면 리턴되고 아래부분을 수행해야하는게 그게 안되고 소스에도 없는 에코 메시지가 뜹니다..
소스를 일단 pc상에서
소스를 일단 pc상에서 돌려보세요..
임베디드 리눅스 커널 문제일수도 있습니다...
그런데 Com Analyzer프로그램 좋네요.. 공개하시는건 어떠신지..
--
Linux강국 KOREA
http://ydongyol.tistory.com/
--
Linux강국 KOREA
http://ydongyol.tistory.com/
소스에는 별로 문제가 없어 보이는데요...
S3C2800에 올리신 리눅스 커널쪽의 문제가 아닐까 싶습니다.
시리얼 디바이스 드라이버 쪽을 다시 체크해 보실 필요가 있을 듯 합니다.
수신이 안되시는거군요..
살짝 핀트가 어긋난 답변을 했었네요 ^^;
명령으로 tty 설정을 한번 살펴보세요.
시리얼 수신이
시리얼 수신이 되는지 안되는지는 /proc 에서 인터럽트 쪽 파일을 열어보셔서
시리얼에 숫자가 증가(시리얼 로 문자가 들어오면 인터럽트가 걸리므로)하는지 보시면 됩니다.
거기에 이상없이 시리얼 수신 인터럽트가 걸리면 커널은 이상이 없게 되는거죠..
--
Linux강국 KOREA
http://ydongyol.tistory.com/
--
Linux강국 KOREA
http://ydongyol.tistory.com/
답변 감사합니다~ ^^
터미널 프로그램 첨부할께요..
보드상에서 위의 프로그램을 실행하고 데이터를 계속 보내는데
/proc/interrupt 파일에 serial 부분이 생기지 않네요..타이머와, Host/PCI Bridge 외에 숫자가 증가하는것도 없고요..
그럼 커널에 이상이 있는 걸까요??
이상이 있다면 커널의 /drivers/char/tty_io.c 요파일만 확인하면 되나요??
이렇게 출력됩니다.
아.. 보레이트는 둘다 115200으로 수정했습니다.
댓글 달기