하드폴트 분석: 어느 줄에서 죽었나
하드폴트가 나면 스택에 저장된 PC와 LR, 그리고 폴트 상태 레지스터로 원인과 위치를 찾습니다.
흔한 원인
- 널 포인터나 해제된 메모리 접근
- 클럭을 켜지 않은 주변장치 레지스터 접근
- 스택 넘침
- 정렬되지 않은 접근, 0으로 나누기(설정에 따라)
- 잘못된 함수 포인터 호출 (Thumb 비트가 0인 주소)
찾는 방법
예외에 들어갈 때 CPU가 스택에 r0~r3, r12, lr, pc, xPSR을 저장합니다. 저장된 pc가 문제를 일으킨 명령어 주소입니다.
void HardFault_Handler(void) {
__asm volatile ("tst lr, #4\n ite eq\n mrseq r0, msp\n mrsne r0, psp\n b hf_c");
}
void hf_c(uint32_t *sp) {
volatile uint32_t pc = sp[6], lr = sp[5];
volatile uint32_t cfsr = SCB->CFSR, bfar = SCB->BFAR;
while (1); // 디버거로 pc, lr, cfsr 확인
}
폴트 레지스터
| 레지스터 | 알려 주는 것 |
|---|---|
| CFSR | 폴트 종류 (버스 / 메모리 / 사용 오류의 세부 비트) |
| BFAR | 버스 오류를 낸 데이터 주소 |
| MMFAR | 메모리 관리 오류 주소 |
pc 주소를 맵 파일이나 addr2line -e firmware.elf 0x080012AC로 소스 줄로 바꾸면 위치가 나옵니다. 현장 제품에서는 이 값들을 .noinit RAM이나 Flash에 기록해 두었다가 재부팅 후 읽어 오면 재현이 어려운 고장도 추적할 수 있습니다.