개념
왜 테스터가 비트 단위까지 알아야 하나
웹 테스터는 TCP가 재전송과 순서 보장을 해 주니 비트를 몰라도 된다. 보드 안의 직렬 통신에는 그런 보호막이 얇거나 없다. UART는 오류를 감지해도 재전송하지 않고, SPI는 오류를 감지하는 장치조차 없으며, I2C는 ACK 한 비트가 유일한 확인이다. 통신 결함이 응용 계층까지 그대로 올라온다. 센서 값이 가끔 튀거나, 설정이 가끔 저장되지 않거나, 부팅이 가끔 멈추는 현상의 원인이 비트 하나의 타이밍인 경우가 많다.
세 프로토콜을 한눈에 비교하면 이렇다.
| 항목 | UART | SPI | I2C |
|---|---|---|---|
| 선 수 | TX, RX (+ RTS/CTS) | SCLK, MOSI, MISO, CS(장치당 1개) | SDA, SCL 2개 |
| 클럭 | 없음(비동기, 양쪽이 속도를 약속) | 마스터가 공급 | 마스터가 공급, 슬레이브가 늦출 수 있음 |
| 연결 | 1:1 | 1 마스터 : 여러 슬레이브 | 여러 장치가 한 버스 공유 |
| 주소 지정 | 없음 | CS 선으로 선택 | 7비트(또는 10비트) 주소 |
| 오류 확인 | 패리티(선택), 프레이밍 | 없음(응용 계층 CRC에 의존) | 바이트마다 ACK/NACK |
| 전형적 속도 | 9600~921600bps | 수 MHz~수십 MHz | 100k~3.4MHz |
UART — 시계 없이 약속만으로
UART는 클럭 선이 없다. 송신 쪽과 수신 쪽이 같은 속도(보드레이트) 를 미리 약속하고, 수신 쪽은 시작 비트의 하강 에지를 보고 자기 시계를 맞춘 뒤 비트 중앙에서 값을 읽는다.
유휴(High) ─┐ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───── 유휴
│ S │D0 │D1 │D2 │D3 │D4 │D5 │D6 │D7 │ P │ Stop
└───┘ (High)
S = 시작 비트(항상 Low)
D0~D7 = 데이터 비트, LSB 먼저
P = 패리티 비트(선택: 없음/짝수/홀수)
Stop = 정지 비트(High, 1 또는 2비트)설정은 흔히 8N1 처럼 줄여 쓴다. 데이터 8비트, 패리티 없음(None), 정지 비트 1개라는 뜻이다. 한 바이트를 보내는 데 시작 1 + 데이터 8 + 정지 1 = 10비트가 든다. 그래서 115200bps의 실제 데이터 처리량은 초당 약 11520바이트다. 테스터가 "초당 20KB 로그를 115200bps UART로 뽑는다"는 설계를 보면 계산만으로 결함 을 찾을 수 있다.
보드레이트 오차 허용
시작 비트에서 한 번 맞춘 시계로 10비트를 끝까지 읽어야 하므로, 양쪽 시계가 조금씩 어긋나면 마지막 비트쯤에서 샘플링 지점이 비트 경계를 넘는다. 수신기가 비트 중앙에서 샘플링한다면 10비트 끝에서 반 비트(50%)까지 밀려도 되니 이론상 한계는 약 ±5%다. 하지만 이 오차는 양쪽 오차의 합 이고, 에지가 무뎌지고 샘플링 방식에도 여유가 필요하므로 실무에서는 한쪽당 ±2~3% 안쪽 을 안전 범위로 본다.
오차는 주로 MCU 클럭을 정수로 나눠 보드레이트를 만들 때 생긴다.
MCU 클럭 16 MHz, 목표 115200bps, 16배 오버샘플링
분주값 = 16,000,000 / (16 × 115200) = 8.68 → 9로 반올림
실제 속도 = 16,000,000 / (16 × 9) = 111,111bps
오차 = (111,111 − 115,200) / 115,200 ≈ −3.5% ← 위험이 보드는 PC와는 대개 통신이 되다가, 역시 오차가 반대 방향으로 있는 다른 장치와 붙이면 가끔 깨진다. 내장 RC 발진기를 쓰는 MCU는 온도에 따라 클럭이 1~2% 흔들리므로 저온·고온에서만 깨지는 UART 도 흔하다.
UART 오류 종류
| 오류 | 의미 | 흔한 원인 |
|---|---|---|
| 프레이밍 오류(framing error) | 정지 비트 자리에서 High가 아니라 Low를 읽음 | 보드레이트 불일치, 잡음, 데이터 비트 수 설정 불일치 |
| 패리티 오류 | 패리티 비트가 계산과 다름 | 잡음, 패리티 설정 불일치 |
| 오버런 오류(overrun) | 이전 바이트를 읽기 전에 다음 바이트가 도착해 덮어씀 | ISR이 늦음, 수신 버퍼(FIFO) 부족, 다른 인터럽트가 길게 점유 |
| 브레이크 감지 | 한 프레임 이상 Low가 계속됨 | 선 끊김, 상대 장치 리셋, 의도된 브레이크 신호 |
오버런은 레슨 1의 인터럽트 문제와 곧바로 연결된다. 통신 자체는 멀쩡한데 소프트웨어가 제때 읽지 못해서 생긴다. 그래서 오버런 시험은 "최대 속도로 연속 수신하면서 다른 인터럽트 부하를 겹치는" 형태가 된다.
흐름 제어
수신 쪽이 처리하지 못할 때 송신을 멈추게 하는 장치가 흐름 제어다. 하드웨어 방식은 RTS/CTS 선, 소프트웨어 방식은 XON(0x11)/XOFF(0x13) 문자를 쓴다. 시험 포인트는 수신 버퍼가 거의 찼을 때 실제로 송신이 멈추는지, 이진 데이터 속 0x11·0x13을 제어 문자로 오인하지 않는지, 한쪽만 흐름 제어를 켰을 때 무엇이 멈추는지다.
SPI — 빠르지만 아무것도 확인하지 않는다
SPI는 마스터가 클럭(SCLK)을 주고, 클럭 한 번마다 MOSI(마스터→슬레이브)와 MISO(슬레이브→마스터)로 동시에 한 비트씩 주고받는다. 슬레이브 선택은 장치마다 따로 있는 CS(Chip Select, 보통 Low 활성) 선으로 한다.
CPOL과 CPHA — 네 가지 모드
SPI에는 표준 협회가 없어서 칩마다 클럭의 극성과 위상이 다르다. 이 두 설정의 조합이 모드 0~3이다.
| 모드 | CPOL(유휴 시 클럭) | CPHA(샘플링 에지) | 샘플링 시점 |
|---|---|---|---|
| 0 | Low | 첫 번째 에지 | 상승 에지 |
| 1 | Low | 두 번째 에지 | 하강 에지 |
| 2 | High | 첫 번째 에지 | 하강 에지 |
| 3 | High | 두 번째 에지 | 상승 에지 |
모드가 틀리면 통신이 완전히 실패하지 않는다는 점이 위험하다. 전형적 증상은 이렇다.
- 값이 한 비트 밀린다 — 0x55를 보냈는데 0xAA나 0x2A가 읽힌다. 모든 값이 2배 또는 절반처럼 보인다
- 대부분 맞고 가끔 틀린다 — 샘플링 에지가 데이터 변화 순간과 겹쳐, 배선 길이·온도·클럭 속도에 따라 결과가 흔들린다
- 첫 바이트만 틀린다 — 모드 0과 3처럼 샘플링 에지는 같지만 유휴 극성이 다를 때, CS 직후 첫 비트에서만 어긋난다
모드 불일치는 낮은 클럭에서는 우연히 동작하다가 클럭을 올리면 드러나기도 한다. 그래서 SPI 클럭 속도는 경계값 시험 대상 이다.
CS 타이밍과 기타 시험 포인트
- CS 셋업·홀드 시간 — CS를 내린 뒤 첫 클럭까지, 마지막 클럭 뒤 CS를 올릴 때까지 칩이 요구하는 최소 시간(데이터시트 표). 최적화 빌드에서 코드가 빨라지면 이 시간이 줄어 실패하기도 한다
- 여러 슬레이브 — 두 CS가 동시에 Low가 되면 MISO에서 두 칩이 충돌한다. 공유 버스를 두 태스크가 쓰면 잠금 누락으로 이런 일이 생긴다
- 무결성 확인 — SPI 자체에 오류 검출이 없으므로 플래시 쓰기 후 되읽기 비교, 응용 계층 CRC가 있는지 확인한다
I2C — 두 선을 여럿이 나눠 쓴다
I2C는 SDA(데이터)와 SCL(클럭) 두 선을 여러 장치가 공유한다. 핵심은 오픈 드레인 구조다. 어떤 장치도 선을 High로 밀지 않는다. 선을 Low로 끌어내릴 수만 있고, High는 풀업 저항 이 만든다. 그래서 풀업 저항이 없으면 버스가 동작하지 않고, 값이 잘못되면 가끔만 동작한다.
풀업 저항 값은 속도와 버스 정전용량(배선 길이·장치 수)의 균형이다. 저항이 크면 상승 시간이 길어져 빠른 속도에서 High가 제때 올라오지 않고, 저항이 작으면 장치가 Low로 끌어내릴 때 전류가 커진다. 오실로스코프로 상승 시간을 재는 것이 확인 방법이다(레슨 4).
트랜잭션 구조
S | 주소 7비트 | R/W | ACK | 데이터 8비트 | ACK | 데이터 8비트 | NACK | P
START: SCL High인 동안 SDA가 High→Low
STOP : SCL High인 동안 SDA가 Low→High
ACK : 수신 쪽이 9번째 클럭에서 SDA를 Low로 당김
NACK : SDA가 High로 남음(아무도 당기지 않음)주소는 7비트라서 한 버스에 이론상 112개 정도(예약 주소 제외)의 장치를 둘 수 있다. 같은 센서 두 개를 붙이려면 주소 핀으로 주소를 바꿔야 하고, 이 설정이 겹치면 두 장치가 동시에 응답 한다. 주소 표기는 데이터시트마다 7비트(0x50)와 R/W 비트를 붙인 8비트(0xA0/0xA1)로 달라서, 설정 오류의 단골 원인이다.
NACK은 "장치가 없다", "장치가 바쁘다", "마지막 바이트를 다 받았다"를 모두 뜻할 수 있다. EEPROM은 쓰기 사이클(수 ms) 동안 NACK으로 응답한다. 이때 소프트웨어가 재시도 없이 실패로 처리 하면 연속 쓰기에서 간헐적 저장 실패가 된다.
속도 모드
| 모드 | 최대 속도 |
|---|---|
| Standard-mode | 100 kbit/s |
| Fast-mode | 400 kbit/s |
| Fast-mode Plus | 1 Mbit/s |
| High-speed mode | 3.4 Mbit/s |
버스에서 가장 느린 장치가 속도를 정한다. Fast-mode Plus를 지원하지 않는 센서가 하나라도 있으면 1MHz로 올릴 수 없다.
클럭 스트레칭
슬레이브가 준비되지 않았을 때 SCL을 Low로 붙잡아 마스터를 기다리게 하는 기능이다. 마스터가 이를 지원하지 않거나, 소프트웨어로 흉내 낸(bit-bang) I2C가 SCL을 확인하지 않으면 슬레이브가 준비되기 전에 데이터를 읽어 쓰레기 값이 나온다. 스트레칭이 비정상적으로 길어지면 마스터가 무한히 기다리므로 타임아웃이 있는지 가 시험 포인트다.
버스 고착과 복구
I2C의 대표적 현장 결함은 SDA가 Low로 고착 되는 것이다. 슬레이브가 바이트 전송 도중 마스터가 리셋되면, 슬레이브는 아직 전송 중이라고 생각하고 SDA를 Low로 붙잡은 채 다음 클럭을 기다린다. 마스터는 버스가 사용 중이라 START를 못 보낸다. 교착이다.
표준적인 복구 방법은 마스터가 SCL에 클럭을 최대 9번 보내 슬레이브가 남은 비트를 다 내보내게 한 뒤 STOP을 보내는 것이다. 시험은 이렇게 한다.
1. 센서 읽기 루프를 돌린다
2. 로직 분석기로 데이터 바이트 중간에 트리거
3. 그 순간 MCU만 리셋(워치독 강제 만료 또는 리셋 핀)
4. 판정: 재부팅 후 버스 복구 루틴이 동작해 센서 읽기가 재개되는가
복구되지 않으면 전원을 끊기 전까지 센서가 죽어 있음 → 결함세 프로토콜의 결함·경계값 시험 케이스
모듈 3 레슨 1의 경계값 분석을 통신 설정에 그대로 적용하면 이런 표가 된다.
| ID | 대상 | 시험 조건 | 기대 결과 | 잡는 결함 |
|---|---|---|---|---|
| U-01 | UART | 상대 장치 보드레이트 −3%, +3% | 오류 없이 수신 | 분주 오차가 큰 설정 |
| U-02 | UART | 상대 보드레이트 −6%, +6% | 프레이밍 오류 감지·카운트, 시스템 멈춤 없음 | 오류 처리 누락, 무한 루프 |
| U-03 | UART | 최대 속도로 수신 버퍼 크기 +1바이트 연속 전송, 동시에 타이머 인터럽트 부하 | 오버런 없음 또는 감지 후 복구 | ISR 지연, 버퍼 부족 |
| U-05 | UART | 저온(−20°C)·고온(+70°C)에서 U-01 반복 | 동일 결과 | RC 발진기 온도 드리프트 |
| S-01 | SPI | 클럭을 규격 최대, 최대의 110% | 최대에서 정상, 초과에서 오류 검출 | 여유 없는 타이밍 |
| S-02 | SPI | 최적화 수준 변경 빌드(-O0, -O2) | 동일 동작 | CS 셋업 시간이 코드 속도에 의존 |
| S-03 | SPI | 두 태스크가 같은 버스의 다른 장치에 동시 접근 | 데이터 혼선 없음 | 버스 잠금 누락, CS 동시 활성 |
| I-01 | I2C | 존재하지 않는 주소로 읽기 | NACK 처리, 타임아웃 내 오류 반환 | NACK 무시, 무한 대기 |
| I-02 | I2C | EEPROM 연속 페이지 쓰기 | 쓰기 사이클 NACK을 재시도로 처리 | 간헐적 저장 실패 |
| I-03 | I2C | 슬레이브가 SCL을 규정보다 길게 붙잡음 | 마스터 타임아웃 후 복구 | 무한 대기 |
| I-04 | I2C | 전송 중 마스터 리셋(버스 고착 유도) | 재부팅 후 9클럭 복구, 통신 재개 | 복구 루틴 없음 |
| I-05 | I2C | 풀업 저항을 설계값의 2배로 교체, 버스 속도 최대 | 상승 시간 규격 이내, 오류 없음 | 풀업·정전용량 여유 부족 |
U-02처럼 범위 밖 조건에서의 기대 결과는 "동작"이 아니라 "안전하게 실패" 다. 오류를 감지하고 카운트하고, 시스템 전체가 멈추지 않는 것이 합격이다.
실무에서 왜 필요한가
직렬 통신 결함은 재현이 어렵고 증상이 엉뚱한 곳에 나타난다. SPI 모드가 틀린 온도 센서는 "온도가 가끔 두 배로 튄다"로 보고되고, 복구 루틴이 없는 I2C 버스 고착은 "현장에서 가끔 센서가 죽는데 전원을 껐다 켜면 된다"로 보고된다. 개발자는 벤치에서 재현하지 못하면 "하드웨어 문제"로 넘기기 쉽다. 프로토콜의 프레임과 경계 조건을 아는 테스터는 증상을 통신 층의 가설로 바꾸고, 로직 분석기로 그 가설을 확인하고, 설정·타이밍·복구 중 어디가 문제인지 결함 보고서에 적을 수 있다. 이것이 "재현 안 됨"으로 닫힐 결함을 수정 가능한 결함으로 바꾸는 차이다.
채용시장에서의 위치
임베디드 검증 공고의 자격요건에 "UART·SPI·I2C·CAN 등 통신 프로토콜 이해"가 거의 빠지지 않는다. 면접에서는 "UART 보드레이트가 3% 어긋나면 어떻게 되나", "SPI 모드가 틀리면 어떤 증상이 나오나", "I2C 버스가 Low로 고착되면 어떻게 복구하나" 같은 질문이 나온다. 정답 암기보다 증상에서 원인을 추론하고 시험으로 확인하는 순서 를 말할 수 있는지가 평가된다. 로직 분석기로 직접 디코딩해 본 경험, 보드레이트 오차를 계산해 본 경험이 있으면 웹 QA 출신이어도 설득력이 크게 올라간다.