본문 바로가기

조금은 전문적인 이야기/자동차 통신

통신 신호 분석하기


 프로토콜에 대한 이해를 하기에 앞서 먼저 공돌이라면 신호 분석 정도는 할 줄 알아야 하기에 일단 한번 짚고 넘어가도록 해보자. 대학에서 흔히 쓰는 오실로 스코프를 이용하면 간단한 신호정도는 잡아 낼 수가 있는데, 이 신호를 이해를 해야 프로토콜에 대한 이해가 좀더 쉬워진다. 


 일단 신호를 잡는 방식은 대부분이 Serial 통신이기 때문에 디지털 파형으로 잡도록 한다. 아날로그로 잡을 경우 굉장히 알아보기 힘든 곡선형 그래프가 나오기 때문에, 스코프의 세팅을 반드시 확인을 해야 한다. 


 그렇다면 먼저 질문이 필요한데, 1 Byte는 몇 개의 Bit로 이루어져 있는가? 만일 8개의 Bit라고 생각 한다면 실제 통신 데이터를 보면 엄청난 혼란에 휩싸이게 된다. 1 Byte는 8개 Bit 이상으로 이루어져 있다. Data가 되는 8개의 Bit외에 시작을 알리는 Start bit와 패리티 비트로 이루어져 있는데, 이를 한번 알아보도록 하자. 


 기본적으로 통신 종류에 따라 다르지만 차량의 통신은 대부분이 HIgh 가 기본으로 시작을 한다. 시작은 1이라는 뜻이다. 그리고 이 High 값은 통신 종류에 따라 전압이 틀린데, 12V 일 수도 있고 5V 일수도 있다. 물론 각 통신별로 어느정도의 절충값이 있어 딱 12V나 5V에 맞아야만 한다는 것은 아니다. 당연히 자동차의 배터리 전압에 따라 왔다갔다 하는데 그 정도도 신경쓰지 않는다면 제대로 된 통신이 되지 않으니 말이다. 


 자 위쪽의 그림을 보면 실제 주고 받는 데이터를 스코프로 찍은 사진이다. 1 Bit가 100us 정도이니 계산을 해보면 100 us = 0.1 ms 가 되므로 1초인 1000으로 나눠주면 초당 10000번의 Bit를 주고 받을 수 있는 10000 BPS가 나온다. 이 프로토콜은 KWP2000으로 10417 BPS의 스펙을 가지고 있다. 정확히는 1 Bit 가 104.17 us로 전송이 된다는 뜻이다. 4.17 us를 잡아내는 것은 굉장히 힘든 일이므로, 대략적인 BPS만 알아내고 나면, 각 프로토콜의 스펙에 맞춰서 정확한 속도를 산출 할 수 있다. 


 이 그림의 경우 길게 0값이 들어오는 부분이 있는데, 총 1800ms 동안 들어온다. 이걸 9로 나누면 한 Bit당 200ms가 나오는데 마찬가지로 1000으로 나눠주면 초당 5번의 Bit를 전송하는 5 BPS 통신이라는 것을 알 수 있다. 이 부분은 ISO 9141-2의 5 BPS 이니셜 부분이다. 


 이런식으로 통신속도를 알아내는 것이 실제 프로토콜 분석을 위한 첫번쨰 단계이며 이 단계가 이루어지지 않으면, 절대로 분석 자체를 실시할 수 조차 없다. 통신속도를 나타내는 단위는 BPS(Bits per second)와 Baud rate(보레이트)가 쓰이는데, 둘다 초당 비트의 전송수을 뜻한다. 


 그렇다면, 통신속도는 알았다. 그러면 이후에 정확한 데이터는 무엇인가? 에 대한 의문이 생긴다. 앞서서 1개의 바이트는 몇 개의 비트로 이루어져 있는지에 대해 말을 했다. 그에 맞춰서 ISO 9141-2의 경우는 한 바이트를 9개 비트로 쪼갠 뒤에 통신 속도를 찾았다. 사실 해당 프로토콜의 경우는 5 BPS 이니셜 이후 통신 속도가 바뀐다. 바뀌는 부분은 첫번째 했던 것 처럼 한 비트의 속도를 보고 산출하면 된다. 


 말이 샛는데, 그렇다면 어떤식으로 데이터를 읽으면 되는지 알아보자. 첫번째 그림을 보고 비트로 정리를 해보면(VCC = 1, GRD = 0)


0 1 0 0 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 1 0 0 0 0 1 1 0 1 0 1 0 1 0 1 1 1 0 0 0 1 0 0 0 0....


이라고 읽을 수 있다. 이것을 읽기 좋게 변경을 해보면 다음과 같다. 


0 [1 0] [0 0 0 1] [0 1 0 0] [1 0] [1 1 1 0] [1 0 1 1] [1 0] [0 0 0 1] [1 0 1 0] [1 0] [1 0 1 1] [1 0 0 0] [1 0 ] 0 0 0....

               8            2                   7            D                   8            5                   D            1


 자 어떻게 보이는가? 이제좀 감이 잡히는가? 이 코드는 위에도 썼지만 KWP2000을 사용하는 프로토콜의 데이터 중간 부분이다. 정확히는 [28] [D7] [58] [1D] 라는 부분이다. 자 어느정도 비트를 읽을 줄 아는 사람이라면 이해를 하고 있을 테지만, 그렇지 않은 경우 이상하다. 왜 저게 저렇게 읽어지는 것일까?

 앞서 말한대로 1 바이트는 8 비트가 아니다. 여기를 보면 10 비트처럼 보이는데, 맨처음의 1 값은 기본 VCC 전압이다. Byte간의 간격에 들어오는 기본 신호라고 보고 무시하면 된다. 사실 KWP2000을 아는 사람이 이 파형을 보면 이상할 것이다. 어째서 바이트간의 간격이 없는 것인가!! P1이나 P4 라고 부르는 이 바이트간 타임은 각 프로토콜 별로 정의가 되어 있는데, 이 파형에서는 없다. 이유는 그냥 사진을 찍기 위해서 시뮬레이터로 만든 가짜 통신 코드이기 때문이다. 

 또 이야기가 이상한 곳으로 샛는데, 자 10 비트에서 첫 번째 1 은 말한대로 기본 전압이고 두 번쨰의 0 은 Start bit 이다. "데이터를 시작합니다."를 알려주는 코드인데, 이 코드가 없다면 당연히 받는 측의 입장에서는 연속해서 데이터가 올 경우 정확한 데이터를 받기가 힘들다. 이와 비슷한 용도로 Stop 비트가 있을 경우가 있고, 패리티 비트가 있을 수 있다. 패리티에 대해서는 아래에 다시 설명을 하겠지만, 데이터의 신뢰성을 위해 만들어진 장치 중의 하나이다. 기본적으로 통신 프로토콜들은 CS 즉 체크섬이라는 것을 두어 메세지의 신뢰성을 보장하기 때문에 패리티의 필요가 그렇게 크지는 않지만 간혹 조금 변태스러운 녀석들은 패리티까지 있는 경우가 있다. 

 자꾸 이야기가 샌다. 자 그렇다면 처음의 [1 0] 부분은 이해가 된다. 그런데 왜 [0 0 0 1] 은 1 이 아니라 8 이고 [0 1 0 0] 은 4가 아니라 2 일까? 그리고 왜 합치면 82가 아니고 28일까? 대부분 MSB와 LSB에 대해서 알고 있을 거라 생각한다. 솔직히 이것에 대해 설명하는 것 자체가 조금 우스울 수 있으나, 책에서 보던 것과 실제는 다르니 한번 설명을 해보자. 먼저 MSB(Most Significant Bit)와 LSB(Least Significant Bit)에 대해서 설명을 하자면, MSB는 Data를 이루고 있는 Bit의 가장 큰 수 즉 가장 왼쪽에 있는 비트를 뜻하며, LSB는 가장 작은 수인 가장 오른쪽에 있는 비트를 뜻한다. [0 0 0 1] [0 1 0 0] 에서 표시된 왼쪽의 0 이 MSB이고 오른쪽의 0 이 LSB를 뜻하는 것인데, 

 그렇다면 읽었을 때 왜 14가 아닐까? 그것은 비트를 읽는 방식에 있다. 이 통신 신호들은 사람이 읽기 편하라고 만들어 진 것이 아니라, 기계에서 효율적으로 데이터를 전송하기 위해서 만들어 져 있다. 비트를 읽는 방식에는 두 가지 방식이 있는데, 빅 엔디안(Big Endian)과 리틀 엔디안(Little Endian)이라는 방식이다. Unix나 서버쪽 지식이 있는 사람들은 아하! 라고 금방 감이 올 것이다. 

 빅 엔디안은 간단하게 말하면 사람이 읽는 대로 순서대로 비트를 읽는 방식이고 리틀 엔디안은 나열된 비트를 거꾸로 읽는 방법이다. 사실 이 두 방식은 서버에 저장이 되는 방식을 뜻하긴 하지만...의미는 통하니 가져다 쓰도록 하자. 

 따라서 이 비트 시그널을 빅 엔디안으로 읽으면 14가 되는 것이고 리틀 엔디안으로 읽으면 28이 되는 것이다. 그리고 대부분의 Serial 통신은 리틀 엔디안으로 비트를 읽는다. 사실 따지고 보면 기계의 입장이 되어서 이 신호를 받는다고 생각 해 보면 차례대로 [0 0 0 1] [0 1 0 0] 이 들어오면 기계에는 들어온 순서대로 [0 0 0 1] -> [1 0 0 0] -> [8], [0 1 0 0] ->[0 0 1 0] -> [2] 로 읽혀진다는 것을 알게 될 것이다. 데이터를 받는 순서대로 낮은 단위부터 쌓이기 때문에 이런 현상이 발생하는 것이다. 이것을 거꾸로 하면, 사람이 읽기는 편하겠으나, 기계에서는 한 바이트를 받을 떄마다 순서를 바꿔줘야 하는 작업을 해줘야 한다. 

 자 그러면 대부분의 의문은 모두 풀렸다. 그렇다면 아까 말을 했던 패리티란 녀석을 알아보자. 이 패리티라는 녀석은 바이트 단위의 데이터 신뢰성 체크를 위해 만들어진 장치로서 데이터의 마지막에 1 비트가 더 붙는 형식으로 이루어 진다. 어떤식으로 신뢰성 체크를 하냐면, 모든 비트의 합을 1 로 만들어 주는 Odd(홀수) 형식의 패리티와, 0 으로 만들어 주는 Even(짝수) 패리티가 대부분 쓰이는데, 간단히 예를 들면, [0 0 0 1] [0 1 0 0] [1] 이렇게 올경우는 모든 비트의 합이 1 이 되므로 Odd 패리티 인 것이고, [0 0 0 1] [0 1 0 0] [0] 일 경우는 모든 비트의 합이 0 이 되므로 Even 패리티가 되는 것이다. 

 이것 까지가 대부분 기본적으로 알고 있는 패리티에 대한 이야기고 사실 패리티의 종류는 두 가지가 더 있다. 바로 Mark 패리티와 Space 패리티 이다. 이 두 가지의 패리티는 조금 특별한 녀석인데, 단 바이트 통신시에 SID와 DATA를 구분하는 용도로 사용이 된다. Mark 패리티의 경우는 무조건 마지막에 [1] 이 오는 것이며 Space 패리티는 마지막에 [0] 이 오는 것을 말한다. 이 패리티는 바이트의 신뢰성을 확인하기 위한 용도가 아니라, 바이트의 용도를 확인하기 위해 쓰인다.  이 녀석은 매우 특별한 경우에만 쓰이기 때문에 접할 기회가 많지는 않을 것이다. 

 자 이제 마지막으로 CS(Check sum)이라는 녀석을 알아보도록 하자. 패리티가 바이트의 신뢰성을 위해 만든 장치라면 CS는 한 프레임의 메세지의 신뢰성을 확인하기 위해 만든 장치이다. 기본적으로 사용하는 CS는 SUM이 가장 많은데, 간단하게 하나의 프레임의 바이트를 모두 더한 값이다 . 그 외에 Xor나 FF에서 더한 값을 빼는 식 등의 특이한 CS들이 존재하는데, 대부분의 CS는 각 프로토콜에서 정의가 되며 간단한 연산으로 확인이 가능하게 만들어져 있다. 이 CS대한 부분은 메세지 프레임에 대해 모른다면 전혀 알 방법이 없으므로 프로토콜에 대해 설명할 떄 다시 설명을 해야 할 것 같다. 

 사실 간단하게 신호 분석에 대해서 쓰려고 했는데, 생각보다 양이 많아 졌고, 굉장히 어려워 졌다. 어느정도의 배경 지식이 없는 상태에서도 이해할 수 있게 해보려고 최대한 쉬운 프로토콜을 예로 들어서 설명을 했는데...이게 쉬운건지 모르겠다. 사실 이 부분은 통신 프로토콜 분석을 하는데 있어 가장 기초적인 부분이기도 하다. 

 각 프로토콜들의 분석에 앞서서 한번 정밀하게 쪼갤 필요는 있기 때문에 바이트를 쪼개서 분석하는 포스트를 남겨둔다. 사실 이 내용은 비단 자동차 통신 뿐만이 아니라 다른 곳에서도 유용하게 쓰일 수 있기 떄문이다. 게다가 가장 기초가 되는 KWP2000과 ISO 9141-2에서는 반드시 비트에 대한 이해가 있어야 하기에 프로토콜 분석에 앞서 설명을 했다.