본문 바로가기
AUTOSAR 심화

SWC와 Runnable이란? : AUTOSAR 소프트웨어의 기본 단위

by 버그없는토마토 2025. 12. 16.

SWC와 Runnable이란? : AUTOSAR 소프트웨어의 기본 단위

SWC와 Runnable이란?

소프트웨어 컴포넌트란?


[Autosar Series]

더보기

들어가며

안녕하세요 버그없는토마토입니다.

지난 세 편에서 AUTOSAR의 전체 구조를 배웠어요. ClassicAdaptive의 차이, ASW-RTE-BSW 계층까지.

기본적인 배경지식과 기초를 쌓았다고 생각하시면 편할거예요

이제 기둥을 세우는 과정을 하게 될거예요

 

AUTOSAR 소프트웨어가 정확히 '어떻게' 구성되는지 배워볼 차례예요.

이건 오토사 심화에서 다루는 내용들이기 때문에 다뤄본적이 없을 경우 생소해서 이해하기 쉽지 않을 수 있어요..

그래서 최대한 그림과 함께 설명하기 위해 노력했는데..

제 노력이 조금이나마 여러분들의 이해에 도움이 됐으면 좋겠습니다.


ASW (응용 소프트웨어)는 마치 빌딩처럼 여러 개의 작은 모듈들로 이루어져 있어요.

이런 모듈을 'SWC (Software Component)'라고 부르고, SWC 안에는 'Runnable'이라는 '실행 함수'가 있어요.

소프트웨어컴포넌트, 러너블에 관련한 내용은 오토사 플랫폼인 모빌진을 사용한다면 쉽게 접할 수 있는데요.
맨날 '컴포넌트, 컴포넌트', '러너블,러너블', 'RTE, RTE' 하지만 추상적인 개념말고 정확한 개념은 모르는 경우가 많죠
오늘 한번 자세히 한번 배워봅시다.

 

오늘 배울 내용의 큰 틀을 먼저 맛보기로 살펴볼게요:

자동차의 엔진 ECU:
├─ EngineControlSWC (엔진 제어 모듈)
│  ├─ EngineControl_Runnable (10ms마다 실행)
│  └─ FuelInjection_Runnable
├─ DiagnosticSWC (진단 모듈)
│  └─ DTC_Recording_Runnable (100ms마다 실행)
└─ CommunicationSWC (통신 모듈)
   └─ SignalSending_Runnable (50ms마다 실행)

이 글에서는 SWC와 Runnable의 정의, 역할, 상호작용을 명확하게 설명할게요.


🏗️ SWC: Software Component란?

SWC의 정의

SWC = 소프트웨어 컴포넌트

AUTOSAR에서 재사용 가능한 소프트웨어 기능 단위예요.

마치 레고 블록처럼, 여러 SWC를 조합해서 전체 애플리케이션을 만들어요.

SWC의 특징

1️⃣ 독립적이고 재사용 가능

한 번 만든 SWC를 여러 프로젝트에서 사용할 수 있어요.

예시: EngineControlSWC 만들기

BMW에서 만듦:
- BMW 5시리즈 엔진 ECU

이걸 다시 사용:
- BMW 7시리즈 엔진 ECU
  (거의 그대로 사용!)

- Mercedes C-Class 엔진 ECU
  (약간 조정하면 사용!)

- Audi A6 엔진 ECU
  (약간 조정하면 사용!)

→ 개발 비용 대폭 절감!

2️⃣ 입출력 인터페이스가 명확

SWC는 명확한 입력 (Require Port)출력 (Provide Port)을 가져요.

리시브포트로 불리죠 Pport Rport
EngineControlSWC:

입력 (Require Port):
├─ ThrottlePosition (스로틀 위치)
├─ EngineTemperature (엔진 온도)
└─ VehicleSpeed (차량 속도)

출력 (Provide Port):
├─ DesiredTorque (원하는 토크)
├─ FuelInjectionPulse (분사 신호)
└─ IgnitionTiming (점화 타이밍)

이렇게 명확하면, 다른 SWC와 쉽게 연결할 수 있어요!

3️⃣ 다른 SWC와 느슨한 결합

SWC는 직접 다른 SWC를 호출하지 않아요. RTE를 통해서만 통신해요.

❌ 잘못된 방식 (강한 결합):
EngineControlSWC가 직접
TransmissionControlSWC.CalculateGear() 호출
→ 변경 어려움!

✅올바른 방식 (느슨한 결합):
EngineControlSWC: "엔진 RPM = 3000"
    ↓ (RTE 통신)
TransmissionControlSWC: "RPM 받았어! 기어 선택해야겠다"

→ 수정 용이!

SWC의 구조

┌─────────────────────────────────┐
│    EngineControlSWC            │
├─────────────────────────────────┤
│                                 │
│  Require Ports (입력):           │
│  ├─ ThrottlePosition            │
│  ├─ EngineTemperature           │
│  └─ VehicleSpeed                │
│                                 │
├─────────────────────────────────┤
│                                 │
│  Runnables (실행 함수):          │
│  ├─ EngineControl_10ms          │
│  ├─ FuelInjection_10ms          │
│  └─ DiagnosticCheck_100ms       │
│                                 │
├─────────────────────────────────┤
│                                 │
│  Provide Ports (출력):           │
│  ├─ DesiredTorque               │
│  ├─ FuelInjectionPulse          │
│  └─ IgnitionTiming              │
│                                 │
└─────────────────────────────────┘

⚙️ Runnable: 실행 함수

Runnable의 정의

Runnable = SWC 내부의 실행 함수

정해진 시간에 실행되는 코드 블록이에요.

Runnable의 특징

1️⃣ 주기적 또는 이벤트 기반 실행

주기적 실행 (Periodic):
┌──────┐
│ 0ms  │ EngineControl_Runnable 시작
│      │ (일부 코드 실행...)
│      │
│ 10ms │ EngineControl_Runnable 시작 (다시!)
│      │
│ 20ms │ EngineControl_Runnable 시작 (또 다시!)
└──────┘

이벤트 기반 실행 (Event-Triggered):
센서에서 신호 들어옴 (예: 문 열림 감지)
    ↓
DoorOpeningDetected_Runnable 즉시 실행
    ↓
"문 열렸어! 경고음 울려!" 처리

2️⃣ Runnable의 실행 속성

각 Runnable은 다음을 가져요:

속성 설명 예시
이름 Runnable의 고유 이름 EngineControl_10ms
주기 얼마나 자주 실행되나? 10ms (매 10ms마다)
실행 시간 실행이 얼마나 오래 걸나? 5ms (WCET: Worst Case Execution Time)
우선순위 여러 Runnable 중 누가 먼저? 우선순위 10
트리거 뭐가 실행 신호일까? TimerInterrupt (타이머 인터럽트)

3️⃣ 원자성 (Atomicity): 중단 없이 실행

한 번 Runnable이 시작되면, 끝날 때까지 중단되지 않아요.

Time 0ms:
┌─────────────────────┐
│ EngineControl_10ms  │
│ 시작                │
│                     │
│ 3ms 소비            │
│                     │
│ 끝                  │ ← 중간에 다른 Runnable 못 끼어들어!
└─────────────────────┘

Time 10ms:
다음 EngineControl_10ms 시작 (다시!)

이걸 원자성(Atomicity)이라고 불러요. 데이터 일관성을 보장해요!

Runnable의 실행 사이클

시간:     0ms  10ms  20ms  30ms  40ms  50ms
         ─────────────────────────────────

10ms 주기: ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐
          Run1 Run1 Run1 Run1 Run1
                            ↑
100ms 주기: ┌──────────────────┐  ┌──────
          Run2            Run2
                   ↑

50ms 주기:      ┌──────────┐  ┌──────────
              Run3        Run3
                    ↑

각 Runnable이 정확한 시간에 실행돼요!


🔗 Port: SWC 간 통신

Port란?

Port = SWC 간 통신 채널

두 가지 종류가 있어요:

1️⃣ Require Port (필요 포트)

"다른 SWC의 데이터가 필요해!"

EngineControlSWC:
├─ Require: ThrottlePosition
│  (스로틀 SWC에서 위치 받음)
├─ Require: EngineTemperature
│  (온도 센서 SWC에서 온도 받음)
└─ Require: VehicleSpeed
   (속도 SWC에서 속도 받음)

구현:
uint8 throttle = Rte_Read_ThrottlePosition();
float temp = Rte_Read_EngineTemperature();

2️⃣ Provide Port (제공 포트)

"내 데이터를 다른 SWC에 제공할게!"

EngineControlSWC:
├─ Provide: DesiredTorque
│  (변속기 SWC가 받음)
├─ Provide: FuelInjectionPulse
│  (연료 분사 SWC가 받음)
└─ Provide: IgnitionTiming
   (점화 시스템 SWC가 받음)

구현:
float torque = CalculateTorque(rpm);
Rte_Write_DesiredTorque(torque);

Port의 커뮤니케이션

┌──────────────────────┐
│ ThrottleSensorSWC    │
│ ─────────────────── │
│ Provide:             │
│ └─ ThrottlePosition   │ (위치 제공)
└──────────┬───────────┘
           │
           │ (RTE 연결)
           ▼
┌──────────────────────┐
│ EngineControlSWC     │
│ ─────────────────── │
│ Require:             │
│ └─ ThrottlePosition   │ (위치 필요)
└──────────┬───────────┘
           │
           │ (RTE 연결)
           ▼
┌──────────────────────┐
│ TransmissionSWC      │
│ ─────────────────── │
│ Provide:             │
│ └─ DesiredGear       │
└──────────────────────┘

(실제로는 RTE가 모든 신호 라우팅 처리)

Port 타입 (Interface Type)

데이터 포트 (Data Port):

신호를 직접 읽고 쓰는 방식

uint8 rpm = Rte_Read_EngineRPM();
// 최신 값을 그대로 읽음

큐 포트 (Queue Port):

신호를 큐(대기열)에 넣는 방식

// 최근 3개의 신호를 모두 처리
while (Rte_Receive_Signal(&data)) {
    Process(data);
}

서버 포트 (Server Port) - Classic은 드물고, Adaptive가 많음:

함수처럼 호출하는 방식

result = Rte_Call_Service(param);
// "이 서비스를 해줘"라고 요청
// 결과를 받음

🚗 실제 자동차 ECU 구성 예시

말 그대로 예시입니다. 가상의 구현!!

예시 1: 현대 so나타 엔진 ECU

EngineECU:
│
├─ EngineControlSWC
│  ├─ Require Ports:
│  │  ├─ CrankshaftPosition (크랭크샤프트 위치, 센서)
│  │  ├─ ThrottlePosition (스로틀 위치, 센서)
│  │  ├─ AirIntakeFlow (흡입 공기량, 센서)
│  │  ├─ CoolantTemperature (냉각수 온도, 센서)
│  │  ├─ BrakeSignal (제동 신호, 제동 ECU)
│  │  └─ VehicleSpeed (차량 속도, ABS ECU)
│  │
│  ├─ Runnables:
│  │  ├─ EngineControl_10ms (10ms 주기)
│  │  │  → 엔진 RPM 읽기
│  │  │  → 분사량 계산
│  │  │  → 분사 명령 내보내기
│  │  │
│  │  └─ FuelInjection_10ms (10ms 주기)
│  │     → 분사 신호 생성
│  │
│  └─ Provide Ports:
│     ├─ EngineRPM (엔진 회전수 → 변속기 ECU)
│     ├─ EngineTorque (엔진 토크 → 변속기 ECU)
│     ├─ EngineLoad (엔진 부하 → OBD 시스템)
│     └─ EmissionLevel (배출가스 수준 → 촉매)
│
├─ DiagnosticSWC
│  ├─ Require Ports:
│  │  ├─ O2SensorVoltage (산소 센서 전압)
│  │  ├─ KnockSignal (노킹 신호)
│  │  └─ ThrottleSignal
│  │
│  ├─ Runnables:
│  │  └─ DiagnosticCheck_100ms (100ms 주기)
│  │     → 센서 고장 검사
│  │     → DTC 기록
│  │
│  └─ Provide Ports:
│     └─ DTC_Data (오류 코드 → 진단 시스템)
│
└─ CommunicationSWC
   ├─ Require Ports:
   │  ├─ EngineRPM (엔진 제어 SWC에서)
   │  ├─ EngineTorque
   │  └─ DTC_Data (진단 SWC에서)
   │
   ├─ Runnables:
   │  └─ CAN_MessagePrepare_10ms (10ms 주기)
   │     → CAN 메시지 생성
   │
   └─ Provide Ports:
      ├─ CAN_EngineData (CAN ID 0x100)
      └─ CAN_DiagnosticData (CAN ID 0x200)

예시 2: 기아 EV10 배터리 관리 시스템 (BMS)

BatteryECU:
│
├─ BatteryStateMonitoringSWC
│  ├─ Require Ports:
│  │  ├─ CellVoltages[96] (96개 셀 전압)
│  │  ├─ PackCurrent (배터리 충방전 전류)
│  │  ├─ CellTemperatures[12] (12개 온도 센서)
│  │  └─ HighVoltageContactorStatus (HV 접점 상태)
│  │
│  ├─ Runnables:
│  │  ├─ StateOfCharge_100ms (100ms 주기)
│  │  │  → SOC (충전 상태) 계산
│  │  │
│  │  ├─ StateOfHealth_1s (1000ms 주기)
│  │  │  → SOH (건강도) 계산
│  │  │
│  │  └─ SafetyCheck_50ms (50ms 주기)
│  │     → 과전압/과전류 감지
│  │
│  └─ Provide Ports:
│     ├─ SOC (충전 상태)
│     ├─ SOH (배터리 건강도)
│     ├─ BatteryReadySignal (충전 준비 신호)
│     └─ BatteryErrorCode (오류 코드)
│
├─ ThermalManagementSWC
│  ├─ Require Ports:
│  │  ├─ CellTemperatures[12]
│  │  ├─ MotorTorque (모터 토크)
│  │  └─ AmbientTemperature (외부 온도)
│  │
│  ├─ Runnables:
│  │  └─ CoolingControl_100ms (100ms 주기)
│  │     → 냉각액 펌프 제어
│  │     → 냉각 팬 속도 결정
│  │
│  └─ Provide Ports:
│     ├─ CoolingPumpCommand (펌프 명령)
│     └─ CoolingFanSpeed (팬 속도)
│
├─ CellBalancingSWC
│  ├─ Require Ports:
│  │  ├─ CellVoltages[96]
│  │  └─ BalancingStatus
│  │
│  ├─ Runnables:
│  │  └─ BalancingControl_500ms (500ms 주기)
│  │     → 각 셀의 전압 차이 계산
│  │     → 불균형 셀 밸런싱
│  │
│  └─ Provide Ports:
│     ├─ BalancingResistorControl[96] (각 셀별)
│     └─ BalancingStatus
│
└─ ChargerCommunicationSWC
   ├─ Require Ports:
   │  ├─ SOC
   │  ├─ BatteryReadySignal
   │  └─ ChargerInputVoltage (외부 충전기 전압)
   │
   ├─ Runnables:
   │  └─ ChargeProtocol_100ms (100ms 주기)
   │     → 충전 프로토콜 처리 (CCS, Type2)
   │     → 충전 레벨 결정
   │
   └─ Provide Ports:
      ├─ ChargePermission (충전 허용)
      └─ ChargeCurrentLimit (충전 전류 제한)

📋 SWC 설계 패턴

패턴 1: 센서 SWC

목적: 센서에서 데이터 읽기, 정제, 제공

SensorSWC:
├─ Require Ports: 없음 (센서가 입력)
├─ Runnables:
│  └─ SensorRead_10ms
│     → 아날로그 값 읽기 (ADC)
│     → 필터링 적용
│     → 범위 검사
└─ Provide Ports:
   └─ SensorValue (정제된 값)

예: TemperatureSensorSWC

패턴 2: 제어 SWC

목적: 입력받아서 계산, 제어 결정

ControlSWC:
├─ Require Ports: 여러 입력값들
├─ Runnables:
│  └─ Control_10ms
│     → PID 제어 알고리즘
│     → 상태 머신
│     → 의사결정
└─ Provide Ports: 제어 명령값들

예: EngineControlSWC, BrakeControlSWC

패턴 3: 액추에이터 SWC

목적: 제어 명령을 물리 신호로 변환

ActuatorSWC:
├─ Require Ports: 제어 명령값
├─ Runnables:
│  └─ ActuatorCommand_10ms
│     → PWM 신호 생성
│     → 릴레이 제어
│     → 모터 제어
└─ Provide Ports: 없음 (물리 출력)

예: FuelInjectionSWC, FanControlSWC

패턴 4: 진단 SWC

목적: 오류 감지 및 기록

DiagnosticSWC:
├─ Require Ports: 모니터링할 신호들
├─ Runnables:
│  └─ SelfTest_100ms
│     → 센서 범위 검사
│     → 신호 일관성 검사
│     → DTC 기록
└─ Provide Ports:
   └─ DTC_Data (오류 코드)

예: DiagnosticMonitorSWC

💡 SWC 설계할 때 고려사항

1️⃣ 단일 책임 원칙 (Single Responsibility)

❌ 나쁜 설계:
SuperControlSWC:
├─ 엔진 제어
├─ 변속 제어
├─ 제동 제어
├─ 진단
└─ 통신
(너무 복잡!)

✅ 좋은 설계:
EngineControlSWC (엔진만!)
TransmissionControlSWC (변속만!)
BrakeControlSWC (제동만!)
DiagnosticSWC (진단만!)
(각자 역할에 집중)

2️⃣ 인터페이스 명확성

좋은 Port 설계:
┌────────────────┐
│ TorqueLimitSWC │
├────────────────┤
│ Require:       │
│ └─ MotorTorque │ (명확한 이름)
│                │
│ Provide:       │
│ └─ TorqueLimit │
└────────────────┘

vs

나쁜 Port 설계:
├─ data1, data2, data3 (뭐야?)
├─ output_a, output_b, output_c
└─ signal_xyz (매우 모호!)

3️⃣ 재사용성

높은 재사용성:
- 하드웨어 독립적 (GPIO 주소 안 쓰기)
- 파라미터화 가능 (설정값으로 조정)
- 표준 인터페이스 (Port가 명확)

낮은 재사용성:
- 하드웨어 종속적 (특정 칩 가정)
- 고정값 사용 (수정 불가)
- 복잡한 인터페이스

정리: SWC와 Runnable 핵심 정보

항목 SWC Runnable
정의 소프트웨어 컴포넌트 SWC 내 실행 함수
역할 기능의 모듈화 주기적/이벤트 실행
특징 재사용 가능, Port로 통신 원자성, 타이밍 보장
상호작용 RTE를 통해 통신 RTE가 실행 시간 관리
예시 EngineControlSWC EngineControl_10ms

마치며

이제 SWC와 Runnable이 어떻게 작동하는지 명확해졌을까요?

지금까지는 취준생과 초급자를 위한 포스팅이었다면.. 이번부터는 초급자부터 실무자 까지로

난이도가 올라간 듯 느껴지죠?

직접 사용할 것이고 사용했던 내용일 거예요

 

다음 편에서는 이 SWC들이 실제로 어떻게 통신하는지 CAN 메시지가 어떻게 신호로 변환되는지, 신호 매핑은 뭔지...

다음 편에서는 "AUTOSAR 통신 시스템: CAN 버스, 신호, COM 모듈의 관계"를 주제로 해보겠습니다.

신호가 물리적 CAN 메시지로 어떻게 변환되는지, 구체적인 예시를 통해 설명해서 최대한 여러분이 이해하기 쉽도록

만들어 올게요...