임베디드 면접 학습 노트 목차

자동차 임베디드 표준 — AUTOSAR · ISO 26262 · UDS

일반 임베디드와 자동차 임베디드를 가르는 것은 문법이 아니라 표준이다. 같은 C 코드라도 자동차에서는 "왜 그렇게 썼는지"를 문서로 증명해야 한다.

이 편은 공고에 이름만 적혀 있는 넷 — AUTOSAR · ISO 26262 · MISRA C · UDS — 을 면접에서 말할 수 있는 수준까지 내린다.


실제로 이렇게 물어본다

"AUTOSAR 들어봤어요? 왜 쓰는 건가요?"
"MCAL이 무슨 층인지 설명해 보세요."
"ASIL이 뭐고 어떻게 정해지나요?"
"워치독은 어디서 먹여야 합니까?"
"MISRA 규칙 중에 기억나는 것 하나만 말해 보세요. 왜 그런 규칙일까요?"
"CAN은 한 프레임이 8바이트인데, 진단 데이터 100바이트는 어떻게 보냅니까?"
"부트로더로 ECU 펌웨어를 올리는 순서를 아는 대로 말해 보세요."
"센서가 보낸 값이 중간에 깨졌는지 수신 쪽에서 어떻게 압니까?"

신입에게 깊이를 기대하지는 않는다. 다만 왜 존재하는 표준인지를 말하면 "찾아보고 온 사람"이 된다.


왜 자동차에만 이런 게 붙나

제약 세 가지가 원인이다.

공급망이 여러 겹    완성차 - 1차 협력사 - 2차 협력사가 각각 코드를 만든다
                    → 인터페이스를 표준으로 못 박지 않으면 통합이 불가능하다   → AUTOSAR

고장이 사람을 다치게 함   브레이크·조향에 개입하는 코드다
                    → "테스트했습니다" 로는 부족하고 증명이 필요하다          → ISO 26262 · A-SPICE

수명이 길고 회수가 비쌈   15~20년 굴러가고, 리콜하면 대당 정비소 비용이 든다
                    → 차 안에서 펌웨어를 고쳐 쓸 방법이 필요하다              → UDS · 부트로더

세 줄이 그대로 답변이 된다. 표준 이름을 나열하는 것보다 "이 문제 때문에 생겼다" 가 훨씬 잘 먹힌다.


AUTOSAR Classic — 하드웨어를 갈아 끼워도 앱은 그대로

계층 구조

다이어그램 로딩 중…

핵심은 MCAL 아래로만 하드웨어 의존성을 몰아넣는다는 것이다. MCU가 바뀌면 MCAL만 교체하고 위층은 그대로 쓴다. 부품사가 여러 완성차에 같은 기능을 납품할 수 있는 이유가 이것이다.

코드로 보면 이렇게 달라진다

/* 베어메탈 — 이 코드는 이 MCU에서만 돈다 */
PTD->PSOR = (1u << 15);          /* 레지스터 이름·비트 위치가 칩마다 다르다 */

/* AUTOSAR — 같은 동작, 이식 가능 */
Dio_WriteChannel(DioConf_DioChannel_LED_STATUS, STD_HIGH);

DioConf_DioChannel_LED_STATUS 는 코드가 아니라 설정에서 나온다. 설정은 .arxml(ARXML) 이라는 XML에 들어 있고, 툴(EB tresos, DaVinci Configurator 등)이 그것을 읽어 C 코드를 생성한다.

.arxml (설정)  ──[생성기]──►  Rte_*.c/h · Dio_Cfg.c · Os 설정 …  ──►  컴파일

그래서 AUTOSAR 프로젝트는 "코드를 짠다"보다 "설정하고 생성한다" 쪽에 가깝다. 신입이 처음 보면 낯선 지점이 정확히 여기다.

SWC와 RTE

기능 단위를 SWC(Software Component)라 부르고, SWC끼리는 직접 함수를 부르지 않는다. 반드시 RTE를 거친다.

/* 초음파 거리를 내보내는 쪽 */
Rte_Write_DistanceOut_value(distance_cm);

/* 그 값을 쓰는 쪽 — 상대가 같은 ECU에 있든 CAN 너머에 있든 코드가 같다 */
uint16 d;
Rte_Read_DistanceIn_value(&d);

같은 코드가 배치만 바꿔서 다른 ECU로 옮겨간다. 이 성질을 VFB(Virtual Function Bus)라고 부른다 — "일단 다 연결돼 있다고 치고 설계한 뒤, 나중에 어디에 놓을지 정한다".

대가

얻는 것치르는 것
MCU·공급사 교체가 가능설정 파일이 수천 줄, 툴이 유료
완성차와 인터페이스가 맞음빌드가 느리고 디버깅 경로가 길다
진단·통신·메모리 스택을 다시 안 짬얇은 기능 하나에도 층을 다 통과

"작은 센서 하나에 AUTOSAR를 쓰면 손해 아닌가요?" 는 좋은 꼬리질문이다. 실제로 단순 센서는 베어메탈이나 경량 스택으로 가고, ECU급 제어기에 AUTOSAR가 들어간다. 타이밍이 급한 부분은 표준 층을 우회하는 **CDD**로 뚫는다.

Adaptive AUTOSAR는 왜 따로 있나

ClassicAdaptive
대상MCU (Cortex-M/R)SoC + OS (Cortex-A, POSIX)
언어CC++
결합빌드 시점에 고정실행 중 서비스 탐색
통신CAN·LIN 신호이더넷 · SOME/IP 서비스
쓰임브레이크·센서·바디인지·주행판단·업데이트

한 차 안에 둘이 같이 있다. 초음파 센서 노드는 Classic 쪽, 카메라·라이다를 묶어 판단하는 컴퓨팅 유닛은 Adaptive 쪽이다. 공고에 RTOS와 Embedded Linux가 나란히 적히는 이유와 같은 구조다.


ISO 26262 — 위험의 크기가 개발 방식을 정한다

등급은 사고 시나리오에서 나온다

먼저 아이템(기능 단위)을 정하고, 고장 시나리오마다 셋을 매긴다.

S (Severity, 다치는 정도)        S0 상해 없음 … S3 생명 위협·치명적
E (Exposure, 그 상황의 빈도)     E0 사실상 없음 … E4 대부분의 주행 조건
C (Controllability, 회피 가능성)  C0 일반적으로 통제 … C3 통제 곤란·불가

세 값을 표에 넣으면 ASIL이 나온다. S3 행은 이렇다.

S3C1C2C3
E1QMQMA
E2QMAB
E3ABC
E4BCD

S가 낮아지면 결과가 한 칸씩 내려간다. QM은 "ISO 26262의 안전 활동은 더 하지 않고 일반 품질 관리로 충분" 이라는 뜻이지, 대충 만들어도 된다는 뜻이 아니다.

주차 보조로 감을 잡으면

시속 5km 주차 중 조향이 잘못 들어간다
  S  낮음~중간 (저속, 보행자 접촉 가능성은 있음)
  E  높음      (주차는 매일 한다)
  C  높음      (운전자가 브레이크를 밟아 멈출 수 있다) → C 값은 낮게 매겨짐

그래서 주차 보조는 보통 고속 주행 개입 기능(AEB·조향 개입)보다 낮은 등급에서 시작한다. 다만 "몇 등급이다"라고 단정해서 말하면 안 된다 — 등급은 회사가 정의한 아이템과 시나리오에 따라 달라진다. 면접에서는 "S·E·C로 정해진다"는 원리까지만 말하는 것이 안전하다.

코드에 실제로 남는 흔적

등급이 정해지면 그에 맞는 안전 메커니즘이 요구된다. 신입이 볼 수 있는 것들은 이렇다.

메커니즘무엇을 막나어떻게 생겼나
윈도우 워치독코드가 멈추거나 폭주너무 일찍 먹여도 리셋
ECC메모리 비트 뒤집힘1비트 정정·2비트 검출
CRC전송 중 깨짐프레임 끝 바이트
MPU비안전 코드가 안전 데이터 침범영역별 접근 권한
이중 저장RAM 변수 오염원본과 보수를 함께 저장
주기 자가진단센서·회로 고장부팅 시·주행 중 점검

워치독먹이는 위치가 곧 설계다.

/* 나쁜 예 — 타이머 인터럽트에서 무조건 먹인다.
   태스크가 전부 죽어도 워치독은 만족한다. 즉 아무것도 감시하지 못한다. */
void SysTick_Handler(void) { WDOG_feed(); }

/* 자동차에서 쓰는 형태 — 모든 감시 대상이 자기 차례를 돌았을 때만 먹인다 */
volatile uint8_t alive_mask;                 /* 각 태스크가 자기 비트를 세운다 */

void task_sensor(void)  { measure();  alive_mask |= BIT_SENSOR; }
void task_comm(void)    { send_can(); alive_mask |= BIT_COMM;   }

void supervisor_10ms(void) {
    if (alive_mask == (BIT_SENSOR | BIT_COMM)) {   /* 전원 생존 확인 */
        WDOG_feed();
        alive_mask = 0;
    }
    /* 하나라도 빠지면 먹이지 않는다 → 워치독이 리셋시킨다 */
}

여기에 FTTI(Fault Tolerant Time Interval, 고장이 사고로 번지기 전까지 허용되는 시간) 개념이 붙는다. 워치독 주기와 진단 주기는 FTTI보다 짧아야 한다. "왜 10ms인가"에 답이 있어야 한다는 뜻이다.

ASIL 분해

높은 등급 하나를 독립된 두 경로로 쪼개 각각 낮은 등급으로 낮추는 기법이다(ASIL D → B + B 등). 조건이 까다롭다 — 두 경로가 서로 간섭하지 않아야(freedom from interference) 하고, 같은 원인으로 함께 고장 나지 않아야 한다. MPU와 코어 분리가 여기서 근거로 쓰인다.


A-SPICE — "만들었다"가 아니라 "추적된다"

Automotive SPICE 의 줄임말이다. 프로세스 성숙도 평가 모델이고, 완성차가 부품사를 감사할 때 쓴다. 핵심은 V 모델과 추적성이다.

요구사항 ─────────────────────────────► 인수 시험
  └ 시스템 설계 ───────────────────► 시스템 통합 시험
       └ SW 요구사항 ──────────► SW 적격성 시험
            └ SW 설계 ─────► 통합 시험
                 └ 구현 ► 단위 시험

V 모델. 왼쪽 아래로 요구사항에서 설계·구현으로 내려가고, 오른쪽 위로 단위·통합·시스템 시험이 올라가며 같은 높이끼리 짝을 이룬다.
V-model — Herman Bruyninckx, CC BY-SA 3.0 (Wikimedia Commons)

왼쪽 항목마다 오른쪽 시험이 짝지어져 있고, 요구사항 하나 → 설계 → 코드 → 시험 결과가 링크로 이어져야 한다. Simulink 같은 모델 기반 도구가 자동차에서 사랑받는 이유도 성능이 아니라 이 추적성이다.


MISRA C — 규칙마다 사고가 하나씩 들어 있다

MISRA C:2012는 규칙 143개 + 지침 16개로 이뤄져 있다. MISRA C:2023은 그 뒤에 나온 개정(Amendment)과 정오표(Technical Corrigendum)를 하나로 합치고 C11/C18을 반영한 판이며, 2025년 3월에는 MISRA C:2025가 나왔다.

분류를 아는 것이 실무에서 더 중요하다.

Mandatory   반드시 지킨다. 예외 없음
Required    지키되, 못 지키면 정식 일탈(deviation) 문서를 남긴다
Advisory    권고. 어기면 사유를 적는다

"MISRA는 다 지켜야 하나요?" 의 답이 여기 있다 — Required는 문서화된 일탈로 넘어갈 수 있다. 규칙보다 그 절차가 핵심이다.

대표적인 것 몇 개와 이유.

지침·규칙내용
Dir 4.12동적 메모리 사용 금지단편화로 몇 시간 뒤 실패한다. 실패 시점이 예측 불가
Rule 21.3malloc/free 사용 금지위와 같은 이유, 함수 수준 금지
Rule 17.2재귀 금지스택 최대 깊이를 정적으로 계산할 수 없다
Rule 16.4switchdefault 필수값이 손상됐을 때 조용히 통과하는 경로를 막는다
Rule 14.4if 조건은 본질적으로 불리언if (ptr) 같은 축약이 타입 실수를 감춘다
Rule 15.5함수 출구는 하나 (권고)자원 해제 누락과 경로 폭증을 줄인다

특히 essential type model(10번대 규칙)은 C의 정수 승격이 만드는 함정을 겨냥한다.

uint8_t  a = 200;
uint8_t  b = 100;
uint8_t  c = a + b;        /* a+b는 int로 승격돼 300, 대입에서 잘려 44 */

if (a + b > 255) { ... }   /* 참이다. 사람 눈에는 uint8 연산처럼 보이는데 */

면접에서 "MISRA 규칙 아는 것" 을 물으면 번호를 외워 말하는 것보다 위 코드 한 조각을 보여주는 편이 낫다.


UDS와 ISO-TP — 8바이트 버스로 펌웨어를 올리는 법

먼저 크기 문제부터

CAN 표준 프레임 구조. SOF·11비트 ID·제어 필드 다음에 데이터 필드가 오고, CRC·ACK·EOF로 끝난다. 데이터 필드는 최대 8바이트다.
CAN-Bus frame in base format — CC BY-SA 3.0 (Wikimedia Commons)

그림에서 가운데 Data Field 가 실을 수 있는 전부다 — 최대 8바이트다(CAN FD는 64). 진단 응답은 그보다 길다. 그래서 ISO 15765-2(ISO-TP) 가 조각내고 다시 붙인다.

다이어그램 로딩 중…

프레임 종류는 넷이고, 첫 바이트 상위 니블로 구분한다.

종류상위 니블역할
Single Frame07바이트 이하면 한 방에
First Frame1전체 길이 선언 + 첫 조각
Consecutive Frame2순번(0~15 순환)과 함께 이어 보냄
Flow Control3수신 측이 BS(블록 크기)와 STmin(최소 간격)을 지정

STmin이 있는 이유가 면접에서 좋은 답이 된다 — 수신 측 버퍼와 처리 속도가 송신보다 느릴 수 있어서, 받는 쪽이 속도를 정한다.

UDS 서비스

요청은 SID(Service ID) 한 바이트로 시작한다. 성공하면 SID + 0x40 으로 답한다.

SID이름쓰임
0x10Diagnostic Session Control기본/확장/프로그래밍 세션 전환
0x11ECU Reset하드·소프트 리셋
0x14 / 0x19Clear / Read DTC고장 코드 지우기·읽기
0x22 / 0x2ERead / Write Data By IdentifierDID로 값 읽고 쓰기 (예: VIN 0xF190)
0x27Security Accessseed 요청 → key 응답
0x28Communication Control일반 통신 끄기 (플래시 중 방해 차단)
0x31Routine Control메모리 소거·자가진단 같은 루틴 실행
0x34 / 0x36 / 0x37Request Download / Transfer Data / Transfer Exit펌웨어 전송 3종
0x3ETester Present세션 유지용 하트비트

실패하면 7F <원래 SID> <NRC> 로 답한다. 실무에서 가장 자주 보는 NRC는 0x78 (요청은 맞게 받았고 처리 중) 이다 — 소거처럼 오래 걸리는 작업에서 진단기가 타임아웃 내지 않게 붙잡아 둔다.

부트로더 플래시 순서

0x10 02   프로그래밍 세션 진입
0x27      Security Access — seed 받고 key 계산해 응답
0x28      일반 통신 정지
0x31 01   루틴: 플래시 영역 소거        ← 여기서 0x78 이 여러 번 온다
0x34      Request Download (주소·크기 알림, ECU가 블록 최대 크기 회신)
0x36 …    Transfer Data 반복 (블록 순번 포함)
0x37      Transfer Exit
0x31 01   루틴: 무결성 검증 (체크섬·서명)
0x11 01   ECU Reset → 새 펌웨어로 부팅

"왜 0x27이 필요한가" 는 반드시 나오는 꼬리질문이다. 누구나 펌웨어를 덮어쓸 수 있으면 안 되기 때문이고, seed/key는 그 자체가 보안이라기보다 정품 진단기 확인에 가깝다(그래서 요즘은 인증서 기반 0x29 로 옮겨가는 중이다).


값이 깨진 것을 수신 측이 아는 법 — E2E

CRC는 버스 상의 비트 오류를 잡는다. 하지만 자동차에서 무서운 고장은 따로 있다.

프레임이 아예 안 온다        (송신 태스크가 죽었다)
같은 값이 계속 온다          (센서가 멈췄는데 마지막 값이 반복된다)
남의 값이 온다               (라우팅 실수로 다른 신호가 들어온다)

CRC만으로는 셋 다 못 잡는다. 그래서 페이로드 안에 CRC + 순번(alive counter) + 데이터 ID를 같이 넣는다. AUTOSAR가 이것을 E2E 보호(E2E Protection)라는 이름으로 표준화해 두었다.

typedef struct {
    uint8_t  crc;        /* 이 구조체 나머지에 대한 CRC */
    uint8_t  counter;    /* 매 송신 +1, 0..14 순환 */
    uint16_t distance_cm;
} __attribute__((packed)) UsSensorMsg;

/* 수신 측 */
if (crc8(&msg.counter, sizeof(msg) - 1) != msg.crc)  fault(E2E_CRC);
else if (msg.counter == prev_counter)                fault(E2E_REPEAT);   /* 멈춤 감지 */
else if (((prev_counter + 1) % 15) != msg.counter)   fault(E2E_LOST);     /* 유실 감지 */

"통신이 끊기면 어떻게 하나요?" 의 정답은 "마지막 값을 유지한다"가 아니라 "정해진 시간 안에 안전 상태로 간다" 이다. 주차 보조라면 기능을 중단하고 운전자에게 알린다.


함정과 오개념

AUTOSAR는 OS가 아니다. OS(Os 모듈)는 그 안의 한 부품일 뿐이고, 표준 전체는 소프트웨어 아키텍처 규약이다. "AUTOSAR 위에서 FreeRTOS가 돈다" 같은 문장은 거꾸로다.

ISO 26262는 인증서가 아니다. 제품이 "ISO 26262 인증"을 받는 게 아니라, 개발 프로세스와 근거 자료로 논증(safety case) 을 구성한다. MCU 데이터시트의 "ASIL B ready"는 그 논증에 쓸 재료가 준비돼 있다는 뜻이다.

QM = 아무거나 해도 됨이 아니다. 안전 요구가 없을 뿐 품질 프로세스는 그대로다.

MISRA는 컴파일 에러가 아니다. 정적 분석 도구가 검사하고, 위반은 일탈 문서로 처리될 수 있다. 도구를 안 돌리면 아무 일도 안 일어난다.

UDS는 CAN 전용이 아니다. ISO 14229는 프로토콜 계층이 분리돼 있어 CAN(ISO-TP), LIN, 이더넷(DoIP) 위에서 모두 돈다.

CAN FD를 써도 ISO-TP는 필요하다. 64바이트도 진단 데이터에는 부족하다.


꼬리질문 대비

"MCAL과 HAL의 차이가 뭔가요?"
  → HAL은 벤더가 편의로 제공하는 계층, MCAL은 AUTOSAR가 인터페이스를 규정한 계층.
    이름·인자·에러 코드가 표준에 고정돼 있어 벤더가 달라도 상위 코드가 안 바뀐다.

"ASIL D가 ASIL B보다 구체적으로 뭐가 더 필요합니까?"
  → 요구사항 추적·검증 방법·커버리지 기준이 강해지고,
    하드웨어 지표(단일점 고장률 등)와 독립성 요구가 붙는다.

"워치독을 인터럽트에서 먹이면 왜 안 되나요?"
  → 인터럽트만 살아 있어도 통과하므로 태스크 정지를 못 잡는다. 감시 대상이 사라진다.

"E2E counter를 8비트로 하면 되지 왜 15로 순환합니까?"
  → 프로파일이 정한 비트 수에 맞춘 것. 핵심은 폭이 아니라
    '유실·정지·중복'을 구분할 수 있는 규칙이 있느냐다.

"부트로더는 자기 자신을 지울 수 있나요?"
  → 안 된다. 부트로더 영역은 보호하고 애플리케이션 영역만 소거·기록한다.
    전원이 중간에 나가도 다시 플래시할 수 있어야 하기 때문이다.

흔한 오답

이렇게 말하면이렇게 고친다
"AUTOSAR는 자동차용 RTOS입니다""소프트웨어 아키텍처 표준이고, OS는 그 안의 한 모듈입니다"
"ASIL은 차량 등급입니다""기능별 위험도 등급입니다. 한 차 안에 QM부터 D까지 섞여 있습니다"
"MISRA는 코딩 스타일 가이드입니다""미정의 동작과 이식성 위험을 줄이는 안전 규칙입니다. 스타일이 아닙니다"
"UDS는 OBD-II와 같습니다""OBD-II는 배출가스 법규용 표준 진단, UDS는 제조사 진단·플래시까지 포함합니다"
"CRC 넣으면 통신 안전은 끝입니다""정지·유실·오배선은 CRC로 안 잡혀서 counter와 timeout이 함께 필요합니다"

Q&A 한 장 정리

질문30초 답변
AUTOSAR를 왜 쓰나여러 회사가 만든 코드를 통합하려고. MCAL 아래로 하드웨어 의존성을 몰아 이식성을 확보한다
RTE는 무엇인가SWC 사이 통신 중계자. 상대가 같은 ECU든 버스 너머든 호출 코드가 같아진다
ASIL은 어떻게 정하나사고 시나리오마다 S·E·C를 매겨 표에서 읽는다. S3·E4·C3이면 D
안전 메커니즘 예윈도우 워치독, ECC, CRC, MPU, 이중 저장, 주기 자가진단
MISRA 분류Mandatory / Required(일탈 문서 가능) / Advisory
ISO-TP가 필요한 이유CAN 프레임이 8바이트라서. FF·CF·FC로 나눠 보내고 수신 측이 속도를 정한다
플래시 순서프로그래밍 세션 → 보안 접근 → 소거 → 0x34/0x36/0x37 → 검증 → 리셋
값이 깨진 걸 아는 법CRC + alive counter + timeout. 셋이 각각 다른 고장을 잡는다

한 줄 요약

  • 자동차 표준은 공급망·안전·수명 세 제약에서 나왔다 — 순서대로 AUTOSAR · ISO 26262 · UDS
  • AUTOSAR Classic은 MCAL 아래로 하드웨어를 몰아넣는 계층 구조이고, 설정(.arxml)에서 코드가 생성된다
  • ISO 26262의 등급은 S·E·C로 정해지고, 그 결과가 워치독·ECC·MPU 같은 코드에 남는 흔적을 요구한다
  • MISRA는 스타일이 아니라 미정의 동작 차단 규칙이며, Required는 일탈 문서로 넘어갈 수 있다
  • CAN 8바이트 한계를 ISO-TP가 풀고, 그 위에서 UDS가 진단과 플래시를 수행한다
  • 통신 신뢰성은 CRC + counter + timeout 세 겹으로 만든다

다음 편S32K144 실습 에서 이 표준들을 실제 자동차 MCU 보드 위에서 만져 본다.

출처AUTOSAR Classic Platform · Renesas — AUTOSAR Layered Architecture · ISO 26262 ASIL 분류 (FuSi Engineering) · Jama Software — ASIL 결정표 · MISRA 공식 · MISRA C — 판본별 규칙 수 · UDS 서비스 정리 (I CAN Hack) · ISO 15765-2 (ISO-TP) — Linux Kernel 문서

면접 시나리오·트러블슈팅 — 종합·트레이드오프(베어메탈/RTOS)·저전력·STARS32K144 실습 — 쿡북(AN5413)·초음파 입력캡처·CAN·HardFault 추적