시리얼 통신에서 read할때 연속된 값이 들어옵니다
글쓴이: raphael4 / 작성시간: 목, 2013/11/21 - 5:32오후
임베디드 장비 끼리 시리얼 통신을 하는데
read 할때 연속된 값이 들어옵니다
예를 들어
A -> 11 22 33 44 -> B
이렇게 보내면
B에서 버퍼를 읽어 보면 11 11 22 33 33 44
이런식으로 중간에 연속된 값이 버퍼에 들어 있더군요
패킷 체크 때문에 1byte씩 읽어야 하는데
너무 빨리 읽어서 그런가 싶어 1byte씩 읽을 때마다 usleep(1000)을 줬더니
그 다음부터는 제대로 값을 읽습니다
하지만 read할때마다 usleep(1000)을 준다는건 너무 위험부담이 큰것 같고 좋은 방법이 안닌것 같아
고민이 많이 됩니다
왜 이렇게 버퍼에 값이 쌓이는 것인지 도무지 모르겠습니다
초보자에게 조언 부탁드립니다
Forums:
대충 세가지 가능성..
첫째 읽는 루틴이 잘못되었거나.. 즉 리딩 루틴에서 이미 사용한 버퍼를 다시 사용한다든지 하는 식.
둘째 보내는쪽에서 실제로 계속 중복해서 보내는게 맞는데 수신측에서 그냥 버퍼 오버런으로 날려버리기 때문에 딜레이를 줬을 때 제대로 동작하는 것처럼 보이는 경우 .
셋째 양자간 통신규약이 미묘하게 다를 경우, 또는 흐름제어 설정/케이블 배선이 잘못된 경우. RTS CTS 신호선이랄지.. XON XOFF, 보레이트나 스타트비트 스탑비트 등등등.. 어이없어보이지만 실제로 이런 케이스가 있었던 기억이 납니다.
대충 이정도 떠오르네요.
저라면 수신측을 검증된 녀석(PC 하이퍼터미널이나.. 새롬데이터맨이나.. 여러가지..)을 사용해서 일단 데이터가 제대로 발생하는지 확인을 해보겠습니다.
--
답변 감사합니다
시리얼 통신이긴 하지만 포트가 일반 RS232가 아니고 특정 장비에만 달수 있는 포트라서
장비를 통하지 않고는 일반 PC에서 확인하긴 어렵습니다. 젠더를 만들수 있는 여건도 안되서...
제 생각엔 수신측이 확실히 잘 못 읽는게 맞을것 같습니다
말씀하신 이유 중 첫번째가 맞을거 같긴한데
이미 사용한 버퍼를 다시 사용한다는게 무슨말씀이신지 모르겠습니다
read하면 버퍼의 seek가 이동되는것 아닌가요?
예를 들어 버퍼에 11 22 33 44 4byte가 들어 있다면
1byte를 읽어오면 다음에 읽을때는 22를 읽어야 하는게 아닌가요?
제가 왠지 잘 못 알고 있다는 생각이 듭니다만
usleep으로 타이밍을 맞춰줘야만 제대로 읽어온다는 것도 이해가 잘 안됩니다.
usleep 으로 딜레이를 주면 제대로 읽어온다면
usleep 으로 딜레이를 주면 제대로 읽어온다면 수신 버퍼에서 사라지기 전에 다시 읽어오는 것 같은데
무슨 개발툴을 쓰는지도 모르고, 수신 코드도 없어서 애매하네요
혹시 수신 버퍼에 도착한 바이트를 읽는 ISR이 읽은 후에 데이터 도착 신호를 제대로 클리어하게 코딩되어 있는지 확인해 보세요.
만약 폴링 방식으로 읽는다면 깝깝할 수 있는 상황인데 데이터 도착 신호를 클리어할 수 없다면 적당한 delay를 주고 폴링할 수 밖에 없음.
사용한 버퍼를 다시 사용한다는 말은
예를들어 100바이트짜리 메모리를 받아서 수신용으로 쓴다 했을때 이 메모리를 반복적으로 수신용으로 사용하면서 리턴값 체크를 제대로 하지 않으면 기존에 받은 데이터가 그대로 남아있는 줄도 모르고 다시 사용을 하겠죠. 만약 이런 상황이라면, sleep을 통해 딜레이를 주고 나서 타이밍적으로 다음 데이터가 넘어올때가 되었으면 다음 데이터가 정상적으로 읽혀질 수도 있는 거죠. 신뢰하기 어려운 방식이지만요. 가베지 값이 아닌, 기존 데이터가 그대로 남아있다는 걸로 봐서 이런 상황이 예상이 되는 것입니다. 간단하게 체크해보려면, 읽기 전에 프로그램상의 버퍼 메모리를 클리어하고 읽어보면 됩니다.
여기서 버퍼란건 작성하신 프로그램상의 버퍼를 말하는 것이고, 드라이버나 하드웨어단의 버퍼를 말하는것이 아닙니다. 물론 해당 장비가 어떤것인지 모르므로 드라이버나 하드웨어단이 잘못되었거나 원래 그렇게 동작하는 하드웨어/드라이버일 가능성도 염두에 두어야 합니다. 일하시는 업체에서 그 부분을 직접 작업했다면 더더욱.
--
시리얼 모니터링 프로그램으로 받아 보세요... 만약
시리얼 모니터링 프로그램으로 받아 보세요... 만약 제대로 받아지면 수신측이 문제
16비트 칩에 리눅스 커널이 들어갑니다
펌웨어 수준은 아니고 리눅스 임베디드 라고 보시면 됩니다
알아 봤더니 선행 개발자가 poll 이벤트로 작업했다가 문제가 있어서
폴링 방식으로 루프 막 돌려서 메시지 받게 했는데 이렇게 작업해서 문제가 없었다고 하네요
제 생각엔 우연히 타이밍이 맞아서 문제가 안나왔던거 같은데
이번에 시스템 업그레이드 하면서 타이밍이 틀어져서 근본적인 문제들이 생겨나는것 같습니다
poll 이벤트 걸고 타임아웃을 1로 주고 올려 봤는데 현재까진 이상 없습니다만
조금 불안하긴 합니다
도대체 왜 이렇게 작업되어진 건지 알길이 없어서 다 갈아엎어버리기도 애매하고...
만약 이래도 문제가 발생하면 1byte읽고 버퍼 초기화 하고 하는식으로 해봐야 겠습니다
읽은후 버퍼 초기화 할때 그 다음 데이타가 이미 들어와 있으면 데이터 소실이 일어날수도 있을까요? 괜히 걱정이...
암튼 위에 두분 답변 정말 감사드립니다
대충 상황이 눈에 그려지네요..
결국 수신측 버퍼는 하드웨어 (또는 드라이버) 단에서 1바이트밖에 없는 것이고.
이벤트나 인터럽트 처리는 모두 생략.
질문에 대한 답변은.. 데이터가 들어온 뒤 읽지 않은 상태에서 다른 데이터가 들어오면 버퍼가 1바이트뿐일 경우 당연히 오버런이 발생합니다. 이 경우 UART의 데이터 오버런 플래그가 세트될겁니다.
여기서 권장해드릴 만한 것들은.
(1) 아주 구형의 UART라도 최소 수 바이트 정도는 버퍼링이 가능한 걸로 알고 있습니다. (아예 버퍼링이 불가능한 것도 있지만 그런게 아직까지 쓰일것 같지는 않고요.) 물론 이 기능을 세팅을 통해서 끌 수도 있고, 정말로 꺼져있다면 한바이트만 수신될수밖에 없겠죠. 혹시 이걸 켤 수 있나요? 드라이버 수정만 할 수 있으면 가능할겁니다. 이걸 켤 수 있다면 폴링으로 메시지를 읽다가 놓치더라도 몇 번의 기회를 더 얻을 수 있습니다. 안정성이 증가함은 말할 것도 없겠죠. 폴링을 좀더 천천히 해도 되고요.
(2) UART레지스터에 데이터 수신여부를 판단할 수 있는 플래그가 있습니다. 이걸 사용하면 한 번 읽은 데이터를 다시 중복해서 읽는 일은 발생하지 않겠죠. 플래그 세트가 안 되어 있으면 데이터를 읽지 않고 그냥 FALSE를 리턴하면 되니까요. 역시 드라이버의 수신 함수에서 구현해야 할 일입니다. UART의 종류를 몰라 이렇게밖에 설명을 못드리지만 분명히 가능할겁니다.
상황상 UART핸들링이 제대로 안 되고 있는 걸로 보입니다. 버퍼링을 켜서 안정성을 높이고 에러 플래그나 데이터 수신 확인 플래그도 계속 검사해야 합니다.
--
댓글 달기