[커널]시리얼 통신 문제
글쓴이: myjimi / 작성시간: 월, 2004/07/05 - 4:48오후
x86계열의 머신이고 리눅스에서 시리얼 디바이스를 작성해서 두개의 머신간에 디바이스 레벨에서 통신을 하려고 합니다. 디바이스 드라이버는 인터럽트 핸들러가 구현되어 있습니다.
데이터의 크기를 20byte라고 생각할때, COM 포트로 연결되어 데이터를 다른 머신으로 보내면 1,2,3...20의 순으로 데이터가 되어 있을때 순서대로 오지않고, 순서가 뒤엉커서 옵니다. 예를들어 읽는 쪽에서 데이터를 확인하면 1,5,10,2,7...20,18 이런식으로 들어오게 됩니다. 데이터 읽는 루틴에서 문제는 없습니다. 다른 머신에서 User Application으로 프로그램을 작성하여 COM 포트에 데이터를 보내면 정상적으로 읽습니다. COM 포트에 데이터를 쓸때 레지스터의 셋팅 문제(init_module에서 register 초기화)인지, 아니면 다른 문제가 있는지 알고 싶은데요. 답변주시면 감사하겠습니다.
Forums:
문제가 무엇인지를 지적하기에는 현상에 대한 설명이 조금 부족한듯 싶군요.
문제가 무엇인지를 지적하기에는 현상에 대한 설명이 조금 부족한듯 싶군요.
소프트웨어로 플로우 콘트롤을 어떻게 구현하셨고, 공유 데이터의 lock을 어떻게 처리하시는지 설명해주시면 원하시는 답변을 얻기가 좀더 수월하실듯 합니다.
단 어림짐작으로도, 레지스터 프로그래밍을 잘못해서 그런 결과가 나오기는 좀 힘들다고 봅니다.
두대의 컴퓨터가 COM 포트를 통해 연결되어 있습니다. device dr
두대의 컴퓨터가 COM 포트를 통해 연결되어 있습니다. device driver에 interrupt handler를 작성하여 interrupt handler가 serial 레지스터 값(0x04 또는 0x02 -> interrupt idenfication register값)을 판단하여 데이터를 base address(COM 포트:0x3F8)에서 1byte 읽거나(inb_p) 쓰는(outb_p) 역할을 합니다. 그리고 데이터 전송 요청시 1byte를 COM 포트에 써주게 됩니다. 그런데 데이터를 받는 쪽에서 읽어온 데이터를 확인하면 보낸 순서와는 다르게 순서가 뒤섞여 옵니다. 보내는 데이터는 0xAA라는 헤더를 가지고 있습니다. 답변주시기에 설명이 부족하다면 추가해서 말씀드리겠습니다.
안녕하세요.
[quote="hb_kim"]소프트웨어로 플로우 콘트롤을 어떻게 구현하셨
다음과 같은 항목을 검토하시면 될듯합니다.
누가 데이터를 생산하는지의 여부 -> 애플리케이션이 데이터를 파일에서 읽어오는지, 아니면 디바이스 드라이버가 자체적으로 데이터 스트림을 구성하는지
디바이스 드라이버가 export 하는 디바이스의 형태 -> char 디바이스를 export 하시는지 아니면 다른 형태의 디바이스인지
데이터의 오버플로우/언더플로우는 어떻게 방지하는지 -> 디바이스 드라이버가 어떠한 방법으로 어떠한 구성의 임시버퍼에 데이터 스트림을 일시적으로 저장하는지, 애플리케이션이 디바이스 드라이버보다 빠른 속도로 데이터를 write 할 경우 어떤 방법으로 이를 처리하시는지, 디바이스 드라이버의 버퍼가 꽉 찼는데도 애플리케이션이 데이터를 읽어가지 않을 경우 어떻게 처리하시는지
lock -> 디바이스 드라이버가 export 하는 디바이스가 single instance 만 제공하는지 아니면 multiple instance 를 제공하는지. multiple instance 의 경우 어떤 전역 변수들이 어떤 lock으로 보호되는지. 하드웨어 리소스를 어떠한 lock 으로 보호하시는지, 같은 하드웨어가 서로 다른 디바이스 드라이버에 의해 동시에 액세스 될수도 있는지 등등
한마디로 디자인 문서나, 아이디어를 요약해놓은 메모나 그런것이 있으면 다시 차분히 검토해보시거나, 게시판에 올려주시면 될듯합니다.
데이터는 User Application에서 전달된 데이터를 커널메모리에
데이터는 User Application에서 전달된 데이터를 커널메모리에 저장후,
전송 요청시 데이터를 읽어와서 다른 머신으로 전송합니다.
[프로그램 처리 순서]
- User Application write 요청 [write(com1fp, data, sizeof(data)]
(data는 20byte의 크기로 가정, header와 tail를 가지고 있음.)
-> device driver [copy_from_user로 데이터 커널 메모리(TxData)에 저장]
-> TxData를 커널 버퍼(TxBuffer[TxHead++])에 저장
-> 데이터 다른 머신으로 전송(outb_p(TxBuffer[TxTail++], BASE_ADDRESS))
-> 다른 머신에서 데이터 수신(interrupt handler에서 1byte씩 데이터 커널버퍼에 저장)
-> tasklet 수행
-> header 찾기, 데이터 저장
-> 데이터 오류검사
-> 오류 발생시 다시 header 찾기 / 정확한 데이터면 알려줌(모니터)
** 데이터를 확인하면 순서대로 들어오는 경우가 적고, 에러 발생 확률이 많습니다.
전체적인 프로그램 처리 순서는 위와 같습니다. 도움을 받을수 있을까요?
안녕하세요.
[quote="myjimi"]-> 데이터 다른 머신으로 전송(out
이 부분에서 printk() 로 전송데이터를 출력하고, 데이터를 원본 데이터와 비교하면 어디가 잘못되었는지 알수 있지 않을까요?
이미 확인했지만, 데이터를 전송할때는 원하는 순서대로 출력됩니다. 이전에
이미 확인했지만, 데이터를 전송할때는 원하는 순서대로 출력됩니다. 이전에도 말씀드렸지만 데이터를 받는 프로그램도 다른 방식으로 확인하면 데이터를 정확하게 받습니다.
그래서 인터럽트 핸들러 구현이 잘못되었거나, BASE Address에 데이터를 써줄때 화면상으로는 문제가 없기때문에 serial register setting에 문제가 있는게 아닐까하는 생각을 하는겁니다.
[ISR routine]
#define IIR 2
status = inb_p(BASE+IIR);
if((status&0x04) == 0x04) readdata;
else((status&0x02) == 0x02) writedata;
ISR routine의 역할은 간단하게 위와 같습니다. 어떻게 해결할 수 있을까요?
안녕하세요.
뭐...비슷한지는 모르겠지만.....저도 그런 비슷한 경험을 했죠..
뭐...비슷한지는 모르겠지만.....
저도 그런 비슷한 경험을 했죠...
이상하게 RX시 데이타가 데이타 길이에 따라 빠지던가 하는 좀 이상한 현상을...^_^
그런데.... 쉽게 해결이 되더군요...
KLDP Wiki:Linuxdoc Sgml/Serial-Programming-HOWTO 문서를 살펴보시기 바랍니다.
그곳에 나온데로 해당 포트의 터미널 모드를 설정했더니..정상적으로 입/출력이 이루어지더군요...
==============================
= Crazy Fighter : Kill Them All =
==============================
자체 제작한 시리얼 디바이스 드라이버라서 리눅스에서 제공해주는 termi
자체 제작한 시리얼 디바이스 드라이버라서 리눅스에서 제공해주는 termios 구조체에 대한 분석은 그리 도움이 되지 않았습니다. 결국 커널 코드를 분석해야 되는데, 시리얼에 관계되는 디바이스 코드도 분량이 만만치 않네요...
이유 불문하고 질문드렸던 문제는 해결했습니다. 시리얼 레지스터(Interrupt Enable Register) setting 문제였습니다. 답변 주신 분들께 감사드립니다.
안녕하세요.
댓글 달기