임베디드 일기장

리눅스 CAN bus-off 상태 복구 — restart-ms 자동 복구 본문

Linux

리눅스 CAN bus-off 상태 복구 — restart-ms 자동 복구

jaeuuu 2026. 7. 12. 19:42
반응형

CAN 컨트롤러는 에러가 누적되면 스스로 버스에서 물러난다. 이 보호 메커니즘(error confinement)의 종착역이 bus-off 상태인데, 여기 들어가면 송수신이 완전히 멈추고 저절로 돌아오지 않는다(설정하지 않는 한). 이 글은 리눅스에서 bus-off를 진단하고 복구하는 방법을 정리하고, 후반부에서는 CAN 하드웨어가 없는 개발 PC에서 상위 스택을 테스트하는 vcan 환경 구성을 다룬다.

1. CAN 에러 상태머신 복습

CAN 노드는 TEC/REC(송신/수신 에러 카운터)에 따라 세 상태를 오간다.

Error-Active   (정상: 에러 프레임을 dominant로 송출 가능)
   ↓ 카운터 > 127
Error-Passive  (경고: 통신은 되지만 에러 프레임이 recessive, 송신 후 대기시간 증가)
   ↓ TEC > 255
Bus-Off        (퇴출: 송수신 불가)

핵심은 bus-off가 일시적 상태가 아니라 종착 상태라는 것. 표준상 복구 조건(128×11 recessive bit 관찰)이 충족돼도, 컨트롤러/드라이버가 재시작 절차를 밟아야 버스로 돌아온다.

2. 상태 확인

ip -details -statistics link show can0

볼 것: state 필드(ERROR-ACTIVE / ERROR-PASSIVE / BUS-OFF), restarts 카운터(자동 복구 횟수), 그리고 berr-counter tx rx의 에러 카운터 값. 상태 전이를 실시간으로 잡고 싶으면 에러 프레임 수신 소켓을 열거나 candump로 관찰한다.

candump -e any,0:0,#FFFFFFFF   # 에러 프레임 포함 덤프

3. 복구 방법 세 가지

① 수동: 인터페이스 재시작

ip link set can0 down
ip link set can0 up type can bitrate 500000

가장 확실하지만, down/up 과정에서 소켓들이 영향을 받고 애플리케이션 재연결 처리가 필요하다.

② 수동: restart 트리거 — 인터페이스를 내리지 않고 bus-off 복구만 지시할 수 있다.

ip link set can0 type can restart

단, 이 명령은 bus-off 상태일 때만 유효하다(아닐 때 실행하면 에러).

③ 자동: restart-ms (실전 권장) — bus-off 진입 후 지정 시간(ms)이 지나면 드라이버가 자동으로 복구를 수행한다.

ip link set can0 down
ip link set can0 up type can bitrate 500000 restart-ms 100

무인 장비라면 사실상 필수 설정이다. 흔한 오해 하나를 짚자면, 이 설정은 소켓 옵션(setsockopt)이 아니라 netlink(ip link) 레벨의 인터페이스 속성이다. 애플리케이션 코드가 아니라 인터페이스 초기화 스크립트에 들어가야 할 값이라는 뜻이다.

주의: 자동 복구는 증상 치료다. bus-off까지 간 근본 원인 — 종단저항 누락, 비트레이트 불일치, 배선 문제, 특정 노드의 고장 — 을 잡지 않으면 "복구 → 재진입"을 무한 반복하며 버스를 계속 오염시킨다. restarts 카운터가 계속 증가하고 있다면 복구 설정이 문제를 가리고 있는 것이니 에러 카운터 추이와 함께 원인 조사를 해야 한다. 원인 규명에는 앞서 쓴 에러 전용 raw 소켓(CAN_RAW_ERR_FILTER) 상시 감시가 유용하다.

4. 하드웨어 없이 스택 테스트: vcan

CAN이 없는 리눅스 PC에서도 SocketCAN 상위 계층은 전부 테스트할 수 있다. vcan(가상 CAN 인터페이스) 은 루프백 기반 가상 네트워크 장치라서, raw 소켓, ISO-TP, BCM, 자체 프로토콜 로직까지 하드웨어 없이 돌려볼 수 있다.

sudo apt install can-utils
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

# 터미널 1
candump vcan0
# 터미널 2
cansend vcan0 123#11223344

가능/불가능의 경계를 분명히 하면: SocketCAN API, ISO-TP 커널 모듈, 필터링, 애플리케이션 프로토콜 검증은 가능. 반면 실제 컨트롤러 드라이버(flexcan 등)의 probe/인터럽트/비트타이밍, 그리고 이 글 전반부의 bus-off 상태 전이 자체는 재현 불가다 — vcan에는 에러 카운터 개념이 없다. 즉 vcan은 "프로토콜 로직 개발용"이고, 에러 처리 경로 검증은 결국 실물(또는 에러 프레임을 주입할 수 있는 장비)이 필요하다.

WSL2 주의사항: WSL2 기본 커널에는 vcan 모듈이 빠져 있어 modprobe vcan이 실패한다. 선택지는 세 가지 — WSL2 커널을 직접 빌드해 CONFIG_CAN/CONFIG_CAN_VCAN을 켜거나, VirtualBox/QEMU의 정식 리눅스 VM을 쓰거나, 개발 보드에서 직접 vcan을 쓰는 것. 커널 빌드가 익숙하다면 WSL2 커널 교체도 할 만하지만(커널 소스에 컨피그 추가 후 .wslconfig로 지정), 한 번 해보는 실험이 아니라면 보드에서 직접 하는 게 결국 편했다.

5. 정리

  1. bus-off는 종착 상태다 — 복구는 down/up, restart 트리거, restart-ms 자동 복구 중 택일
  2. restart-ms는 소켓 옵션이 아니라 ip link 인터페이스 속성이다 — 초기화 스크립트에 넣어라
  3. 자동 복구를 걸었어도 restarts 카운터 증가는 근본 원인이 살아 있다는 경보다
  4. vcan으로 프로토콜 로직은 하드웨어 없이 개발 가능하지만, 에러 상태머신은 재현되지 않는다
  5. WSL2에서는 vcan이 기본 불가 — 커널 재빌드 또는 VM/실보드로

CAN 시스템의 버스 에러 대응 설계 과정에서 정리한 내용입니다.

반응형