직렬 포트 패리티 오류를 확인 중이신가요?

직렬 포트 패리티 오류를 확인 중이신가요?

몇 가지 테스트를 실행하려는 장치가 있습니다. 나는 그것이 115200보드로 연결되고 8개의 데이터 비트, 패리티 없음 및 1개의 정지 비트를 가지고 있다는 것을 알고 있습니다.

저는 이러한 설정을 증명하려고 노력 중입니다. 또는 적어도 이러한 설정이 실제로 장치에서 사용되는 설정이라는 것을 증명하는 데 가까워지려고 노력 중입니다. 장치는 시작 시 알려진 데이터를 전송하므로 테스트 전략은 올바른 설정에서 연결하여 데이터를 수신한 다음 개별 설정을 변경하고 데이터가 손상될 수 있음을 예상하는 것입니다.

그러나 pyserial 또는 termios를 사용하여 직접 패리티 또는 정지 비트 설정을 변경하면 손상된 데이터가 표시되지 않습니다. 6비트 데이터 크기만 변경하면 데이터가 손상됩니다.

패리티 또는 정지 비트 오류와 같은 문제를 기록할 수 있는 위치나 로그가 있습니까? 패리티를 기록하거나 비트 오류를 ​​중지하도록 조정할 수 있는 termios를 사용하는 일부 설정이 있습니까?

추가 데이터: 실제 직렬 트래픽은 USB-COM422-PLUS4 보드의 FT4232H를 통과하므로 테스트 중인 블랙박스에는 /dev/ttyUSB3이라고 표시됩니다.

답변1

드라이버가 제공하는 내용에 따라 패리티 오류를 감지하고 올바른 termios 설정으로 이를 계산할 수도 있어야 합니다. ioctl TIOCGICOUNT(참조남자 4 tty_ioctl)는 매뉴얼 페이지에 문서화되어 있지 않지만 오류 카운터를 검색할 수 있습니다. Python은 ioctl을 제공하지 않지만 다음 스크립트는 getcounts.py시스템에 맞게 수정해야 할 수 있는 낮은 수준의 fcntl 호출을 통해 이를 수행합니다. 커널 포함 파일에 설명된 구조를 사용합니다 serial.h. (실제 직렬 장치에 대한 카운터는 에도 표시되지만 /proc/tty/driver/serialUSB 장치에는 표시되지 않습니다.)

#!/usr/bin/python2
# https://unix.stackexchange.com/a/525261/119298
import sys, fcntl, array
# ioctl to get counters. see /usr/include/linux/serial.h
# struct serial_icounter_struct{
#  int cts, dsr, rng, dcd, rx, tx, frame, overrun, parity, brk,
#      buf_overrun, reserved[9]; }
def getcounts(filename):
    TIOCGICOUNT = 0x545D
    fd = open(filename)
    s = array.array('I',[0 for i in range(20)])
    rc = fcntl.ioctl(fd.fileno(),TIOCGICOUNT,s,True)
    if rc!=0:
        print "rc",rc
    names = "cts,dsr,rng,dcd,rx,tx,frame,overrun,parity,brk,bufo"
    cts,dsr,rng,dcd,rx,tx,frame,overrun,parity,brk,bufo = s[:11]
    for i,name in enumerate(names.split(",")):
        print name,s[i]
    fd.close()

getcounts(sys.argv[1])

예를 들어, 크로스오버 케이블을 통해 2개의 실제 직렬 포트를 연결하는 경우 다음 스크립트는 패리티 감지 설정을 변경할 때 3가지 다른 결과를 표시합니다. 먼저 두 직렬 장치를 동일하게 설정하여 짝수 패리티( "not" -ignpar으로 표시)를 생성하고 감지합니다. -이 함수는 에 쓰기 try위해 3번 실행되고 , 에서 결과를 읽는 데 사용되며 , 마지막으로 카운터를 인쇄하기 위해 실행됩니다.hellottyS1xxdttyS0getcounts.py

#!/bin/bash
try()(
    xxd -l 16 /dev/ttyS0 &
    sleep 1
    for i in 1 2 3 ; do echo hello; done >/dev/ttyS1
    sleep 1
    getcounts.py /dev/ttyS0
)

stty -F /dev/ttyS0 9600 raw -echo clocal
stty -F /dev/ttyS1 9600 raw -echo clocal
stty -F /dev/ttyS0 parenb -ignpar inpck parodd
stty -F /dev/ttyS1 parenb -ignpar inpck parodd
try # should be ok
stty -F /dev/ttyS0 -parodd
try # should get parity errors, lots of null data
stty -F /dev/ttyS0 parmrk
try # should get parity errors, lots of ff 00 prefix to each data

첫 번째 시도에서는 데이터가 정상이고 패리티 카운트가 0이라는 것을 보여주어야 합니다(이 장치를 방금 사용하기 시작했다고 가정).

00000000: 6865 6c6c 6f0a 6865 6c6c 6f0a 6865 6c6c  hello.hello.hell
...
parity 0
...

다음 시도 전에 짝수 패리티로 변경 ttyS0하고 출력을 얻습니다.

00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
parity 16

즉, 패리티 오류가 있는 모든 문자에는 널 문자가 있습니다. xxd16자를 읽은 후 중지하면 실제 패리티 오류 개수는 16개입니다.

마지막 시도를 하기 전에 우리는 묻습니다.표시데이터의 패리티 오류입니다. 이로 인해 커널은 각 잘못된 데이터 문자 앞에 2바이트 0xff 및 0x00을 배치하고 다음과 같은 결과를 얻습니다.

00000000: ff00 68ff 0065 ff00 6cff 006c ff00 6fff  ..h..e..l..l..o.
parity 22

xxd종료 시간이 더 빠르기 때문에 패리티 수는 6씩만 증가합니다 .

USB 드라이버의 경우 위에 표시된 데이터는 동일해야 하지만 카운터는 어떤 식으로든 변경되지 않을 수 있습니다.

관련 정보