null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
워치독과 폴트 핸들링
#watchdog
#wdt
#endinit
#hardfault
#safety
@devpc
|
2026-04-03 23:46:47
|
GET /api/v1/nodes/237?nv=1
History:
v1 (2026-04-03) (Latest)
0
Views
2
Calls
# 워치독과 폴트 핸들링 ## 워치독의 원리 워치독(Watchdog Timer)은 소프트웨어가 정상적으로 동작하는 동안 **주기적으로 타이머를 초기화(서비스)**하도록 강제한다. 소프트웨어가 멈추거나 무한 루프에 빠지면 서비스가 중단되고, 타이머가 만료되면 MCU를 리셋한다. ``` 정상 동작: SW 실행 ─── 서비스(kick) ─── SW 실행 ─── 서비스(kick) ─── ... 타이머 초기화 타이머 초기화 비정상 (무한루프): SW 실행 ─── (서비스 없음) ─── 타이머 만료 ─── 리셋! ``` --- ## TC37x WDT 구조 TC37x는 **두 종류**의 워치독을 제공한다: ``` ┌─────────────────────────────────────────────────────┐ │ TC37x WDT │ │ │ │ CPU WDT (코어별, 3개) Safety WDT (1개) │ │ ├── CPU0_WDT SWDT │ │ ├── CPU1_WDT ├── 안전 임계 코드 │ │ └── CPU2_WDT └── ISO 26262 관련 │ │ │ │ ENDINIT 보호 하에 설정 변경 │ └─────────────────────────────────────────────────────┘ ``` --- ## ENDINIT 보호 메커니즘 TC37x에서 WDT 설정 레지스터와 중요 시스템 레지스터들은 **ENDINIT** 메커니즘으로 보호된다. 이 보호를 해제하려면 정해진 **비밀번호 시퀀스**를 써야 한다. 이는 소프트웨어 버그나 잘못된 접근으로 WDT 설정이 변경되는 것을 막는다. ``` ENDINIT 해제 시퀀스 (의사 코드): 1. WDT_CON0에 패스워드 포함한 ENDINIT=0 값 쓰기 2. 설정 레지스터 수정 3. WDT_CON0에 ENDINIT=1 복구 ENDINIT 보호된 레지스터: ├── WDT 설정 레지스터 ├── PLL 설정 ├── 클록 제어 └── 포트 입출력 설정 일부 ``` iLLD를 사용한 안전한 WDT 서비스: ```c #include "IfxScuWdt.h" /* WDT 서비스 (kick) — iLLD 방식 */ void wdt_service_cpu0(void) { uint16_t endinit_pw = IfxScuWdt_getCpuWatchdogPassword(); IfxScuWdt_serviceCpuWatchdog(endinit_pw); } /* Safety WDT 서비스 */ void wdt_service_safety(void) { uint16_t endinit_pw = IfxScuWdt_getSafetyWatchdogPassword(); IfxScuWdt_serviceSafetyWatchdog(endinit_pw); } ``` --- ## WDT 설계 패턴 ### 윈도우 워치독 단순 WDT는 너무 자주 서비스해도 통과된다. **윈도우 워치독**은 일정 시간 범위 안에서만 서비스를 허용한다: ``` │← 서비스 금지 구간 →│← 서비스 허용 구간 →│← 만료 →│ 0% 50% 100% ↑ 여기서만 kick 가능 ``` 서비스를 너무 일찍 하면 리셋, 너무 늦으면 리셋. 정확한 타이밍에 SW가 실행됨을 보장한다. ### 체크포인트 패턴 (Safety WDT 활용) 각 태스크가 체크포인트를 통과할 때마다 비트를 셋하고, Safety WDT 서비스 태스크가 모든 비트가 셋됐을 때만 서비스: ```c #define TASK_A_CHK (1U << 0) #define TASK_B_CHK (1U << 1) #define TASK_C_CHK (1U << 2) #define ALL_TASKS (TASK_A_CHK | TASK_B_CHK | TASK_C_CHK) volatile uint32_t checkpoint_flags = 0U; void task_a_checkpoint(void) { checkpoint_flags |= TASK_A_CHK; } void safety_wdt_task(void) { if ((checkpoint_flags & ALL_TASKS) == ALL_TASKS) { checkpoint_flags = 0U; wdt_service_safety(); /* 모두 살아있을 때만 서비스 */ } /* 하나라도 없으면 Safety WDT 만료 → 안전 상태로 진입 */ } ``` --- ## TriCore 폴트 처리 TriCore는 ARM의 HardFault와 달리 **Trap 시스템**을 사용한다. ``` TriCore Trap 클래스: 클래스 0: MMU 트랩 (가상 주소 변환 오류) 클래스 1: 내부 보호 트랩 (권한 위반, 정렬 오류) 클래스 2: 명령어 오류 트랩 (불법 명령, 미구현 명령) 클래스 3: 컨텍스트 관리 트랩 (CSA 언더플로/오버플로) 클래스 4: 시스템 버스 오류 트랩 (버스 오류, ECC 오류) 클래스 5: 어설션 트랩 (BISR, 소프트웨어 트랩) 클래스 6: 시스템 콜 트랩 (SYSCALL 명령) 클래스 7: NMI 트랩 (마스크 불가 인터럽트) ``` 폴트 핸들러 등록 및 디버깅 정보 수집: ```c /* 클래스 4 (버스 오류) 트랩 핸들러 */ __attribute__((interrupt_handler)) void trap_bus_error(uint32_t tin) { /* TIN: Trap Identification Number */ volatile uint32_t fault_addr; __asm__ volatile ("mfcr %0, $DSTR" : "=d"(fault_addr)); /* 폴트 정보 저장 (리셋 후에도 유지되는 영역에) */ fault_log.trap_class = 4U; fault_log.tin = tin; fault_log.address = fault_addr; fault_log.pc = get_return_address(); /* 안전 상태 진입 */ enter_safe_state(); while (1) {} } ``` > **ARM HardFault와의 비교** > ARM은 HardFault, BusFault, UsageFault 등으로 구분되며 > CFSR(Configurable Fault Status Register)로 원인을 파악한다. > TriCore의 Trap 클래스는 ARM의 Fault 분류와 개념적으로 유사하며, > TIN 값으로 세부 원인을 구분하는 방식도 비슷하다.
// COMMENTS
Newest First
ON THIS PAGE